From 6e8b75483833f6cf7a54ccc00a0136657d5588ad Mon Sep 17 00:00:00 2001 From: Ryan Draves Date: Sat, 17 Apr 2021 23:13:44 -0400 Subject: [PATCH 1/4] start ROSCore for launch debugging if not running (ROS1) --- .../configuration/resolvers/ros1/launch.ts | 17 ++++++++++++++++- src/ros/common/unknown-ros.ts | 5 +++++ src/ros/ros.ts | 5 +++++ src/ros/ros1/ros1.ts | 4 ++++ src/ros/ros2/ros2.ts | 5 +++++ 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/debugger/configuration/resolvers/ros1/launch.ts b/src/debugger/configuration/resolvers/ros1/launch.ts index 7d5033bc..e92c35a3 100644 --- a/src/debugger/configuration/resolvers/ros1/launch.ts +++ b/src/debugger/configuration/resolvers/ros1/launch.ts @@ -15,6 +15,7 @@ import * as vscode from "vscode"; import * as extension from "../../../../extension"; import * as requests from "../../../requests"; import * as utils from "../../../utils"; +import { rosApi } from "../../../../ros/ros"; const promisifiedExec = util.promisify(child_process.exec); @@ -32,7 +33,21 @@ export class LaunchResolver implements vscode.DebugConfigurationProvider { if (!path.isAbsolute(config.target) || path.extname(config.target) !== ".launch") { throw new Error("Launch request requires an absolute path as target."); } - + + const delay = ms => new Promise(res => setTimeout(res, ms)); + + // Manage the status of the ROS core, starting one if not present + // The ROS core will continue to run until the VSCode window is closed + const core_active = rosApi.getCoreStatus(); + if (!(await core_active).valueOf()) { + rosApi.startCore(); + + // Wait for the core to start + while (!(await rosApi.getCoreStatus()).valueOf()) { + await delay(100); + } + } + const rosExecOptions: child_process.ExecOptions = { env: await extension.resolvedEnv(), }; diff --git a/src/ros/common/unknown-ros.ts b/src/ros/common/unknown-ros.ts index d3c54549..9c6adacb 100644 --- a/src/ros/common/unknown-ros.ts +++ b/src/ros/common/unknown-ros.ts @@ -52,6 +52,11 @@ export class UnknownROS implements ros.ROSApi { return; } + public getCoreStatus(): Promise { + console.error("Unknown ROS distro."); + return; + } + public rosdep() { console.error("Unknown ROS distro."); return; diff --git a/src/ros/ros.ts b/src/ros/ros.ts index 79c72242..aea637bf 100644 --- a/src/ros/ros.ts +++ b/src/ros/ros.ts @@ -56,6 +56,11 @@ export interface ROSApi { */ stopCore: () => void; + /** + * Get ROS Core status + */ + getCoreStatus: () => Promise; + /** * Run ROSDep */ diff --git a/src/ros/ros1/ros1.ts b/src/ros/ros1/ros1.ts index f8a66b41..b6b5fd45 100644 --- a/src/ros/ros1/ros1.ts +++ b/src/ros/ros1/ros1.ts @@ -140,6 +140,10 @@ export class ROS1 implements ros.ROSApi { ros_core.stopCore(this.context, this._getXmlRpcApi()); } + public getCoreStatus(): Promise { + return this._getXmlRpcApi().check(); + } + public activateCoreMonitor(): vscode.Disposable { if (typeof this.env.ROS_MASTER_URI === "undefined") { return null; diff --git a/src/ros/ros2/ros2.ts b/src/ros/ros2/ros2.ts index 7a374640..8bf8f25f 100644 --- a/src/ros/ros2/ros2.ts +++ b/src/ros/ros2/ros2.ts @@ -148,6 +148,11 @@ export class ROS2 implements ros.ROSApi { daemon.stopDaemon(); } + public getCoreStatus(): Promise { + // TODO: Core status checking not implemented for ROS2 + return; + } + public rosdep(): vscode.Terminal { const terminal = ros_utils.createTerminal(this.context); terminal.sendText(`rosdep install --from-paths src --ignore-src -r -y`); From cde9ff0289c74eae08bd192730a4c443b0b2d49f Mon Sep 17 00:00:00 2001 From: Ryan Draves Date: Sat, 17 Apr 2021 23:24:35 -0400 Subject: [PATCH 2/4] make launch debugging auto roscore start unique to ros1 --- .../configuration/resolvers/ros1/launch.ts | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/debugger/configuration/resolvers/ros1/launch.ts b/src/debugger/configuration/resolvers/ros1/launch.ts index e92c35a3..9d92af4f 100644 --- a/src/debugger/configuration/resolvers/ros1/launch.ts +++ b/src/debugger/configuration/resolvers/ros1/launch.ts @@ -16,6 +16,7 @@ import * as extension from "../../../../extension"; import * as requests from "../../../requests"; import * as utils from "../../../utils"; import { rosApi } from "../../../../ros/ros"; +import { env } from "../../../../extension"; const promisifiedExec = util.promisify(child_process.exec); @@ -36,17 +37,27 @@ export class LaunchResolver implements vscode.DebugConfigurationProvider { const delay = ms => new Promise(res => setTimeout(res, ms)); - // Manage the status of the ROS core, starting one if not present - // The ROS core will continue to run until the VSCode window is closed - const core_active = rosApi.getCoreStatus(); - if (!(await core_active).valueOf()) { - rosApi.startCore(); - - // Wait for the core to start - while (!(await rosApi.getCoreStatus()).valueOf()) { - await delay(100); + switch(env.ROS_VERSION.trim()) { + case "1": { + // Manage the status of the ROS core, starting one if not present + // The ROS core will continue to run until the VSCode window is closed + const core_active = rosApi.getCoreStatus(); + if (!(await core_active).valueOf()) { + rosApi.startCore(); + + // Wait for the core to start + while (!(await rosApi.getCoreStatus()).valueOf()) { + await delay(100); + } + } + break; + } + case "2": { + // TODO, support starting the ROS2 daemon automatically + break; } } + const rosExecOptions: child_process.ExecOptions = { env: await extension.resolvedEnv(), From ab894163874f0aba03ff6e9348fb5e7e76e10fbc Mon Sep 17 00:00:00 2001 From: Ryan Draves Date: Sun, 18 Apr 2021 22:47:44 -0400 Subject: [PATCH 3/4] added timeout to waiting for ROSCore to start --- .../configuration/resolvers/ros1/launch.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/debugger/configuration/resolvers/ros1/launch.ts b/src/debugger/configuration/resolvers/ros1/launch.ts index 9d92af4f..e7c42255 100644 --- a/src/debugger/configuration/resolvers/ros1/launch.ts +++ b/src/debugger/configuration/resolvers/ros1/launch.ts @@ -37,7 +37,7 @@ export class LaunchResolver implements vscode.DebugConfigurationProvider { const delay = ms => new Promise(res => setTimeout(res, ms)); - switch(env.ROS_VERSION.trim()) { + switch (env.ROS_VERSION.trim()) { case "1": { // Manage the status of the ROS core, starting one if not present // The ROS core will continue to run until the VSCode window is closed @@ -45,9 +45,16 @@ export class LaunchResolver implements vscode.DebugConfigurationProvider { if (!(await core_active).valueOf()) { rosApi.startCore(); - // Wait for the core to start - while (!(await rosApi.getCoreStatus()).valueOf()) { - await delay(100); + // Wait for the core to start up to a timeout + const timeout_ms: number = 3000; + const interval_ms: number = 100; + let attempts: number = 0; + while (!(await rosApi.getCoreStatus()).valueOf() && attempts * interval_ms < timeout_ms) { + attempts += 1; + await delay(interval_ms); + } + if (attempts * interval_ms >= timeout_ms) { + throw (new Error('Timed out waiting for ROSCore to start. Start ROSCore manually to avoid this error.')); } } break; From e490def7c998fed0ebac079d2071ccf2f5dd9e10 Mon Sep 17 00:00:00 2001 From: Ryan Draves Date: Sun, 18 Apr 2021 22:58:00 -0400 Subject: [PATCH 4/4] reference issue related to TODOs --- src/debugger/configuration/resolvers/ros1/launch.ts | 2 +- src/ros/ros2/ros2.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debugger/configuration/resolvers/ros1/launch.ts b/src/debugger/configuration/resolvers/ros1/launch.ts index e7c42255..bb757763 100644 --- a/src/debugger/configuration/resolvers/ros1/launch.ts +++ b/src/debugger/configuration/resolvers/ros1/launch.ts @@ -60,7 +60,7 @@ export class LaunchResolver implements vscode.DebugConfigurationProvider { break; } case "2": { - // TODO, support starting the ROS2 daemon automatically + // TODO(#431), support starting the ROS2 daemon automatically break; } } diff --git a/src/ros/ros2/ros2.ts b/src/ros/ros2/ros2.ts index 8bf8f25f..c3704c75 100644 --- a/src/ros/ros2/ros2.ts +++ b/src/ros/ros2/ros2.ts @@ -149,7 +149,7 @@ export class ROS2 implements ros.ROSApi { } public getCoreStatus(): Promise { - // TODO: Core status checking not implemented for ROS2 + // TODO(#431): Core status checking not implemented for ROS2 return; }