generation of action message types

This commit is contained in:
Martin Dahl 2021-05-10 13:36:44 +02:00
parent c84bb67914
commit ebe9287d76
5 changed files with 96 additions and 19 deletions

View File

@ -32,7 +32,22 @@ fn main() {
for (prefix, msgs) in prefixes { for (prefix, msgs) in prefixes {
codegen.push_str(&format!(" pub mod {} {{\n", prefix)); codegen.push_str(&format!(" pub mod {} {{\n", prefix));
if prefix == &"srv" { if prefix == &"action" {
for msg in msgs {
codegen.push_str("#[allow(non_snake_case)]\n");
codegen.push_str(&format!(" pub mod {} {{\n", msg));
codegen.push_str(" use super::super::super::*;\n");
codegen.push_str(&msg_gen::generate_rust_action(module, prefix, msg));
for s in &["Goal", "Result", "Feedback"] {
let msgname = format!("{}_{}", msg, s);
codegen.push_str(&msg_gen::generate_rust_msg(module, prefix, &msgname));
println!("cargo:rustc-cfg=r2r__{}__{}__{}", module, prefix, msg);
}
codegen.push_str(" }\n");
}
} else if prefix == &"srv" {
for msg in msgs { for msg in msgs {
codegen.push_str("#[allow(non_snake_case)]\n"); codegen.push_str("#[allow(non_snake_case)]\n");
codegen.push_str(&format!(" pub mod {} {{\n", msg)); codegen.push_str(&format!(" pub mod {} {{\n", msg));
@ -47,12 +62,14 @@ fn main() {
} }
codegen.push_str(" }\n"); codegen.push_str(" }\n");
} }
} else { } else if prefix == &"msg" {
codegen.push_str(" use super::super::*;\n"); codegen.push_str(" use super::super::*;\n");
for msg in msgs { for msg in msgs {
codegen.push_str(&msg_gen::generate_rust_msg(module, prefix, msg)); codegen.push_str(&msg_gen::generate_rust_msg(module, prefix, msg));
println!("cargo:rustc-cfg=r2r__{}__{}__{}", module, prefix, msg); println!("cargo:rustc-cfg=r2r__{}__{}__{}", module, prefix, msg);
} }
} else {
panic!("unknown prefix type: {}", prefix);
} }
codegen.push_str(" }\n"); codegen.push_str(" }\n");

View File

@ -57,6 +57,18 @@ fn get_msgs_from_package(package: &Path) -> Vec<String> {
msgs.push(srv_name); msgs.push(srv_name);
} }
} }
if l.starts_with("action/") && (l.ends_with(".idl") || l.ends_with(".action")) {
if let Some(file_name_str) = file_name.to_str() {
let substr = if l.ends_with(".action") {
&l[7..l.len()-7]
} else {
&l[7..l.len()-4] // .idl
};
let action_name = format!("{}/action/{}", file_name_str, substr);
println!("found action: {}", action_name);
msgs.push(action_name);
}
}
}); });
} }
} }
@ -80,19 +92,6 @@ pub fn get_ros_msgs(paths: &[&Path]) -> Vec<String> {
msgs msgs
} }
#[test]
fn test_msg_list() {
let msgs = get_all_ros_msgs();
for m in &msgs {
println!("{}", m);
}
assert!(msgs.contains(&"std_msgs/msg/String".to_string()));
assert!(msgs.contains(&"builtin_interfaces/msg/Time".to_string()));
}
pub fn parse_msgs(msgs: &Vec<String>) -> Vec<RosMsg> { pub fn parse_msgs(msgs: &Vec<String>) -> Vec<RosMsg> {
let v: Vec<Vec<&str>> = msgs.iter().map(|l| l.split("/").into_iter().take(3).collect()).collect(); let v: Vec<Vec<&str>> = msgs.iter().map(|l| l.split("/").into_iter().take(3).collect()).collect();
let v: Vec<_> = v.iter().filter(|v|v.len() == 3). let v: Vec<_> = v.iter().filter(|v|v.len() == 3).

View File

@ -73,7 +73,14 @@ fn main() {
let val = &format!("unsafe {{ rosidl_typesupport_introspection_c__get_message_type_support_handle__{}__{}__{}_{}() }} as *const i32 as usize", &msg.module, &msg.prefix, &msg.name, s); let val = &format!("unsafe {{ rosidl_typesupport_introspection_c__get_message_type_support_handle__{}__{}__{}_{}() }} as *const i32 as usize", &msg.module, &msg.prefix, &msg.name, s);
introspecion_map.push_str(&format!("m.insert(\"{}\", {});\n", key, val)); introspecion_map.push_str(&format!("m.insert(\"{}\", {});\n", key, val));
} }
} else { } else if msg.prefix == "action" {
for s in &["Goal", "Result", "Feedback"] {
let key = &format!("{}__{}__{}_{}", &msg.module, &msg.prefix, &msg.name, s);
let val = &format!("unsafe {{ rosidl_typesupport_introspection_c__get_message_type_support_handle__{}__{}__{}_{}() }} as *const i32 as usize", &msg.module, &msg.prefix, &msg.name, s);
introspecion_map.push_str(&format!("m.insert(\"{}\", {});\n", key, val));
}
}
else {
let key = &format!("{}__{}__{}", &msg.module, &msg.prefix, &msg.name); let key = &format!("{}__{}__{}", &msg.module, &msg.prefix, &msg.name);
let val = &format!("unsafe {{ rosidl_typesupport_introspection_c__get_message_type_support_handle__{}__{}__{}() }} as *const i32 as usize", &msg.module, &msg.prefix, &msg.name); let val = &format!("unsafe {{ rosidl_typesupport_introspection_c__get_message_type_support_handle__{}__{}__{}() }} as *const i32 as usize", &msg.module, &msg.prefix, &msg.name);
introspecion_map.push_str(&format!("m.insert(\"{}\", {});\n", key, val)); introspecion_map.push_str(&format!("m.insert(\"{}\", {});\n", key, val));

View File

@ -119,6 +119,24 @@ pub fn generate_rust_service(module_: &str, prefix_: &str, name_: &str) -> Strin
", module_, prefix_, name_) ", module_, prefix_, name_)
} }
pub fn generate_rust_action(module_: &str, prefix_: &str, name_: &str) -> String {
format!(
"
pub struct Action();
impl WrappedActionTypeSupport for Action {{
type Goal = Goal;
type Result = Result;
type Feedback = Feedback;
fn get_ts() -> &'static rosidl_action_type_support_t {{
unsafe {{
&*rosidl_typesupport_c__get_action_type_support_handle__{}__{}__{}()
}}
}}
}}
", module_, prefix_, name_)
}
// TODO: this is a terrible hack :) // TODO: this is a terrible hack :)
pub fn generate_rust_msg(module_: &str, prefix_: &str, name_: &str) -> String { pub fn generate_rust_msg(module_: &str, prefix_: &str, name_: &str) -> String {
@ -133,9 +151,11 @@ pub fn generate_rust_msg(module_: &str, prefix_: &str, name_: &str) -> String {
assert_eq!(prefix, prefix_); assert_eq!(prefix, prefix_);
assert_eq!(name, name_); assert_eq!(name, name_);
if prefix == "srv" { if prefix == "srv" || prefix == "action" {
// for srv, the message name is both the service name and _Request or _Respone // for srv, the message name is both the service name and _Request or _Respone
// we only want to keep the last part. // we only want to keep the last part.
// same for actions with _Goal, _Result, _Feedback
// TODO: refactor...
let mut nn = name.splitn(2, "_"); let mut nn = name.splitn(2, "_");
let _mod_name = nn.next().expect(&format!("malformed service name {}", name)); let _mod_name = nn.next().expect(&format!("malformed service name {}", name));
let msg_name = nn.next().expect(&format!("malformed service name {}", name)); let msg_name = nn.next().expect(&format!("malformed service name {}", name));
@ -380,8 +400,8 @@ impl WrappedNativeMsgUntyped {
let mut lines = String::new(); let mut lines = String::new();
for msg in msgs { for msg in msgs {
// for now don't generate untyped services // for now don't generate untyped services or actions
if msg.prefix == "srv" { continue; } if msg.prefix == "srv" || msg.prefix == "action" { continue; }
let typename = format!("{}/{}/{}", msg.module, msg.prefix, msg.name); let typename = format!("{}/{}/{}", msg.module, msg.prefix, msg.name);
let rustname = format!("{}::{}::{}", msg.module, msg.prefix, msg.name); let rustname = format!("{}::{}::{}", msg.module, msg.prefix, msg.name);

View File

@ -38,6 +38,14 @@ pub trait WrappedServiceTypeSupport {
fn get_ts() -> &'static rosidl_service_type_support_t; fn get_ts() -> &'static rosidl_service_type_support_t;
} }
pub trait WrappedActionTypeSupport {
type Goal: WrappedTypesupport;
type Result: WrappedTypesupport;
type Feedback: WrappedTypesupport;
fn get_ts() -> &'static rosidl_action_type_support_t;
}
#[derive(Debug)] #[derive(Debug)]
pub struct WrappedNativeMsg<T> pub struct WrappedNativeMsg<T>
@ -1638,4 +1646,30 @@ mod tests {
println!("resp {:?}", resp2); println!("resp {:?}", resp2);
assert_eq!(resp, resp2); assert_eq!(resp, resp2);
} }
#[cfg(r2r__example_interfaces__action__Fibonacci)]
#[test]
fn test_action_msgs() {
use example_interfaces::action::Fibonacci;
let mut goal = Fibonacci::Goal::default();
goal.order = 5;
let gn = WrappedNativeMsg::<_>::from(&goal);
let goal2 = Fibonacci::Goal::from_native(&gn);
println!("goal2 {:?}", goal2);
assert_eq!(goal, goal2);
let mut res = Fibonacci::Result::default();
res.sequence = vec![1,2,3];
let rn = WrappedNativeMsg::<_>::from(&res);
let res2 = Fibonacci::Result::from_native(&rn);
println!("res2 {:?}", res2);
assert_eq!(res, res2);
let mut fb = Fibonacci::Feedback::default();
fb.sequence = vec![4,3,6];
let fbn = WrappedNativeMsg::<_>::from(&fb);
let fb2 = Fibonacci::Feedback::from_native(&fbn);
println!("feedback2 {:?}", fb2);
assert_eq!(fb, fb2);
}
} }