Skip to content

Commit c76651c

Browse files
committed
Default values for parameters
1 parent 3094ff8 commit c76651c

File tree

5 files changed

+218
-107
lines changed

5 files changed

+218
-107
lines changed

rclrs/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ pub use error::*;
213213
pub use executor::*;
214214
pub use logging::*;
215215
pub use node::*;
216+
pub use parameter::structured::{ParameterOptions, StructuredParameters, StructuredParametersMeta};
216217
pub use parameter::*;
217218
pub use publisher::*;
218219
pub use qos::*;

rclrs/src/parameter.rs

Lines changed: 2 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod override_map;
22
mod range;
33
mod service;
4+
pub mod structured;
45
mod value;
56

67
pub(crate) use override_map::*;
@@ -13,6 +14,7 @@ use crate::vendor::rcl_interfaces::msg::rmw::{ParameterType, ParameterValue as R
1314
use crate::{
1415
call_string_getter_with_rcl_node, rcl_bindings::*, Node, RclrsError, ENTITY_LIFECYCLE_MUTEX,
1516
};
17+
use std::default;
1618
use std::{
1719
collections::{btree_map::Entry, BTreeMap},
1820
fmt::Debug,
@@ -871,38 +873,6 @@ impl ParameterInterface {
871873
}
872874
}
873875

874-
pub trait StructuredParameters: Sized {
875-
fn declare_structured(
876-
node: &crate::NodeState,
877-
name: &str,
878-
) -> core::result::Result<Self, crate::DeclarationError>;
879-
}
880-
881-
impl<T: crate::ParameterVariant> StructuredParameters for crate::MandatoryParameter<T> {
882-
fn declare_structured(
883-
node: &crate::NodeState,
884-
name: &str,
885-
) -> core::result::Result<crate::MandatoryParameter<T>, crate::DeclarationError> {
886-
node.declare_parameter(name).mandatory()
887-
}
888-
}
889-
impl<T: crate::ParameterVariant> StructuredParameters for crate::OptionalParameter<T> {
890-
fn declare_structured(
891-
node: &crate::NodeState,
892-
name: &str,
893-
) -> core::result::Result<crate::OptionalParameter<T>, crate::DeclarationError> {
894-
node.declare_parameter(name).optional()
895-
}
896-
}
897-
impl<T: crate::ParameterVariant> StructuredParameters for crate::ReadOnlyParameter<T> {
898-
fn declare_structured(
899-
node: &crate::NodeState,
900-
name: &str,
901-
) -> core::result::Result<crate::ReadOnlyParameter<T>, crate::DeclarationError> {
902-
node.declare_parameter(name).read_only()
903-
}
904-
}
905-
906876
#[cfg(test)]
907877
mod tests {
908878
use super::*;
@@ -1442,66 +1412,4 @@ mod tests {
14421412
.optional()
14431413
.unwrap();
14441414
}
1445-
1446-
use crate as rclrs;
1447-
use rclrs_proc_macros::StructuredParameters;
1448-
1449-
#[derive(StructuredParameters, Debug)]
1450-
struct SimpleStructuredParameters {
1451-
_mandatory: MandatoryParameter<f64>,
1452-
_optional: OptionalParameter<f64>,
1453-
_readonly: ReadOnlyParameter<f64>,
1454-
}
1455-
1456-
#[test]
1457-
fn test_simple_structured_parameters() {
1458-
let args: Vec<String> = [
1459-
"test",
1460-
"--ros-args",
1461-
"-p",
1462-
"_mandatory:=1.0",
1463-
"-p",
1464-
"_optional:=1.0",
1465-
"-p",
1466-
"_readonly:=1.0",
1467-
]
1468-
.into_iter()
1469-
.map(str::to_string)
1470-
.collect();
1471-
1472-
let context = crate::Context::new(args, InitOptions::default()).unwrap();
1473-
let exec = context.create_basic_executor();
1474-
let node = exec.create_node(NodeOptions::new("test")).unwrap();
1475-
let _params = SimpleStructuredParameters::declare_structured(&node, "").unwrap();
1476-
}
1477-
1478-
#[derive(StructuredParameters, Debug)]
1479-
struct NestedStructuredParameters {
1480-
_simple: SimpleStructuredParameters,
1481-
_mandatory: MandatoryParameter<Arc<str>>,
1482-
}
1483-
1484-
#[test]
1485-
fn test_nested_structured_parameters() {
1486-
let args: Vec<String> = [
1487-
"test",
1488-
"--ros-args",
1489-
"-p",
1490-
"nested._simple._mandatory:=1.0",
1491-
"-p",
1492-
"nested._simple._optional:=1.0",
1493-
"-p",
1494-
"nested._simple._readonly:=1.0",
1495-
"-p",
1496-
"nested._mandatory:=foo",
1497-
]
1498-
.into_iter()
1499-
.map(str::to_string)
1500-
.collect();
1501-
1502-
let context = crate::Context::new(args, InitOptions::default()).unwrap();
1503-
let exec = context.create_basic_executor();
1504-
let node = exec.create_node(NodeOptions::new("test")).unwrap();
1505-
let _params = NestedStructuredParameters::declare_structured(&node, "nested").unwrap();
1506-
}
15071415
}

rclrs/src/parameter/structured.rs

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
use crate::NodeState;
2+
3+
pub enum DefaultForbidden {}
4+
5+
pub struct ParameterOptions<'a, 'b, T> {
6+
node: &'a crate::NodeState,
7+
name: &'b str,
8+
default: Option<T>,
9+
}
10+
pub trait StructuredParametersMeta<T>: Sized {
11+
fn declare_structured_(
12+
options: ParameterOptions<T>,
13+
) -> core::result::Result<Self, crate::DeclarationError>;
14+
}
15+
16+
pub trait StructuredParameters: Sized {
17+
fn declare_structured<T>(
18+
options: ParameterOptions<T>,
19+
) -> core::result::Result<Self, crate::DeclarationError>
20+
where
21+
Self: StructuredParametersMeta<T>,
22+
{
23+
Self::declare_structured_(options)
24+
}
25+
}
26+
impl<T: crate::ParameterVariant> StructuredParameters for crate::MandatoryParameter<T> {}
27+
impl<T: crate::ParameterVariant> StructuredParametersMeta<T> for crate::MandatoryParameter<T> {
28+
fn declare_structured_(
29+
options: ParameterOptions<T>,
30+
) -> core::result::Result<Self, crate::DeclarationError> {
31+
let builder = options.node.declare_parameter(options.name);
32+
let builder = match options.default {
33+
Some(default) => builder.default(default),
34+
None => builder,
35+
};
36+
builder.mandatory()
37+
}
38+
}
39+
impl<T: crate::ParameterVariant> StructuredParameters for crate::ReadOnlyParameter<T> {}
40+
impl<T: crate::ParameterVariant> StructuredParametersMeta<T> for crate::ReadOnlyParameter<T> {
41+
fn declare_structured_(
42+
options: ParameterOptions<T>,
43+
) -> core::result::Result<Self, crate::DeclarationError> {
44+
let builder = options.node.declare_parameter(options.name);
45+
let builder = match options.default {
46+
Some(default) => builder.default(default),
47+
None => builder,
48+
};
49+
builder.read_only()
50+
}
51+
}
52+
impl<T: crate::ParameterVariant> StructuredParameters for crate::OptionalParameter<T> {}
53+
impl<T: crate::ParameterVariant> StructuredParametersMeta<T> for crate::OptionalParameter<T> {
54+
fn declare_structured_(
55+
options: ParameterOptions<T>,
56+
) -> core::result::Result<Self, crate::DeclarationError> {
57+
let builder = options.node.declare_parameter(options.name);
58+
let builder = match options.default {
59+
Some(default) => builder.default(default),
60+
None => builder,
61+
};
62+
builder.optional()
63+
}
64+
}
65+
66+
impl NodeState {
67+
fn declare_parameters<T, T0>(
68+
&self,
69+
name: &str,
70+
) -> core::result::Result<T, crate::DeclarationError>
71+
where
72+
T: StructuredParameters + StructuredParametersMeta<T0>,
73+
{
74+
T::declare_structured(ParameterOptions {
75+
node: self,
76+
name: name,
77+
default: None,
78+
})
79+
}
80+
}
81+
82+
mod tests {
83+
use std::sync::Arc;
84+
85+
use crate as rclrs;
86+
use rclrs::parameter::structured::*;
87+
use rclrs::CreateBasicExecutor;
88+
use rclrs_proc_macros::StructuredParameters;
89+
90+
#[derive(StructuredParameters, Debug)]
91+
struct SimpleStructuredParameters {
92+
_mandatory: rclrs::MandatoryParameter<f64>,
93+
_optional: rclrs::OptionalParameter<f64>,
94+
_readonly: rclrs::ReadOnlyParameter<f64>,
95+
}
96+
97+
#[test]
98+
fn test_simple_structured_parameters() {
99+
let args: Vec<String> = [
100+
"test",
101+
"--ros-args",
102+
"-p",
103+
"_mandatory:=1.0",
104+
"-p",
105+
"_optional:=1.0",
106+
"-p",
107+
"_readonly:=1.0",
108+
]
109+
.into_iter()
110+
.map(str::to_string)
111+
.collect();
112+
113+
let context = crate::Context::new(args, rclrs::InitOptions::default()).unwrap();
114+
let exec = context.create_basic_executor();
115+
let node = exec.create_node(rclrs::NodeOptions::new("test")).unwrap();
116+
let _params: SimpleStructuredParameters = node.declare_parameters("").unwrap();
117+
println!("{:?}", _params);
118+
}
119+
120+
#[derive(StructuredParameters, Debug)]
121+
struct NestedStructuredParameters {
122+
_simple: SimpleStructuredParameters,
123+
_mandatory: rclrs::MandatoryParameter<Arc<str>>,
124+
}
125+
126+
#[test]
127+
fn test_nested_structured_parameters() {
128+
let args: Vec<String> = [
129+
"test",
130+
"--ros-args",
131+
"-p",
132+
"nested._simple._mandatory:=1.0",
133+
"-p",
134+
"nested._simple._optional:=1.0",
135+
"-p",
136+
"nested._simple._readonly:=1.0",
137+
"-p",
138+
"nested._mandatory:=foo",
139+
]
140+
.into_iter()
141+
.map(str::to_string)
142+
.collect();
143+
144+
let context = crate::Context::new(args, rclrs::InitOptions::default()).unwrap();
145+
let exec = context.create_basic_executor();
146+
let node = exec.create_node(rclrs::NodeOptions::new("test")).unwrap();
147+
let _params: NestedStructuredParameters = node.declare_parameters("nested").unwrap();
148+
println!("{:?}", _params);
149+
}
150+
151+
#[derive(Debug, StructuredParameters)]
152+
struct SimpleStructuredParametersWithDefaults {
153+
#[param(default = 42.0)]
154+
_mandatory: rclrs::MandatoryParameter<f64>,
155+
#[param(default = 42.0)]
156+
_optional: rclrs::OptionalParameter<f64>,
157+
#[param(default = Arc::from("test"))]
158+
_readonly: rclrs::ReadOnlyParameter<Arc<str>>,
159+
}
160+
161+
#[test]
162+
fn test_simple_structured_parameters_with_defaults() {
163+
let args: Vec<String> = ["test", "--ros-args"]
164+
.into_iter()
165+
.map(str::to_string)
166+
.collect();
167+
let context = crate::Context::new(args, rclrs::InitOptions::default()).unwrap();
168+
let exec = context.create_basic_executor();
169+
let node = exec.create_node(rclrs::NodeOptions::new("test")).unwrap();
170+
let _params: SimpleStructuredParametersWithDefaults = node.declare_parameters("").unwrap();
171+
println!("{:?}", _params);
172+
}
173+
}

rclrs_proc_macros/src/impl.rs

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
use std::default;
2+
13
use proc_macro2::TokenStream;
24
use quote::quote;
3-
use syn::DeriveInput;
5+
use syn::{Data, DeriveInput, Expr, Lit, Meta};
46

57
pub(crate) fn derive_struct_parameters(input: DeriveInput) -> syn::Result<TokenStream> {
68
let ident = input.ident;
@@ -21,6 +23,27 @@ pub(crate) fn derive_struct_parameters(input: DeriveInput) -> syn::Result<TokenS
2123
for f in fields {
2224
let ident = f.ident.as_ref().unwrap();
2325
let ident_str = syn::LitStr::new(&f.ident.as_ref().unwrap().to_string(), ident.span());
26+
27+
let mut default: Option<Expr> = None;
28+
29+
for attr in &f.attrs {
30+
if attr.path().is_ident("param") {
31+
attr.parse_nested_meta(|meta| {
32+
if meta.path.is_ident("default") {
33+
default = Some(meta.value()?.parse()?);
34+
Ok(())
35+
} else {
36+
syn::Result::Err(syn::Error::new_spanned(meta.path, "Unknown key."))
37+
}
38+
})?;
39+
}
40+
}
41+
42+
let default = match default {
43+
Some(expr) => quote! {Some(#expr)},
44+
None => quote! {None},
45+
};
46+
2447
let field_type = match &f.ty {
2548
syn::Type::Path(p) => {
2649
let mut p = p.path.clone();
@@ -32,36 +55,42 @@ pub(crate) fn derive_struct_parameters(input: DeriveInput) -> syn::Result<TokenS
3255
e => {
3356
return syn::Result::Err(syn::Error::new_spanned(
3457
e,
35-
"attribute can only be path type",
58+
"only PathType attributes are supported.",
3659
));
3760
}
3861
};
3962
let r = quote! {
4063
#ident : #field_type::declare_structured(
41-
node, &{match name {
42-
"" => #ident_str.to_string(),
43-
prefix => [prefix, ".", #ident_str].concat(),
64+
rclrs::parameter::structured::ParameterOptions {
65+
node: options.node,
66+
name: &{match options.name {
67+
"" => #ident_str.to_string(),
68+
prefix => [prefix, ".", #ident_str].concat(),
69+
}},
70+
default: #default,
4471
}
45-
})?,
72+
)?,
4673
};
4774
args.push(r);
4875
}
4976

5077
let result = quote!(
5178
impl #ident {
5279
const _ASSERT_PARAMETER: fn() = || {
53-
fn assert_parameter<T: rclrs::StructuredParameters>() {}
80+
fn assert_parameter<T: rclrs::parameter::structured::StructuredParameters>() {}
5481
#(
5582
assert_parameter::<#field_types>();
5683
)*
5784
};
58-
}
85+
}
86+
impl rclrs::parameter::structured::StructuredParametersMeta<rclrs::parameter::structured::DefaultForbidden> for #ident {
87+
fn declare_structured_(options: rclrs::parameter::structured::ParameterOptions<rclrs::parameter::structured::DefaultForbidden>)
88+
-> core::result::Result<Self, crate::DeclarationError> {
89+
core::result::Result::Ok(Self{ #(#args)*})
90+
}
5991

60-
impl rclrs::StructuredParameters for #ident {
61-
fn declare_structured(node: &rclrs::NodeState, name: &str) -> core::result::Result<Self, rclrs::DeclarationError> {
62-
core::result::Result::Ok(Self{ #(#args)*})
63-
}
6492
}
93+
impl rclrs::StructuredParameters for #ident {}
6594
);
6695
syn::Result::Ok(result)
6796
}

0 commit comments

Comments
 (0)