From 7baecea71df811cbb654e83ecf3de0656152e6e5 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Thu, 11 Jan 2024 17:39:45 +0100 Subject: [PATCH] Provide functions to create topics and publishers --- .../c++-ros2-dataflow/node-rust-api/main.cc | 3 + .../extensions/ros2-bridge/msg-gen/src/lib.rs | 6 +- .../ros2-bridge/msg-gen/src/types/message.rs | 55 +++++++++++++++---- .../ros2-bridge/msg-gen/src/types/package.rs | 3 +- 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/examples/c++-ros2-dataflow/node-rust-api/main.cc b/examples/c++-ros2-dataflow/node-rust-api/main.cc index aa498f90..d58f91a3 100644 --- a/examples/c++-ros2-dataflow/node-rust-api/main.cc +++ b/examples/c++-ros2-dataflow/node-rust-api/main.cc @@ -9,6 +9,9 @@ int main() std::cout << "HELLO FROM C++" << std::endl; auto ros2_context = init_ros2_context(); + auto node = ros2_context->new_node("/ros2_demo", "turtle_teleop"); + auto vel_topic = node->create_topic_geometry_msgs_Twist("/turtle1", "cmd_vel", 0); + auto vel_publisher = node->create_publisher(vel_topic, 0); geometry_msgs::Twist twist = { .linear = {.x = 1, .y = 0, .z = 0}, diff --git a/libraries/extensions/ros2-bridge/msg-gen/src/lib.rs b/libraries/extensions/ros2-bridge/msg-gen/src/lib.rs index 5fca7030..f7f3495c 100644 --- a/libraries/extensions/ros2-bridge/msg-gen/src/lib.rs +++ b/libraries/extensions/ros2-bridge/msg-gen/src/lib.rs @@ -29,13 +29,12 @@ where let mut message_topic_impls = Vec::new(); let mut aliases = Vec::new(); for package in &packages { - let package_name = Ident::new(&package.name, Span::call_site()); for message in &package.messages { - let (def, imp) = message.struct_token_stream(&package_name, create_cxx_bridge); + let (def, imp) = message.struct_token_stream(&package.name, create_cxx_bridge); shared_type_defs.push(def); message_struct_impls.push(imp); if create_cxx_bridge { - let (topic_def, topic_impl) = message.topic_def(&package_name); + let (topic_def, topic_impl) = message.topic_def(&package.name); message_topic_defs.push(topic_def); message_topic_impls.push(topic_impl); } @@ -52,7 +51,6 @@ where type Ros2Node; fn init_ros2_context() -> Result>; fn new_node(self: &Ros2Context, name_space: &str, base_name: &str) -> Result>; - #(#message_topic_defs)* } }, diff --git a/libraries/extensions/ros2-bridge/msg-gen/src/types/message.rs b/libraries/extensions/ros2-bridge/msg-gen/src/types/message.rs index 9f7fbb1c..4611386e 100644 --- a/libraries/extensions/ros2-bridge/msg-gen/src/types/message.rs +++ b/libraries/extensions/ros2-bridge/msg-gen/src/types/message.rs @@ -125,7 +125,7 @@ pub struct Message { impl Message { pub fn struct_token_stream( &self, - package_name: &Ident, + package_name: &str, gen_cxx_bridge: bool, ) -> (impl ToTokens, impl ToTokens) { let cxx_name = format_ident!("{}", self.name); @@ -176,27 +176,62 @@ impl Message { } } - pub fn topic_def(&self, package_name: &Ident) -> (impl ToTokens, impl ToTokens) { + pub fn topic_def(&self, package_name: &str) -> (impl ToTokens, impl ToTokens) { + if self.members.is_empty() { + return (quote! {}, quote! {}); + }; + let topic_name = format_ident!("Topic__{package_name}__{}", self.name); - let fn_name = format_ident!("new__Topic__{package_name}__{}", self.name); let cxx_topic_name = format_ident!("Topic_{}", self.name); - let cxx_fn_name = format!("create_{cxx_topic_name}"); + let create_topic = format_ident!("new__Topic__{package_name}__{}", self.name); + let cxx_create_topic = format!("create_topic_{package_name}_{}", self.name); + + let publisher_name = format_ident!("Publisher__{package_name}__{}", self.name); + let cxx_publisher_name = format_ident!("Publisher_{}", self.name); + let create_publisher = format_ident!("new__Publisher__{package_name}__{}", self.name); + let cxx_create_publisher = format_ident!("create_publisher"); + let struct_raw_name = format_ident!("{package_name}__{}", self.name); + let self_name = &self.name; let def = quote! { #[namespace = #package_name] #[cxx_name = #cxx_topic_name] type #topic_name; + #[cxx_name = #cxx_create_topic] + fn #create_topic(self: &Ros2Node, name_space: &str, base_name: &str, qos: u32) -> Result>; + #[namespace = #package_name] - #[cxx_name = #cxx_fn_name] - fn #fn_name() -> Box<#topic_name>; + #[cxx_name = #cxx_publisher_name] + type #publisher_name; + #[cxx_name = #cxx_create_publisher] + fn #create_publisher(self: &mut Ros2Node, topic: &Box<#topic_name>, qos: u32) -> Result>; }; let imp = quote! { #[allow(non_camel_case_types)] - pub struct #topic_name; - #[allow(non_snake_case)] - pub fn #fn_name() -> Box<#topic_name> { - Box::new(#topic_name) + pub struct #topic_name(rustdds::Topic); + + impl Ros2Node { + #[allow(non_snake_case)] + pub fn #create_topic(&self, name_space: &str, base_name: &str, qos: u32) -> eyre::Result> { + let name = ros2_client::Name::new(name_space, base_name).map_err(|e| eyre::eyre!(e))?; + let type_name = ros2_client::MessageTypeName::new(#package_name, #self_name); + let qos = Default::default(); // TODO + let topic = self.0.create_topic(&name, type_name, &qos)?; + Ok(Box::new(#topic_name(topic))) + } } + + #[allow(non_camel_case_types)] + pub struct #publisher_name(ros2_client::Subscription); + + impl Ros2Node { + #[allow(non_snake_case)] + pub fn #create_publisher(&mut self, topic: &Box<#topic_name>, qos: u32) -> eyre::Result> { + let subscription = self.0.create_subscription(&topic.0, None)?; // TODO + Ok(Box::new(#publisher_name(subscription))) + } + } + }; (def, imp) } diff --git a/libraries/extensions/ros2-bridge/msg-gen/src/types/package.rs b/libraries/extensions/ros2-bridge/msg-gen/src/types/package.rs index 1e6e6fc8..ab0ccb3c 100644 --- a/libraries/extensions/ros2-bridge/msg-gen/src/types/package.rs +++ b/libraries/extensions/ros2-bridge/msg-gen/src/types/package.rs @@ -27,7 +27,6 @@ impl Package { } pub fn message_structs(&self, gen_cxx_bridge: bool) -> (impl ToTokens, impl ToTokens) { - let package_name = Ident::new(&self.name, Span::call_site()); if self.messages.is_empty() { // empty msg (quote! {}, quote! {}) @@ -35,7 +34,7 @@ impl Package { let items = self .messages .iter() - .map(|v| v.struct_token_stream(&package_name, gen_cxx_bridge)); + .map(|v| v.struct_token_stream(&self.name, gen_cxx_bridge)); let defs = items.clone().map(|(def, _)| def); let impls = items.clone().map(|(_, im)| im); let def_tokens = quote! {