Skip to content

Several fixes on ros2 bridge and readme update#1253

Merged
haixuanTao merged 6 commits intodora-rs:mainfrom
drindr:fix-ros2-example
Dec 17, 2025
Merged

Several fixes on ros2 bridge and readme update#1253
haixuanTao merged 6 commits intodora-rs:mainfrom
drindr:fix-ros2-example

Conversation

@drindr
Copy link
Copy Markdown
Contributor

@drindr drindr commented Dec 8, 2025

  • Support boolean literal True and False according to the nav2_msgs.
  • Accept buildtool_depend and build_depend tags as the dependencies while parsing the ROS2 package.
  • Support transitive dependencies for ROS2 messages.
  • Ensure the ROS node always being killed correctly in the examples' run.rs.
  • Update the README file for the main ROS2 example of each language.
  • Remove the ros2-examples feature gate

Copilot AI review requested due to automatic review settings December 8, 2025 17:47
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements several fixes and improvements to the ROS2 bridge functionality:

  • Adds support for boolean literals True and False in ROS2 message parsing
  • Extends dependency parsing to include buildtool_depend and build_depend tags
  • Implements transitive dependency resolution for ROS2 messages using depth-first search
  • Ensures proper cleanup of ROS nodes in example run scripts
  • Updates documentation with clearer instructions and removes obsolete feature flags

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
libraries/extensions/ros2-bridge/msg-gen/src/parser/literal.rs Adds capitalized boolean literal support (True/False) for compatibility with nav2_msgs
libraries/extensions/ros2-bridge/msg-gen/src/parser/package.rs Implements transitive dependency resolution and adds support for additional dependency tags
libraries/extensions/ros2-bridge/Cargo.toml Removes ros2-examples feature flag and moves dependencies to dev-dependencies
examples/ros2-bridge/rust/turtle/run.rs Refactors cleanup logic to ensure ROS nodes are killed even if dataflow fails
examples/ros2-bridge/rust/topic-sub/run.rs Refactors cleanup logic to ensure ROS nodes are killed even if dataflow fails
examples/ros2-bridge/rust/topic-pub/run.rs Refactors cleanup logic to ensure ROS nodes are killed even if dataflow fails
examples/ros2-bridge/rust/service-server/run.rs Removes error handling from run() call (error is now silently ignored)
examples/ros2-bridge/rust/service-client/run.rs Refactors cleanup logic to ensure ROS nodes are killed even if dataflow fails
examples/ros2-bridge/python/turtle/run.rs Refactors cleanup logic to ensure ROS nodes are killed even if dataflow fails
examples/ros2-bridge/c++/turtle/run.rs Refactors cleanup logic to ensure ROS nodes are killed even if dataflow fails
examples/ros2-bridge/rust/turtle/README.md Updates documentation with generic ROS distribution placeholder and simplified run command
examples/ros2-bridge/python/turtle/README.md Updates documentation with generic ROS distribution placeholder and corrects file paths
examples/ros2-bridge/c++/turtle/README.md Reorganizes documentation with clearer structure and updated run instructions
.github/workflows/ci.yml Updates CI workflow to remove ros2-examples feature flag from cargo commands

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// flatten the dependencies
let dependencies = {
let mut flattened_dependencies = HashMap::<String, BTreeSet<String>>::new();
let mut finished_set: BTreeSet<String> = dependencies.keys().cloned().into_iter().collect();
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .into_iter() call is redundant here. The .cloned() iterator adapter already returns an iterator, so chaining .into_iter() after it has no effect.

Consider simplifying to:

let mut finished_set: BTreeSet<String> = dependencies.keys().cloned().collect();
Suggested change
let mut finished_set: BTreeSet<String> = dependencies.keys().cloned().into_iter().collect();
let mut finished_set: BTreeSet<String> = dependencies.keys().cloned().collect();

Copilot uses AI. Check for mistakes.
.get(&package.name)
.unwrap()
.iter()
.filter_map(|dep| map.get(dep).and_then(|pkg| Some(pkg.clone())))
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The and_then with Some is redundant here. When using filter_map, you can directly return the value from map.get(dep) since it already returns Option<&Package>. The .and_then(|pkg| Some(pkg.clone())) is equivalent to just .map(|pkg| pkg.clone()).

Consider simplifying to:

.filter_map(|dep| map.get(dep).map(|pkg| pkg.clone()))
Suggested change
.filter_map(|dep| map.get(dep).and_then(|pkg| Some(pkg.clone())))
.filter_map(|dep| map.get(dep).map(|pkg| pkg.clone()))

Copilot uses AI. Check for mistakes.
let (finish_tx, finish_rx) = mpsc::channel();
let dataflow_task = std::thread::spawn(move || {
run("dataflow.yml".to_string(), false).unwrap();
run("dataflow.yml".to_string(), false);
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value of the run function (which returns eyre::Result<()>) is being silently ignored. If the dataflow fails to run, this error will be lost and won't be propagated.

Consider handling the result:

let dataflow_task = std::thread::spawn(move || {
    let result = run("dataflow.yml".to_string(), false);
    finish_tx.send(());
    result
});

Then later, you could check the result with dataflow_task.join() if needed.

Copilot uses AI. Check for mistakes.
}

fn dfs_collect(
name: &String,
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter type name: &String is non-idiomatic. It's generally better to use &str instead of &String for function parameters as it's more flexible (accepts both &String and &str) and follows Rust best practices.

Consider changing to:

fn dfs_collect(
    name: &str,
    // ... rest of parameters

You'll need to update the call sites accordingly (e.g., use name.as_str() or &name when calling).

Copilot uses AI. Check for mistakes.
Comment on lines +148 to +158
let direct_deps: BTreeSet<String> = dependencies.get(name).unwrap().iter().cloned().collect();
for dep_name in &direct_deps {
let indirect_deps = dfs_collect(
&dep_name,
dependencies,
flattened_dependencies,
finished_set,
);
add_deps.extend(indirect_deps);
}
add_deps.extend(direct_deps);
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line creates an unnecessary intermediate BTreeSet by cloning all the dependency names. The dependencies.get(name).unwrap() already returns a &BTreeSet<String>, which can be iterated directly.

Consider simplifying to:

for dep_name in dependencies.get(name).unwrap() {

This avoids the allocation and cloning of all strings.

Suggested change
let direct_deps: BTreeSet<String> = dependencies.get(name).unwrap().iter().cloned().collect();
for dep_name in &direct_deps {
let indirect_deps = dfs_collect(
&dep_name,
dependencies,
flattened_dependencies,
finished_set,
);
add_deps.extend(indirect_deps);
}
add_deps.extend(direct_deps);
for dep_name in dependencies.get(name).unwrap() {
let indirect_deps = dfs_collect(
dep_name,
dependencies,
flattened_dependencies,
finished_set,
);
add_deps.extend(indirect_deps);
}
add_deps.extend(dependencies.get(name).unwrap().iter().cloned());

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +27
## Alternative(manual)
Not recommended, because manually build c++ is heavy job.
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several grammar and spelling issues in this section:

  1. "Alternative(manual)" should have a space: "Alternative (manual)"
  2. "manually build c++ is heavy job" should be "manually building C++ is a heavy job"
Suggested change
## Alternative(manual)
Not recommended, because manually build c++ is heavy job.
## Alternative (manual)
Not recommended, because manually building C++ is a heavy job.

Copilot uses AI. Check for mistakes.

then start DORA service client from another terminal
```
3. From terminal 3 in the folder of dora repository. Note the source command here is necessary as this allow ROS2 message types to be found and compile dynamically.
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar issue: "this allow" should be "this allows" (singular subject requires singular verb form).

Suggested change
3. From terminal 3 in the folder of dora repository. Note the source command here is necessary as this allow ROS2 message types to be found and compile dynamically.
3. From terminal 3 in the folder of dora repository. Note the source command here is necessary as this allows ROS2 message types to be found and compile dynamically.

Copilot uses AI. Check for mistakes.
@drindr drindr force-pushed the fix-ros2-example branch 3 times, most recently from f6a9e60 to bccee1f Compare December 9, 2025 09:39
Copy link
Copy Markdown
Collaborator

@haixuanTao haixuanTao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great overall!

Made some comment and agree with copilot review m

Some ros2 msg like the `robot_localization` depends `builtin_interface`
with the `builttool_depend`.

Some ros2 msg like the `slam_toolbox` use the transitive depenedency
through the `tf2_geometry_msgs`

Signed-off-by: drindr <dreamchancn@qq.com>
Signed-off-by: drindr <dreamchancn@qq.com>
The examples of ROS2 have been placed under the crate `dora-ros2-bridge`,
hence removing the `ros2-examples` feature-gate

Signed-off-by: drindr <dreamchancn@qq.com>
…r's function name

Signed-off-by: drindr <dreamchancn@qq.com>
@drindr
Copy link
Copy Markdown
Contributor Author

drindr commented Dec 12, 2025

This PR is updated. But I do not know why the CI is always timeout😭️. Should we configure the timeout with a longer timeout tolerance?

@phil-opp
Copy link
Copy Markdown
Collaborator

Should we configure the timeout with a longer timeout tolerance?

I don't think that this will help. Looks like it hangs for some reason:

image

(note the timestamps)

The command that hangs seems to be dora run examples/python-async/dataflow.yaml --uv

I just restarted the build to see whether it's reproducible.

cc @haixuanTao

@phil-opp
Copy link
Copy Markdown
Collaborator

Retrying seemed to "fix" it. Not sure what was causing this, we should look into it when we have time. But it seems to be unrelated to this PR.

@drindr
Copy link
Copy Markdown
Contributor Author

drindr commented Dec 12, 2025

The command that hangs seems to be dora run examples/python-async/dataflow.yaml --uv

event = await node.recv_async()

Maybe a timeout for the async waiting can solve it.

@phil-opp
Copy link
Copy Markdown
Collaborator

Maybe a timeout for the async waiting can solve it.

There should be periodic timer ticks. Once the input is closed, the recv_async function should return immediately with None. But for some reason the input seems to stay open, but no more events are sent...

@drindr
Copy link
Copy Markdown
Contributor Author

drindr commented Dec 17, 2025

@haixuanTao Could you review this PR again. Flaws you mentioned above have been solved.

@haixuanTao haixuanTao merged commit e3309a8 into dora-rs:main Dec 17, 2025
72 of 76 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants