1
- use crate :: error:: { RclReturnCode , ToResult } ;
2
- use crate :: qos:: QoSProfile ;
3
- use crate :: rcl_bindings:: * ;
4
- use crate :: Context ;
5
-
6
1
mod publisher;
7
2
mod subscription;
8
3
pub use self :: publisher:: * ;
9
4
pub use self :: subscription:: * ;
10
5
6
+ use crate :: rcl_bindings:: * ;
7
+ use crate :: { Context , QoSProfile , RclReturnCode , ToResult } ;
11
8
use std:: ffi:: { CStr , CString } ;
9
+
10
+ use std:: cmp:: PartialEq ;
11
+ use std:: fmt;
12
12
use std:: sync:: { Arc , Weak } ;
13
13
use std:: vec:: Vec ;
14
14
@@ -40,8 +40,26 @@ pub struct Node {
40
40
pub ( crate ) subscriptions : Vec < Weak < dyn SubscriptionBase > > ,
41
41
}
42
42
43
+ impl Eq for Node { }
44
+
45
+ impl PartialEq for Node {
46
+ fn eq ( & self , other : & Self ) -> bool {
47
+ Arc :: ptr_eq ( & self . handle , & other. handle )
48
+ }
49
+ }
50
+
51
+ impl fmt:: Debug for Node {
52
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> Result < ( ) , fmt:: Error > {
53
+ f. debug_struct ( "Node" )
54
+ . field ( "fully_qualified_name" , & self . fully_qualified_name ( ) )
55
+ . finish ( )
56
+ }
57
+ }
58
+
43
59
impl Node {
44
60
/// Creates a new node in the empty namespace.
61
+ ///
62
+ /// See [`Node::new_with_namespace`] for documentation.
45
63
#[ allow( clippy:: new_ret_no_self) ]
46
64
pub fn new ( node_name : & str , context : & Context ) -> Result < Node , RclReturnCode > {
47
65
Self :: new_with_namespace ( "" , node_name, context)
@@ -51,6 +69,53 @@ impl Node {
51
69
///
52
70
/// A namespace without a leading forward slash is automatically changed to have a leading
53
71
/// forward slash.
72
+ ///
73
+ /// # Naming
74
+ /// The node namespace will be prefixed to the node name itself to form the *fully qualified
75
+ /// node name*. This is the name that is shown e.g. in `ros2 node list`.
76
+ /// Similarly, the node namespace will be prefixed to all names of topics and services
77
+ /// created from this node.
78
+ ///
79
+ /// By convention, a node name with a leading underscore marks the node as hidden.
80
+ ///
81
+ /// It's a good idea for node names in the same executable to be unique.
82
+ ///
83
+ /// ## Remapping
84
+ /// The namespace and name given here can be overriden through the command line.
85
+ /// In that sense, the parameters to this functions are only the _default_ namespace and name.
86
+ /// See also the [official tutorial][1] on the command line arguments for ROS nodes, and the
87
+ /// [`Node::namespace()`] and [`Node::name()`] functions for examples.
88
+ ///
89
+ /// ## Rules for valid names
90
+ /// The node namespace needs to fulfill the criteria of
91
+ /// [`rmw_validate_namespace()`][2], otherwise an error will be returned.
92
+ /// Likewise, the node name needs to fulfill the criteria of [`rmw_validate_node_name()`][3].
93
+ ///
94
+ /// # Example
95
+ /// ```
96
+ /// # use rclrs::{Context, Node, RclReturnCode, NodeErrorCode};
97
+ /// let ctx = Context::new([])?;
98
+ /// // This is a valid namespace and name
99
+ /// assert!(Node::new_with_namespace("/my/nested/namespace", "my_node", &ctx).is_ok());
100
+ /// // This name contains invalid characters, although the empty namespace is valid
101
+ /// assert_eq!(
102
+ /// Node::new_with_namespace("", "röböt", &ctx),
103
+ /// Err(RclReturnCode::NodeError(NodeErrorCode::NodeInvalidName))
104
+ /// );
105
+ /// // This namespace starts with a number
106
+ /// assert_eq!(
107
+ /// Node::new_with_namespace("/123/4", "my_node", &ctx),
108
+ /// Err(RclReturnCode::NodeError(NodeErrorCode::NodeInvalidNamespace))
109
+ /// );
110
+ /// # Ok::<(), RclReturnCode>(())
111
+ /// ```
112
+ ///
113
+ /// # Panics
114
+ /// When the node namespace or node name contain interior null bytes.
115
+ ///
116
+ /// [1]: https://docs.ros.org/en/rolling/How-To-Guides/Node-arguments.html
117
+ /// [2]: https://docs.ros2.org/latest/api/rmw/validate__namespace_8h.html
118
+ /// [3]: https://docs.ros2.org/latest/api/rmw/validate__node__name_8h.html
54
119
pub fn new_with_namespace (
55
120
node_ns : & str ,
56
121
node_name : & str ,
@@ -100,12 +165,12 @@ impl Node {
100
165
/// // Without remapping
101
166
/// let context = Context::new([])?;
102
167
/// let node = context.create_node("my_node")?;
103
- /// assert_eq!(node.name(), String::from( "my_node") );
168
+ /// assert_eq!(node.name(), "my_node");
104
169
/// // With remapping
105
170
/// let remapping = ["--ros-args", "-r", "__node:=your_node"].map(String::from);
106
171
/// let context_r = Context::new(remapping)?;
107
172
/// let node_r = context_r.create_node("my_node")?;
108
- /// assert_eq!(node_r.name(), String::from( "your_node") );
173
+ /// assert_eq!(node_r.name(), "your_node");
109
174
/// # Ok::<(), RclReturnCode>(())
110
175
/// ```
111
176
pub fn name ( & self ) -> String {
@@ -123,12 +188,12 @@ impl Node {
123
188
/// // Without remapping
124
189
/// let context = Context::new([])?;
125
190
/// let node = context.create_node_with_namespace("/my/namespace", "my_node")?;
126
- /// assert_eq!(node.namespace(), String::from( "/my/namespace") );
191
+ /// assert_eq!(node.namespace(), "/my/namespace");
127
192
/// // With remapping
128
193
/// let remapping = ["--ros-args", "-r", "__ns:=/your_namespace"].map(String::from);
129
194
/// let context_r = Context::new(remapping)?;
130
195
/// let node_r = context_r.create_node("my_node")?;
131
- /// assert_eq!(node_r.namespace(), String::from( "/your_namespace") );
196
+ /// assert_eq!(node_r.namespace(), "/your_namespace");
132
197
/// # Ok::<(), RclReturnCode>(())
133
198
/// ```
134
199
pub fn namespace ( & self ) -> String {
@@ -145,13 +210,14 @@ impl Node {
145
210
/// # use rclrs::{Context, RclReturnCode};
146
211
/// let context = Context::new([])?;
147
212
/// let node = context.create_node_with_namespace("/my/namespace", "my_node")?;
148
- /// assert_eq!(node.fully_qualified_name(), String::from( "/my/namespace/my_node") );
213
+ /// assert_eq!(node.fully_qualified_name(), "/my/namespace/my_node");
149
214
/// # Ok::<(), RclReturnCode>(())
150
215
/// ```
151
216
pub fn fully_qualified_name ( & self ) -> String {
152
217
self . get_string ( rcl_node_get_fully_qualified_name)
153
218
}
154
219
220
+ // Helper for name(), namespace(), fully_qualified_name()
155
221
fn get_string (
156
222
& self ,
157
223
getter : unsafe extern "C" fn ( * const rcl_node_t ) -> * const c_char ,
0 commit comments