@@ -42,7 +42,7 @@ pub struct Node {
42
42
43
43
/// A builder for node instantiation.
44
44
///
45
- /// The default values for each field are
45
+ /// default value in each fields are
46
46
/// - context: user defined
47
47
/// - name: user defined
48
48
/// - namespace: "/"
@@ -86,67 +86,6 @@ impl Node {
86
86
NodeBuilder :: new ( node_name, context) . build ( )
87
87
}
88
88
89
- /// Creates a new node in a namespace.
90
- ///
91
- /// A namespace without a leading forward slash is automatically changed to have a leading
92
- /// forward slash.
93
- ///
94
- /// # Naming
95
- /// The node namespace will be prefixed to the node name itself to form the *fully qualified
96
- /// node name*. This is the name that is shown e.g. in `ros2 node list`.
97
- /// Similarly, the node namespace will be prefixed to all names of topics and services
98
- /// created from this node.
99
- ///
100
- /// By convention, a node name with a leading underscore marks the node as hidden.
101
- ///
102
- /// It's a good idea for node names in the same executable to be unique.
103
- ///
104
- /// ## Remapping
105
- /// The namespace and name given here can be overriden through the command line.
106
- /// In that sense, the parameters to this functions are only the _default_ namespace and name.
107
- /// See also the [official tutorial][1] on the command line arguments for ROS nodes, and the
108
- /// [`Node::namespace()`] and [`Node::name()`] functions for examples.
109
- ///
110
- /// ## Rules for valid names
111
- /// The node namespace needs to fulfill the criteria of
112
- /// [`rmw_validate_namespace()`][2], otherwise an error will be returned.
113
- /// Likewise, the node name needs to fulfill the criteria of [`rmw_validate_node_name()`][3].
114
- ///
115
- /// # Example
116
- /// ```
117
- /// # use rclrs::{Context, Node, RclReturnCode, NodeErrorCode};
118
- /// let ctx = Context::new([])?;
119
- /// // This is a valid namespace and name
120
- /// assert!(Node::new_with_namespace("/my/nested/namespace", "my_node", &ctx).is_ok());
121
- /// // This name contains invalid characters, although the empty namespace is valid
122
- /// assert_eq!(
123
- /// Node::new_with_namespace("", "röböt", &ctx),
124
- /// Err(RclReturnCode::NodeError(NodeErrorCode::NodeInvalidName))
125
- /// );
126
- /// // This namespace starts with a number
127
- /// assert_eq!(
128
- /// Node::new_with_namespace("/123/4", "my_node", &ctx),
129
- /// Err(RclReturnCode::NodeError(NodeErrorCode::NodeInvalidNamespace))
130
- /// );
131
- /// # Ok::<(), RclReturnCode>(())
132
- /// ```
133
- ///
134
- /// # Panics
135
- /// When the node namespace or node name contain interior null bytes.
136
- ///
137
- /// [1]: https://docs.ros.org/en/rolling/How-To-Guides/Node-arguments.html
138
- /// [2]: https://docs.ros2.org/latest/api/rmw/validate__namespace_8h.html
139
- /// [3]: https://docs.ros2.org/latest/api/rmw/validate__node__name_8h.html
140
- pub fn new_with_namespace (
141
- node_ns : & str ,
142
- node_name : & str ,
143
- context : & Context ,
144
- ) -> Result < Node , RclReturnCode > {
145
- NodeBuilder :: new ( node_name, context)
146
- . namespace ( node_ns)
147
- . build ( )
148
- }
149
-
150
89
/// Returns the name of the node.
151
90
///
152
91
/// This returns the name after remapping, so it is not necessarily the same as the name that
@@ -180,7 +119,10 @@ impl Node {
180
119
/// # use rclrs::{Context, RclReturnCode};
181
120
/// // Without remapping
182
121
/// let context = Context::new([])?;
183
- /// let node = context.create_node_with_namespace("/my/namespace", "my_node")?;
122
+ /// let node = context
123
+ /// .create_node_builder("my_node")
124
+ /// .namespace("/my/namespace")
125
+ /// .build()?;
184
126
/// assert_eq!(node.namespace(), "/my/namespace");
185
127
/// // With remapping
186
128
/// let remapping = ["--ros-args", "-r", "__ns:=/your_namespace"].map(String::from);
@@ -202,7 +144,10 @@ impl Node {
202
144
/// ```
203
145
/// # use rclrs::{Context, RclReturnCode};
204
146
/// let context = Context::new([])?;
205
- /// let node = context.create_node_with_namespace("/my/namespace", "my_node")?;
147
+ /// let node = context
148
+ /// .create_node_builder("my_node")
149
+ /// .namespace("/my/namespace")
150
+ /// .build()?;
206
151
/// assert_eq!(node.fully_qualified_name(), "/my/namespace/my_node");
207
152
/// # Ok::<(), RclReturnCode>(())
208
153
/// ```
@@ -308,6 +253,45 @@ impl Node {
308
253
309
254
impl NodeBuilder {
310
255
/// Creates new builder for Node.
256
+ ///
257
+ /// # Naming rule for node name
258
+ /// The node name must follow below rules.
259
+ /// - must not be an empty.
260
+ /// - must only contain alphanumeric characters and underscores(a-z|A-Z|0-9|_).
261
+ /// - must not start a number.
262
+ /// The validation performs at [`NodeBuilder::build()`][1], and does not perform in this function.
263
+ /// For more details, see [`rmw_validate_nodename`][2].
264
+ ///
265
+ /// By convention, a node name with a leading underscore marks the node as hidden.
266
+ /// Fully qualified node names(namespace + name) should be unique in the same executable to be unique.
267
+ ///
268
+ /// # Remapping
269
+ /// The namespace and name given here can be overriden through the command line.
270
+ /// In that sense, the parameters to this constructor and
271
+ /// [`NodeBuilder::namespace()`][3] are only the _default_ namespace and name.
272
+ /// See also the [official tutorial][4] on the command line arguments for ROS nodes, and
273
+ /// the [`Node::namespace()`] and [`Node::name()`] functions for examples.
274
+ ///
275
+ /// # Example
276
+ /// ```
277
+ /// # use rclrs::{Context, Node, NodeBuilder, RclReturnCode, NodeErrorCode};
278
+ /// let context = Context::new([])?;
279
+ /// let builder = NodeBuilder::new("foo_node", &context);
280
+ /// let node = builder.build()?;
281
+ /// assert_eq!(node.name(), "foo_node");
282
+ /// // invalid node name
283
+ /// let builder = NodeBuilder::new("123abc", &context);
284
+ /// assert_eq!(
285
+ /// builder.build(),
286
+ /// Err(RclReturnCode::NodeError(NodeErrorCode::NodeInvalidName))
287
+ /// );
288
+ /// # Ok::<(), RclReturnCode>(())
289
+ /// ```
290
+ ///
291
+ /// [1]: NodeBuilder::build
292
+ /// [2]: https://docs.ros2.org/bouncy/api/rmw/validate__node__name_8h.html
293
+ /// [3]: NodeBuilder::namespace
294
+ /// [4]: https://docs.ros.org/en/rolling/How-To-Guides/Node-arguments.html
311
295
pub fn new ( name : & str , context : & Context ) -> NodeBuilder {
312
296
NodeBuilder {
313
297
context : context. handle . clone ( ) ,
@@ -317,12 +301,76 @@ impl NodeBuilder {
317
301
}
318
302
319
303
/// Sets node namespace.
304
+ ///
305
+ /// # Naming rule for node namespace
306
+ /// The node namespace naming rules is based on rules defined for a [topic][1].
307
+ /// namespace naming rules are below.
308
+ /// - must not be empty(Note that empty string is allowed in this method. Empty string is replaced to "/".)
309
+ /// - may contain alphanumric characters, underscores, or forward slashes(a-z|A-Z|0-9|_|/)
310
+ /// - must no start with numeric character(0-9)
311
+ /// - must not contain repeated forward slashes(/)
312
+ /// - must not contain repeated underscores(_)
313
+ ///
314
+ /// In fully qualified name, Namespace will be prefixed to node name.
315
+ /// e.g. `/foo/bar/node_name` when namespace is `/foo/bar` and node name is `node_name`
316
+ ///
317
+ /// Note that namespace naming validation is delayed to [`NodeBuilder::build()`][2].
318
+ /// For more details, see [`rmw_validate_namespace()`][3].
319
+ ///
320
+ /// [1]: http://design.ros2.org/articles/topic_and_service_names.html
321
+ /// [2]: NodeBuilder::build
322
+ /// [3]: https://docs.ros2.org/bouncy/api/rmw/validate__namespace_8h.html
323
+ ///
324
+ /// # Example
325
+ /// ```
326
+ /// # use rclrs::{Context, Node, NodeBuilder, RclReturnCode, NodeErrorCode};
327
+ /// let context = Context::new([])?;
328
+ /// let builder = NodeBuilder::new("node_name", &context);
329
+ /// let node = builder.namespace("/foo/bar").build()?;
330
+ /// assert_eq!(node.fully_qualified_name(), "/foo/bar/node_name");
331
+ /// // invalid namespace
332
+ /// let builder = NodeBuilder::new("node_name", &context);
333
+ /// assert_eq!(
334
+ /// builder.namespace("123abc").build(),
335
+ /// Err(RclReturnCode::NodeError(NodeErrorCode::NodeInvalidNamespace))
336
+ /// );
337
+ /// # Ok::<(), RclReturnCode>(())
338
+ /// ```
320
339
pub fn namespace ( mut self , namespace : & str ) -> Self {
321
340
self . namespace = namespace. to_string ( ) ;
322
341
self
323
342
}
324
343
325
- /// Builds node instance
344
+ /// Builds node instance
345
+ ///
346
+ /// Node name and namespace validation is performed in this method.
347
+ /// If invalid name and/or namespace are specified to builder,
348
+ /// this method will return RclReturnCode as error.
349
+ ///
350
+ /// # Example
351
+ /// ```
352
+ /// # use rclrs::{Context, Node, NodeBuilder, RclReturnCode, NodeErrorCode};
353
+ /// let context = Context::new([])?;
354
+ ///
355
+ /// let builder = NodeBuilder::new("node_name", &context);
356
+ /// let result = builder.namespace("/foo/bar").build();
357
+ /// assert!(result.is_ok());
358
+ /// // invalid node name
359
+ /// let builder = NodeBuilder::new("123abc", &context);
360
+ /// let result = builder.namespace("/foo/bar").build();
361
+ /// assert_eq!(
362
+ /// result,
363
+ /// Err(RclReturnCode::NodeError(NodeErrorCode::NodeInvalidName))
364
+ /// );
365
+ /// // invalid namespace
366
+ /// let builder = NodeBuilder::new("node_name", &context);
367
+ /// let result = builder.namespace("123abc").build();
368
+ /// assert_eq!(
369
+ /// result,
370
+ /// Err(RclReturnCode::NodeError(NodeErrorCode::NodeInvalidNamespace))
371
+ /// );
372
+ /// # Ok::<(), RclReturnCode>(())
373
+ /// ```
326
374
pub fn build ( & self ) -> Result < Node , RclReturnCode > {
327
375
let node_name = CString :: new ( self . name . as_str ( ) ) . unwrap ( ) ;
328
376
let node_namespace = CString :: new ( self . namespace . as_str ( ) ) . unwrap ( ) ;
0 commit comments