Skip to content
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

Add methods related to node options to NodeBuilder #186

Merged
merged 26 commits into from
Jun 10, 2022
Merged
Changes from 3 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
85e7fea
Add methods related to node options to NodeBuilder
Soya-Onishi May 31, 2022
b04b17a
Format comment and move line to put near from related ones
Soya-Onishi Jun 1, 2022
a6ce30f
Remove domain_id because of erased field from galactic
Soya-Onishi Jun 2, 2022
a343aba
Fix SAFETY comments
Soya-Onishi Jun 2, 2022
e11f01e
Fix SAFETY docs for rcl_parse_arguments
Soya-Onishi Jun 2, 2022
3785db0
Separate procedure related to node_options in build()
Soya-Onishi Jun 2, 2022
d9416dd
Replace docs about arguments method
Soya-Onishi Jun 3, 2022
35cce29
Replace docs about use_global_arguments method
Soya-Onishi Jun 3, 2022
b5323a3
Add Drop impls
Soya-Onishi Jun 3, 2022
8090e80
merge from upstream
Soya-Onishi Jun 3, 2022
58d02fa
Add reference for details about command line arguments
Soya-Onishi Jun 3, 2022
612d7d5
remove wasted line
Soya-Onishi Jun 3, 2022
c2d9049
Add more detailed comments for enable_rosout method
Soya-Onishi Jun 3, 2022
bb09962
Add null check to prevent from calling post process twice
Soya-Onishi Jun 4, 2022
115ad6f
merge upstream
Soya-Onishi Jun 4, 2022
804bbb2
Fix valid string statements
Soya-Onishi Jun 4, 2022
1d46963
Exclude context lock from unsafe block
Soya-Onishi Jun 4, 2022
aded175
merge from upstream
Soya-Onishi Jun 9, 2022
39ca296
Remove Drop for rcl_arguments_t
Soya-Onishi Jun 9, 2022
82076ad
Merge branch 'master' into node_options
Soya-Onishi Jun 9, 2022
cc893ca
Add statement about rcl_arguments_t fininalization
Soya-Onishi Jun 9, 2022
fe5d05c
Merge branch 'node_options' of github.com:Soya-Onishi/ros2_rust into …
Soya-Onishi Jun 9, 2022
aad27b4
Fix comments
Soya-Onishi Jun 9, 2022
523ec5b
Add failsafe code like NulError checker in build
Soya-Onishi Jun 9, 2022
33e65d0
Fix to deal with erroneous case of cstring cast
Soya-Onishi Jun 10, 2022
7427701
Remove outdated safety comment
nnmm Jun 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 110 additions & 4 deletions rclrs/src/node/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ use std::sync::Arc;
///
/// The default values for optional fields are:
/// - `namespace: "/"`
/// - `domain_id: ROS_DOMAIN_ID`
/// - `use_global_arguments: true`
/// - `arguments: []`
/// - `enable_rosout`: true`
///
/// # Example
/// ```
Expand Down Expand Up @@ -40,6 +44,9 @@ pub struct NodeBuilder {
context: Arc<Mutex<rcl_context_t>>,
name: String,
namespace: String,
use_global_arguments: bool,
arguments: Vec<String>,
enable_rosout: bool,
}

impl NodeBuilder {
Expand Down Expand Up @@ -84,6 +91,9 @@ impl NodeBuilder {
context: context.handle.clone(),
name: name.to_string(),
namespace: "/".to_string(),
use_global_arguments: true,
arguments: vec![],
enable_rosout: true,
}
}

Expand Down Expand Up @@ -142,28 +152,124 @@ impl NodeBuilder {
self
}

/// Sets flag for using global arguments.
/// If false then only use arguments passed to this builder,
/// otherwise use global arguments also.
///
/// # Example
/// ```
/// # use rclrs::{Context, Node, NodeBuilder, RclrsError};
/// let args = ["--ros-args", "--remap", "my_node:__node:=your_node"]
/// .iter()
/// .map(|s| s.to_string())
/// .collect::<Vec<_>>();
/// let context = Context::new(args)?;
/// // Use global arguments
/// let node = context
/// .create_node_builder("my_node")
/// .use_global_arguments(true)
/// .build()?;
/// assert_eq!(node.name(), "your_node");
///
/// // Not use global arguments
/// let node = context
/// .create_node_builder("my_node")
/// .use_global_arguments(false)
/// .build()?;
/// assert_eq!(node.name(), "my_node");
/// # Ok::<(), RclrsError>(())
pub fn use_global_arguments(mut self, enable: bool) -> Self {
self.use_global_arguments = enable;
self
}

/// Sets node specific command line arguments.
///
/// Command line arguments can mix ROS specific and not specific arguments.
/// ROS specific arguments are wrapped between `--ros-args` and `--`.
/// Note that `--ros-args` followed by only ROS specific arguments is valid pattern.
///
/// below arguments examples are valid:
/// --ros-args -r from:=to -- user_arg0 user_arg1
/// --ros-args -p name:=value
///
/// # Example
/// ```
/// # use rclrs::{Context, Node, NodeBuilder, RclrsError};
/// let context = Context::new([])?;
/// let node_args = ["--ros-args", "--remap", "my_node:__node:=your_node"]
/// .iter()
/// .map(|s| s.to_string())
/// .collect::<Vec<_>>();
/// let node = context
/// .create_node_builder("my_node")
/// .arguments(node_args)
/// .build()?;
/// assert_eq!(node.name(), "your_node");
/// # Ok::<(), RclrsError>(())
/// ```
pub fn arguments(mut self, arguments: impl IntoIterator<Item = String>) -> Self {
self.arguments = arguments.into_iter().collect();
self
}

/// Enables rosout.
/// If false, rosout logging is disabled.
pub fn enable_rosout(mut self, enable: bool) -> Self {
self.enable_rosout = enable;
self
}

/// Builds the node instance.
///
/// Node name and namespace validation is performed in this method.
///
/// For example usage, see the [`NodeBuilder`][1] docs.
///
/// # Panics
/// When the node name or namespace contain null bytes.
/// If any of below conditions are filled, panic occurs
/// - node name contains null byte
/// - namespace contains null byte
/// - any of node argument strings contain null byte.
///
/// [1]: crate::NodeBuilder
pub fn build(&self) -> Result<Node, RclrsError> {
let node_name = CString::new(self.name.as_str()).unwrap();
let node_namespace = CString::new(self.namespace.as_str()).unwrap();

// SAFETY: No preconditions for this function.
let mut node_handle = unsafe { rcl_get_zero_initialized_node() };
let mut node_options = unsafe { rcl_node_get_default_options() };

let cstr_args = self
.arguments
.iter()
.map(|s| CString::new(s.as_str()).unwrap())
.collect::<Vec<_>>();
let cstr_arg_ptrs = cstr_args.iter().map(|s| s.as_ptr()).collect::<Vec<_>>();
// SAFETY: No preconditions for this function.
let mut arguments = unsafe { rcl_get_zero_initialized_arguments() };
unsafe {
// SAFETY: No preconditions for this function.
let context_handle = &mut *self.context.lock();
rcl_parse_arguments(
cstr_arg_ptrs.len() as i32,
cstr_arg_ptrs.as_ptr(),
rcutils_get_default_allocator(),
&mut arguments,
)
}
.ok()?;

node_options.arguments = arguments;
node_options.use_global_arguments = self.use_global_arguments;
node_options.enable_rosout = self.enable_rosout;
// SAFETY: No preconditions for this function.
node_options.allocator = unsafe { rcutils_get_default_allocator() };

// SAFETY: No preconditions for this function.
let mut node_handle = unsafe { rcl_get_zero_initialized_node() };
unsafe {
// SAFETY: No preconditions for this function.
let node_options = rcl_node_get_default_options();
let context_handle = &mut *self.context.lock();

// SAFETY: The node handle is zero-initialized as expected by this function.
// The strings and node options are copied by this function, so we don't need
Expand Down