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