-
Notifications
You must be signed in to change notification settings - Fork 79
Generate missing messages at runtime #1257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -90,6 +90,67 @@ let interfaceLoader = { | |||||||||
| return pkg; | ||||||||||
| }, | ||||||||||
|
|
||||||||||
| _searchAndGenerateInterface(packageName, type, messageName, filePath) { | ||||||||||
| // Check if it's a valid package | ||||||||||
| for (const pkgPath of generator.getInstalledPackagePaths()) { | ||||||||||
| // We are going to ignore the path ROS2 installed. | ||||||||||
| if (pkgPath.includes('ros2-linux')) { | ||||||||||
| continue; | ||||||||||
| } | ||||||||||
|
||||||||||
|
|
||||||||||
| // Recursively search for files named messageName.* under pkgPath/ | ||||||||||
| if (fs.existsSync(pkgPath)) { | ||||||||||
| // Recursive function to search for files | ||||||||||
| function searchForFile(dir) { | ||||||||||
| try { | ||||||||||
| const items = fs.readdirSync(dir, { withFileTypes: true }); | ||||||||||
| for (const item of items) { | ||||||||||
| const fullPath = path.join(dir, item.name); | ||||||||||
|
|
||||||||||
| if (item.isFile()) { | ||||||||||
| const baseName = path.parse(item.name).name; | ||||||||||
| // Check if the base filename matches messageName | ||||||||||
| if (baseName === messageName) { | ||||||||||
| return fullPath; | ||||||||||
| } | ||||||||||
| } else if (item.isDirectory()) { | ||||||||||
| // Recursively search subdirectories | ||||||||||
| const result = searchForFile(fullPath); | ||||||||||
| if (result) { | ||||||||||
| return result; | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } catch (err) { | ||||||||||
| // Skip directories we can't read | ||||||||||
| console.error('Error reading directory:', dir, err.message); | ||||||||||
|
||||||||||
| console.error('Error reading directory:', dir, err.message); | |
| console.error( | |
| `Failed to read directory during message discovery for package "${packageName}", type "${type}", message "${messageName}". Directory: ${dir}. Error: ${err.message}` | |
| ); |
Copilot
AI
Sep 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message lacks context about which package/interface failed to generate. Include packageName, type, and messageName in the error message for better debugging.
| console.error('Error in interface generation:', err); | |
| console.error(`Error in interface generation for package: ${packageName}, type: ${type}, message: ${messageName}:`, err); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,63 @@ | ||||||
| // Copyright (c) 2025, The Robot Web Tools Contributors | ||||||
| // | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
| // you may not use this file except in compliance with the License. | ||||||
| // You may obtain a copy of the License at | ||||||
| // | ||||||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||||||
| // | ||||||
| // Unless required by applicable law or agreed to in writing, software | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
| // See the License for the specific language governing permissions and | ||||||
| // limitations under the License. | ||||||
|
|
||||||
| const fse = require('fs-extra'); | ||||||
| const generateJSStructFromIDL = require('./idl_generator.js'); | ||||||
| const packages = require('./packages.js'); | ||||||
| const path = require('path'); | ||||||
| const idlConvertor = require('../rosidl_convertor/idl_convertor.js'); | ||||||
|
|
||||||
| const generatedRoot = path.join(__dirname, '../generated/'); | ||||||
| const idlPath = path.join(generatedRoot, 'share'); | ||||||
| const useIDL = !!process.argv.find((arg) => arg === '--idl'); | ||||||
|
|
||||||
| // Get target path from environment variable instead of workerData | ||||||
|
||||||
| // Get target path from environment variable instead of workerData | |
| // Get target path from the WORKER_TARGET_PATH environment variable |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| cmake_minimum_required(VERSION 3.8) | ||
| project(custom_msg_test) | ||
|
|
||
| if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") | ||
| add_compile_options(-Wall -Wextra -Wpedantic) | ||
| endif() | ||
|
|
||
| # find dependencies | ||
| find_package(ament_cmake REQUIRED) | ||
| find_package(std_msgs REQUIRED) | ||
| find_package(builtin_interfaces REQUIRED) | ||
| find_package(rosidl_default_generators REQUIRED) | ||
|
|
||
| # Generate interfaces | ||
| rosidl_generate_interfaces(${PROJECT_NAME} | ||
| "msg/Testing.msg" | ||
| DEPENDENCIES std_msgs builtin_interfaces | ||
| ) | ||
|
|
||
| if(BUILD_TESTING) | ||
| find_package(ament_lint_auto REQUIRED) | ||
| # the following line skips the linter which checks for copyrights | ||
| # comment the line when a copyright and license is added to all source files | ||
| set(ament_cmake_copyright_FOUND TRUE) | ||
| # the following line skips cpplint (only works in a git repo) | ||
| # comment the line when this package is in a git repo and when | ||
| # a copyright and license is added to all source files | ||
| set(ament_cmake_cpplint_FOUND TRUE) | ||
| ament_lint_auto_find_test_dependencies() | ||
| endif() | ||
|
|
||
| ament_package() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # Custom Message Test Package | ||
|
|
||
| This ROS2 package contains custom message definitions for testing rclnodejs runtime message generation capabilities. | ||
|
|
||
| ## Messages | ||
|
|
||
| ### Testing.msg | ||
|
|
||
| A test message that contains the position of a point in free space with additional data: | ||
|
|
||
| - `float64 x` - X coordinate | ||
| - `float64 y` - Y coordinate | ||
| - `float64 z` - Z coordinate | ||
| - `string data` - Additional string data | ||
|
|
||
| ## Usage | ||
|
|
||
| This package is used by the rclnodejs test suite to verify that custom messages can be generated and used at runtime. | ||
|
|
||
| ## Building | ||
|
|
||
| ```bash | ||
| # From the test directory | ||
| cd custom_msg_test | ||
| colcon build | ||
| source install/setup.bash | ||
| ``` | ||
|
|
||
| ## Testing | ||
|
|
||
| The message definitions in this package are used by `test-rosidl-message-generator.js` to verify runtime message generation functionality. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # This contains the position of a point in free space | ||
| float64 x | ||
| float64 y | ||
| float64 z | ||
|
Comment on lines
+2
to
+4
|
||
| string data | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| <?xml version="1.0"?> | ||
| <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> | ||
| <package format="3"> | ||
| <name>custom_msg_test</name> | ||
| <version>1.0.0</version> | ||
| <description>Custom message definitions for rclnodejs testing</description> | ||
| <maintainer email="[email protected]">Test Maintainer</maintainer> | ||
| <license>Apache-2.0</license> | ||
|
|
||
| <buildtool_depend>ament_cmake</buildtool_depend> | ||
|
|
||
| <depend>std_msgs</depend> | ||
| <depend>builtin_interfaces</depend> | ||
|
|
||
| <build_depend>rosidl_default_generators</build_depend> | ||
| <exec_depend>rosidl_default_runtime</exec_depend> | ||
|
|
||
| <member_of_group>rosidl_interface_packages</member_of_group> | ||
|
|
||
| <export> | ||
| <build_type>ament_cmake</build_type> | ||
| </export> | ||
| </package> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hardcoded 'ros2-linux' string check is a magic value that lacks explanation. This filtering logic should be documented or made configurable to explain why certain paths are excluded.