rclnodejs 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/binding.gyp +1 -0
- package/index.js +26 -3
- package/lib/context.js +4 -2
- package/lib/lifecycle.js +9 -0
- package/lib/node.js +106 -18
- package/lib/serialization.js +60 -0
- package/lib/type_description_service.js +27 -1
- package/package.json +3 -1
- package/rosidl_convertor/README.md +298 -0
- package/rosidl_convertor/idl_convertor.js +49 -0
- package/rosidl_convertor/idl_convertor.py +1176 -0
- package/rosidl_gen/generator.json +2 -2
- package/rosidl_gen/index.js +21 -4
- package/rosidl_gen/packages.js +65 -32
- package/rosidl_gen/templates/message.dot +1 -1
- package/scripts/npmjs-readme.md +1 -1
- package/src/addon.cpp +2 -0
- package/src/macros.h +17 -1
- package/src/rcl_action_client_bindings.cpp +3 -2
- package/src/rcl_action_goal_bindings.cpp +3 -2
- package/src/rcl_action_server_bindings.cpp +7 -5
- package/src/rcl_client_bindings.cpp +4 -3
- package/src/rcl_context_bindings.cpp +29 -19
- package/src/rcl_guard_condition_bindings.cpp +3 -2
- package/src/rcl_lifecycle_bindings.cpp +18 -4
- package/src/rcl_node_bindings.cpp +105 -3
- package/src/rcl_publisher_bindings.cpp +4 -3
- package/src/rcl_serialization_bindings.cpp +116 -0
- package/src/rcl_serialization_bindings.h +26 -0
- package/src/rcl_service_bindings.cpp +4 -3
- package/src/rcl_subscription_bindings.cpp +3 -2
- package/src/rcl_time_point_bindings.cpp +3 -2
- package/src/rcl_timer_bindings.cpp +8 -6
- package/src/rcl_utilities.cpp +31 -0
- package/src/rcl_utilities.h +7 -0
- package/tsconfig.json +2 -2
- package/types/context.d.ts +3 -2
- package/types/index.d.ts +26 -1
- package/types/lifecycle.d.ts +7 -0
- package/types/node.d.ts +48 -8
|
@@ -20,10 +20,13 @@
|
|
|
20
20
|
#include <rcl/arguments.h>
|
|
21
21
|
#include <rcl/error_handling.h>
|
|
22
22
|
#include <rcl/rcl.h>
|
|
23
|
+
#include <rcl/remap.h>
|
|
23
24
|
#include <rcl_action/rcl_action.h>
|
|
24
25
|
#include <rcl_yaml_param_parser/parser.h>
|
|
25
26
|
#include <rcl_yaml_param_parser/types.h>
|
|
26
27
|
|
|
28
|
+
#include <rcpputils/scope_exit.hpp>
|
|
29
|
+
// NOLINTNEXTLINE
|
|
27
30
|
#include <string>
|
|
28
31
|
|
|
29
32
|
#include "macros.h"
|
|
@@ -180,21 +183,46 @@ Napi::Value CreateNode(const Napi::CallbackInfo& info) {
|
|
|
180
183
|
rcl_context_t* context =
|
|
181
184
|
reinterpret_cast<rcl_context_t*>(context_handle->ptr());
|
|
182
185
|
|
|
183
|
-
|
|
186
|
+
Napi::Array jsArgv = info[3].As<Napi::Array>();
|
|
187
|
+
size_t argc = jsArgv.Length();
|
|
188
|
+
char** argv = AbstractArgsFromNapiArray(jsArgv);
|
|
189
|
+
RCPPUTILS_SCOPE_EXIT({ FreeArgs(argv, argc); });
|
|
190
|
+
|
|
191
|
+
rcl_arguments_t arguments = rcl_get_zero_initialized_arguments();
|
|
192
|
+
rcl_ret_t ret =
|
|
193
|
+
rcl_parse_arguments(argc, argv, rcl_get_default_allocator(), &arguments);
|
|
194
|
+
if ((ret != RCL_RET_OK) || HasUnparsedROSArgs(arguments)) {
|
|
195
|
+
Napi::Error::New(env, "failed to parse arguments")
|
|
196
|
+
.ThrowAsJavaScriptException();
|
|
197
|
+
return env.Undefined();
|
|
198
|
+
}
|
|
184
199
|
|
|
200
|
+
RCPPUTILS_SCOPE_EXIT({
|
|
201
|
+
if (RCL_RET_OK != rcl_arguments_fini(&arguments)) {
|
|
202
|
+
Napi::Error::New(env, "failed to fini arguments")
|
|
203
|
+
.ThrowAsJavaScriptException();
|
|
204
|
+
rcl_reset_error();
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
bool use_global_arguments = info[4].As<Napi::Boolean>().Value();
|
|
208
|
+
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(malloc(sizeof(rcl_node_t)));
|
|
185
209
|
*node = rcl_get_zero_initialized_node();
|
|
210
|
+
|
|
186
211
|
rcl_node_options_t options = rcl_node_get_default_options();
|
|
212
|
+
options.use_global_arguments = use_global_arguments;
|
|
213
|
+
options.arguments = arguments;
|
|
187
214
|
|
|
188
215
|
THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
|
|
189
216
|
rcl_node_init(node, node_name.c_str(),
|
|
190
217
|
name_space.c_str(), context, &options),
|
|
191
218
|
rcl_get_error_string().str);
|
|
192
219
|
|
|
193
|
-
auto handle = RclHandle::NewInstance(env, node, nullptr, [](void* ptr) {
|
|
220
|
+
auto handle = RclHandle::NewInstance(env, node, nullptr, [env](void* ptr) {
|
|
194
221
|
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(ptr);
|
|
195
222
|
rcl_ret_t ret = rcl_node_fini(node);
|
|
196
223
|
free(ptr);
|
|
197
|
-
|
|
224
|
+
THROW_ERROR_IF_NOT_EQUAL_NO_RETURN(RCL_RET_OK, ret,
|
|
225
|
+
rcl_get_error_string().str);
|
|
198
226
|
});
|
|
199
227
|
|
|
200
228
|
return handle;
|
|
@@ -450,6 +478,78 @@ Napi::Value GetRMWImplementationIdentifier(const Napi::CallbackInfo& info) {
|
|
|
450
478
|
return Napi::String::New(info.Env(), rmw_get_implementation_identifier());
|
|
451
479
|
}
|
|
452
480
|
|
|
481
|
+
Napi::Value ResolveName(const Napi::CallbackInfo& info) {
|
|
482
|
+
Napi::Env env = info.Env();
|
|
483
|
+
|
|
484
|
+
RclHandle* node_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
485
|
+
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
|
|
486
|
+
const rcl_node_options_t* node_options = rcl_node_get_options(node);
|
|
487
|
+
std::string topic_name = info[1].As<Napi::String>().Utf8Value();
|
|
488
|
+
bool only_expand = info[2].As<Napi::Boolean>().Value();
|
|
489
|
+
bool is_service = info[3].As<Napi::Boolean>().Value();
|
|
490
|
+
|
|
491
|
+
char* output_cstr = nullptr;
|
|
492
|
+
rcl_ret_t ret =
|
|
493
|
+
rcl_node_resolve_name(node, topic_name.c_str(), node_options->allocator,
|
|
494
|
+
is_service, only_expand, &output_cstr);
|
|
495
|
+
|
|
496
|
+
auto name_deleter = [&]() {
|
|
497
|
+
node_options->allocator.deallocate(output_cstr,
|
|
498
|
+
node_options->allocator.state);
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
RCPPUTILS_SCOPE_EXIT({ name_deleter(); });
|
|
502
|
+
|
|
503
|
+
if (RCL_RET_OK != ret) {
|
|
504
|
+
Napi::Error::New(env, ("failed to resolve name"))
|
|
505
|
+
.ThrowAsJavaScriptException();
|
|
506
|
+
return env.Undefined();
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return Napi::String::New(env, output_cstr);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
Napi::Value RemapTopicName(const Napi::CallbackInfo& info) {
|
|
513
|
+
Napi::Env env = info.Env();
|
|
514
|
+
RclHandle* node_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
|
|
515
|
+
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
|
|
516
|
+
std::string topic_name = info[1].As<Napi::String>().Utf8Value();
|
|
517
|
+
|
|
518
|
+
const rcl_node_options_t* node_options = rcl_node_get_options(node);
|
|
519
|
+
if (nullptr == node_options) {
|
|
520
|
+
Napi::Error::New(env, "failed to get node options")
|
|
521
|
+
.ThrowAsJavaScriptException();
|
|
522
|
+
return env.Undefined();
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const rcl_arguments_t* global_args = nullptr;
|
|
526
|
+
if (node_options->use_global_arguments) {
|
|
527
|
+
global_args = &(node->context->global_arguments);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
char* output_cstr = nullptr;
|
|
531
|
+
rcl_ret_t ret = rcl_remap_topic_name(
|
|
532
|
+
&(node_options->arguments), global_args, topic_name.c_str(),
|
|
533
|
+
rcl_node_get_name(node), rcl_node_get_namespace(node),
|
|
534
|
+
node_options->allocator, &output_cstr);
|
|
535
|
+
if (RCL_RET_OK != ret) {
|
|
536
|
+
Napi::Error::New(env, "failed to remap topic name")
|
|
537
|
+
.ThrowAsJavaScriptException();
|
|
538
|
+
return env.Undefined();
|
|
539
|
+
}
|
|
540
|
+
if (nullptr == output_cstr) {
|
|
541
|
+
return Napi::String::New(env, topic_name);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
auto name_deleter = [&]() {
|
|
545
|
+
node_options->allocator.deallocate(output_cstr,
|
|
546
|
+
node_options->allocator.state);
|
|
547
|
+
};
|
|
548
|
+
RCPPUTILS_SCOPE_EXIT({ name_deleter(); });
|
|
549
|
+
|
|
550
|
+
return Napi::String::New(env, output_cstr);
|
|
551
|
+
}
|
|
552
|
+
|
|
453
553
|
Napi::Object InitNodeBindings(Napi::Env env, Napi::Object exports) {
|
|
454
554
|
exports.Set("getParameterOverrides",
|
|
455
555
|
Napi::Function::New(env, GetParameterOverrides));
|
|
@@ -474,6 +574,8 @@ Napi::Object InitNodeBindings(Napi::Env env, Napi::Object exports) {
|
|
|
474
574
|
Napi::Function::New(env, GetFullyQualifiedName));
|
|
475
575
|
exports.Set("getRMWImplementationIdentifier",
|
|
476
576
|
Napi::Function::New(env, GetRMWImplementationIdentifier));
|
|
577
|
+
exports.Set("resolveName", Napi::Function::New(env, ResolveName));
|
|
578
|
+
exports.Set("remapTopicName", Napi::Function::New(env, RemapTopicName));
|
|
477
579
|
return exports;
|
|
478
580
|
}
|
|
479
581
|
|
|
@@ -55,12 +55,13 @@ Napi::Value CreatePublisher(const Napi::CallbackInfo& info) {
|
|
|
55
55
|
rcl_publisher_init(publisher, node, ts, topic.c_str(), &publisher_ops),
|
|
56
56
|
RCL_RET_OK, rcl_get_error_string().str);
|
|
57
57
|
|
|
58
|
-
auto js_obj =
|
|
59
|
-
|
|
58
|
+
auto js_obj = RclHandle::NewInstance(
|
|
59
|
+
env, publisher, node_handle, [node, env](void* ptr) {
|
|
60
60
|
rcl_publisher_t* publisher = reinterpret_cast<rcl_publisher_t*>(ptr);
|
|
61
61
|
rcl_ret_t ret = rcl_publisher_fini(publisher, node);
|
|
62
62
|
free(ptr);
|
|
63
|
-
|
|
63
|
+
THROW_ERROR_IF_NOT_EQUAL_NO_RETURN(RCL_RET_OK, ret,
|
|
64
|
+
rcl_get_error_string().str);
|
|
64
65
|
});
|
|
65
66
|
|
|
66
67
|
return js_obj;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Copyright (c) 2025, The Robot Web Tools Contributors
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
#include "rcl_serialization_bindings.h"
|
|
16
|
+
|
|
17
|
+
#include <rmw/rmw.h>
|
|
18
|
+
#include <rmw/serialized_message.h>
|
|
19
|
+
#include <rosidl_runtime_c/message_type_support_struct.h>
|
|
20
|
+
|
|
21
|
+
#include <string>
|
|
22
|
+
|
|
23
|
+
#include "rcl_utilities.h"
|
|
24
|
+
|
|
25
|
+
namespace {
|
|
26
|
+
|
|
27
|
+
struct SerializedMessage {
|
|
28
|
+
explicit SerializedMessage(Napi::Env env, rcutils_allocator_t allocator)
|
|
29
|
+
: env(env) {
|
|
30
|
+
rcl_msg = rmw_get_zero_initialized_serialized_message();
|
|
31
|
+
rcutils_ret_t rcutils_ret =
|
|
32
|
+
rmw_serialized_message_init(&rcl_msg, 0u, &allocator);
|
|
33
|
+
if (RCUTILS_RET_OK != rcutils_ret) {
|
|
34
|
+
Napi::Error::New(env, "failed to initialize serialized message")
|
|
35
|
+
.ThrowAsJavaScriptException();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
~SerializedMessage() {
|
|
40
|
+
rcutils_ret_t ret = rmw_serialized_message_fini(&rcl_msg);
|
|
41
|
+
if (RCUTILS_RET_OK != ret) {
|
|
42
|
+
Napi::Error::New(env,
|
|
43
|
+
"failed to fini rcl_serialized_msg_t in destructor.")
|
|
44
|
+
.ThrowAsJavaScriptException();
|
|
45
|
+
rcutils_reset_error();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
rcl_serialized_message_t rcl_msg;
|
|
50
|
+
Napi::Env env;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
} // namespace
|
|
54
|
+
|
|
55
|
+
namespace rclnodejs {
|
|
56
|
+
|
|
57
|
+
Napi::Value Serialize(const Napi::CallbackInfo& info) {
|
|
58
|
+
Napi::Env env = info.Env();
|
|
59
|
+
|
|
60
|
+
std::string package_name = info[0].As<Napi::String>().Utf8Value();
|
|
61
|
+
std::string message_sub_folder = info[1].As<Napi::String>().Utf8Value();
|
|
62
|
+
std::string message_name = info[2].As<Napi::String>().Utf8Value();
|
|
63
|
+
void* ros_msg = info[3].As<Napi::Buffer<char>>().Data();
|
|
64
|
+
const rosidl_message_type_support_t* ts =
|
|
65
|
+
GetMessageTypeSupport(package_name, message_sub_folder, message_name);
|
|
66
|
+
|
|
67
|
+
// Create a serialized message object.
|
|
68
|
+
SerializedMessage serialized_msg(env, rcutils_get_default_allocator());
|
|
69
|
+
|
|
70
|
+
rmw_ret_t rmw_ret = rmw_serialize(ros_msg, ts, &serialized_msg.rcl_msg);
|
|
71
|
+
if (RMW_RET_OK != rmw_ret) {
|
|
72
|
+
Napi::Error::New(env, "Failed to serialize ROS message")
|
|
73
|
+
.ThrowAsJavaScriptException();
|
|
74
|
+
return env.Undefined();
|
|
75
|
+
}
|
|
76
|
+
Napi::Buffer<char> buffer = Napi::Buffer<char>::Copy(
|
|
77
|
+
env, reinterpret_cast<const char*>(serialized_msg.rcl_msg.buffer),
|
|
78
|
+
serialized_msg.rcl_msg.buffer_length);
|
|
79
|
+
return buffer;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
Napi::Value Deserialize(const Napi::CallbackInfo& info) {
|
|
83
|
+
Napi::Env env = info.Env();
|
|
84
|
+
|
|
85
|
+
std::string package_name = info[0].As<Napi::String>().Utf8Value();
|
|
86
|
+
std::string message_sub_folder = info[1].As<Napi::String>().Utf8Value();
|
|
87
|
+
std::string message_name = info[2].As<Napi::String>().Utf8Value();
|
|
88
|
+
const rosidl_message_type_support_t* ts =
|
|
89
|
+
GetMessageTypeSupport(package_name, message_sub_folder, message_name);
|
|
90
|
+
Napi::Buffer<char> serialized = info[3].As<Napi::Buffer<char>>();
|
|
91
|
+
void* msg_taken = info[4].As<Napi::Buffer<char>>().Data();
|
|
92
|
+
|
|
93
|
+
// Create a serialized message object.
|
|
94
|
+
rcl_serialized_message_t serialized_msg =
|
|
95
|
+
rmw_get_zero_initialized_serialized_message();
|
|
96
|
+
serialized_msg.buffer_capacity = serialized.Length();
|
|
97
|
+
serialized_msg.buffer_length = serialized.Length();
|
|
98
|
+
serialized_msg.buffer = reinterpret_cast<uint8_t*>(serialized.Data());
|
|
99
|
+
|
|
100
|
+
rmw_ret_t rmw_ret = rmw_deserialize(&serialized_msg, ts, msg_taken);
|
|
101
|
+
|
|
102
|
+
if (RMW_RET_OK != rmw_ret) {
|
|
103
|
+
Napi::Error::New(env, "failed to deserialize ROS message")
|
|
104
|
+
.ThrowAsJavaScriptException();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return env.Undefined();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
Napi::Object InitSerializationBindings(Napi::Env env, Napi::Object exports) {
|
|
111
|
+
exports.Set("serialize", Napi::Function::New(env, Serialize));
|
|
112
|
+
exports.Set("deserialize", Napi::Function::New(env, Deserialize));
|
|
113
|
+
return exports;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
} // namespace rclnodejs
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright (c) 2025, The Robot Web Tools Contributors
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
#ifndef SRC_RCL_SERIALIZATION_BINDINGS_H_
|
|
16
|
+
#define SRC_RCL_SERIALIZATION_BINDINGS_H_
|
|
17
|
+
|
|
18
|
+
#include <napi.h>
|
|
19
|
+
|
|
20
|
+
namespace rclnodejs {
|
|
21
|
+
|
|
22
|
+
Napi::Object InitSerializationBindings(Napi::Env env, Napi::Object exports);
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#endif // SRC_RCL_SERIALIZATION_BINDINGS_H_
|
|
@@ -55,12 +55,13 @@ Napi::Value CreateService(const Napi::CallbackInfo& info) {
|
|
|
55
55
|
THROW_ERROR_IF_NOT_EQUAL(
|
|
56
56
|
rcl_service_init(service, node, ts, service_name.c_str(), &service_ops),
|
|
57
57
|
RCL_RET_OK, rcl_get_error_string().str);
|
|
58
|
-
auto js_obj =
|
|
59
|
-
|
|
58
|
+
auto js_obj = RclHandle::NewInstance(
|
|
59
|
+
env, service, node_handle, [node, env](void* ptr) {
|
|
60
60
|
rcl_service_t* service = reinterpret_cast<rcl_service_t*>(ptr);
|
|
61
61
|
rcl_ret_t ret = rcl_service_fini(service, node);
|
|
62
62
|
free(ptr);
|
|
63
|
-
|
|
63
|
+
THROW_ERROR_IF_NOT_EQUAL_NO_RETURN(RCL_RET_OK, ret,
|
|
64
|
+
rcl_get_error_string().str);
|
|
64
65
|
});
|
|
65
66
|
|
|
66
67
|
return js_obj;
|
|
@@ -136,12 +136,13 @@ Napi::Value CreateSubscription(const Napi::CallbackInfo& info) {
|
|
|
136
136
|
rcl_get_error_string().str);
|
|
137
137
|
|
|
138
138
|
auto js_obj = RclHandle::NewInstance(
|
|
139
|
-
env, subscription, node_handle, [node](void* ptr) {
|
|
139
|
+
env, subscription, node_handle, [node, env](void* ptr) {
|
|
140
140
|
rcl_subscription_t* subscription =
|
|
141
141
|
reinterpret_cast<rcl_subscription_t*>(ptr);
|
|
142
142
|
rcl_ret_t ret = rcl_subscription_fini(subscription, node);
|
|
143
143
|
free(ptr);
|
|
144
|
-
|
|
144
|
+
THROW_ERROR_IF_NOT_EQUAL_NO_RETURN(RCL_RET_OK, ret,
|
|
145
|
+
rcl_get_error_string().str);
|
|
145
146
|
});
|
|
146
147
|
|
|
147
148
|
return js_obj;
|
|
@@ -151,11 +151,12 @@ Napi::Value CreateClock(const Napi::CallbackInfo& info) {
|
|
|
151
151
|
rcl_clock_init(clock_type, clock, &allocator),
|
|
152
152
|
rcl_get_error_string().str);
|
|
153
153
|
|
|
154
|
-
return RclHandle::NewInstance(env, clock, nullptr, [](void* ptr) {
|
|
154
|
+
return RclHandle::NewInstance(env, clock, nullptr, [env](void* ptr) {
|
|
155
155
|
rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(ptr);
|
|
156
156
|
rcl_ret_t ret = rcl_clock_fini(clock);
|
|
157
157
|
free(ptr);
|
|
158
|
-
|
|
158
|
+
THROW_ERROR_IF_NOT_EQUAL_NO_RETURN(RCL_RET_OK, ret,
|
|
159
|
+
rcl_get_error_string().str);
|
|
159
160
|
});
|
|
160
161
|
}
|
|
161
162
|
|
|
@@ -58,12 +58,14 @@ Napi::Value CreateTimer(const Napi::CallbackInfo& info) {
|
|
|
58
58
|
rcl_get_error_string().str);
|
|
59
59
|
#endif
|
|
60
60
|
|
|
61
|
-
auto js_obj =
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
auto js_obj =
|
|
62
|
+
RclHandle::NewInstance(env, timer, clock_handle, [env](void* ptr) {
|
|
63
|
+
rcl_timer_t* timer = reinterpret_cast<rcl_timer_t*>(ptr);
|
|
64
|
+
rcl_ret_t ret = rcl_timer_fini(timer);
|
|
65
|
+
free(ptr);
|
|
66
|
+
THROW_ERROR_IF_NOT_EQUAL_NO_RETURN(RCL_RET_OK, ret,
|
|
67
|
+
rcl_get_error_string().str);
|
|
68
|
+
});
|
|
67
69
|
|
|
68
70
|
return js_obj;
|
|
69
71
|
}
|
package/src/rcl_utilities.cpp
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
#include <rmw/topic_endpoint_info.h>
|
|
20
20
|
#include <uv.h>
|
|
21
21
|
|
|
22
|
+
#include <cstdio>
|
|
22
23
|
#include <memory>
|
|
23
24
|
#include <string>
|
|
24
25
|
|
|
@@ -260,4 +261,34 @@ Napi::Array ConvertToJSTopicEndpointInfoList(
|
|
|
260
261
|
return list;
|
|
261
262
|
}
|
|
262
263
|
|
|
264
|
+
char** AbstractArgsFromNapiArray(const Napi::Array& jsArgv) {
|
|
265
|
+
size_t argc = jsArgv.Length();
|
|
266
|
+
char** argv = nullptr;
|
|
267
|
+
|
|
268
|
+
if (argc > 0) {
|
|
269
|
+
argv = reinterpret_cast<char**>(malloc(argc * sizeof(char*)));
|
|
270
|
+
for (size_t i = 0; i < argc; i++) {
|
|
271
|
+
std::string arg = jsArgv.Get(i).As<Napi::String>().Utf8Value();
|
|
272
|
+
int len = arg.length() + 1;
|
|
273
|
+
argv[i] = reinterpret_cast<char*>(malloc(len * sizeof(char)));
|
|
274
|
+
snprintf(argv[i], len, "%s", arg.c_str());
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return argv;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
void FreeArgs(char** argv, size_t argc) {
|
|
281
|
+
if (argv) {
|
|
282
|
+
for (size_t i = 0; i < argc; i++) {
|
|
283
|
+
free(argv[i]);
|
|
284
|
+
}
|
|
285
|
+
free(argv);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
bool HasUnparsedROSArgs(const rcl_arguments_t& rcl_args) {
|
|
290
|
+
int unparsed_ros_args_count = rcl_arguments_get_count_unparsed_ros(&rcl_args);
|
|
291
|
+
return unparsed_ros_args_count != 0;
|
|
292
|
+
}
|
|
293
|
+
|
|
263
294
|
} // namespace rclnodejs
|
package/src/rcl_utilities.h
CHANGED
|
@@ -53,6 +53,13 @@ Napi::Array ConvertToJSTopicEndpointInfoList(
|
|
|
53
53
|
|
|
54
54
|
Napi::Value ConvertToQoS(Napi::Env env, const rmw_qos_profile_t* qos_profile);
|
|
55
55
|
|
|
56
|
+
// `AbstractArgsFromNapiArray` and `FreeArgs` must be called in pairs.
|
|
57
|
+
char** AbstractArgsFromNapiArray(const Napi::Array& jsArgv);
|
|
58
|
+
// `AbstractArgsFromNapiArray` and `FreeArgs` must be called in pairs.
|
|
59
|
+
void FreeArgs(char** argv, size_t argc);
|
|
60
|
+
|
|
61
|
+
bool HasUnparsedROSArgs(const rcl_arguments_t& rcl_args);
|
|
62
|
+
|
|
56
63
|
} // namespace rclnodejs
|
|
57
64
|
|
|
58
65
|
#endif // SRC_RCL_UTILITIES_H_
|
package/tsconfig.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"module": "commonjs",
|
|
4
4
|
"moduleResolution": "node",
|
|
5
|
-
"target": "
|
|
5
|
+
"target": "es2020",
|
|
6
6
|
/* Strict Type-Checking Options */
|
|
7
7
|
"strict": true,
|
|
8
8
|
/* Additional Checks */
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"noUnusedParameters": true,
|
|
12
12
|
"noImplicitReturns": true,
|
|
13
13
|
"noFallthroughCasesInSwitch": true,
|
|
14
|
-
"lib": ["
|
|
14
|
+
"lib": ["es2020"]
|
|
15
15
|
},
|
|
16
16
|
"include": [
|
|
17
17
|
"types/**/*"
|
package/types/context.d.ts
CHANGED
|
@@ -38,8 +38,9 @@ declare module 'rclnodejs' {
|
|
|
38
38
|
* Create a new instance in uninitialized state.
|
|
39
39
|
* Call rcl.init(context) to initialize this context state for
|
|
40
40
|
* use in creating nodes, etc.
|
|
41
|
+
* @param {bigint} - Optional, The domain ID of this context.
|
|
41
42
|
*/
|
|
42
|
-
constructor();
|
|
43
|
+
constructor(domainId?: bigint);
|
|
43
44
|
|
|
44
45
|
/**
|
|
45
46
|
* Test if this context has not been initialized by rcl.init(context).
|
|
@@ -92,6 +93,6 @@ declare module 'rclnodejs' {
|
|
|
92
93
|
* Get the domain ID of this context.
|
|
93
94
|
* @returns domain ID of this context
|
|
94
95
|
*/
|
|
95
|
-
domainId():
|
|
96
|
+
domainId(): bigint;
|
|
96
97
|
}
|
|
97
98
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/// <reference path="./base.d.ts" />
|
|
2
2
|
|
|
3
3
|
declare module 'rclnodejs' {
|
|
4
|
+
type Class = new (...args: any[]) => any;
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* Create a node.
|
|
6
8
|
*
|
|
@@ -11,6 +13,9 @@ declare module 'rclnodejs' {
|
|
|
11
13
|
* @param namespace - The namespace used in ROS, default is an empty string.
|
|
12
14
|
* @param context - The context, default is Context.defaultContext().
|
|
13
15
|
* @param options - The node options, default is NodeOptions.defaultOptions.
|
|
16
|
+
* @param args - The arguments to be passed to the node, default is an empty array.
|
|
17
|
+
* @param useGlobalArguments - If true, the node will use global arguments, default is true.
|
|
18
|
+
* If false, the node will not use global arguments.
|
|
14
19
|
* @returns The new Node instance.
|
|
15
20
|
* @deprecated since 0.18.0, Use new Node constructor.
|
|
16
21
|
*/
|
|
@@ -18,7 +23,9 @@ declare module 'rclnodejs' {
|
|
|
18
23
|
nodeName: string,
|
|
19
24
|
namespace?: string,
|
|
20
25
|
context?: Context,
|
|
21
|
-
options?: NodeOptions
|
|
26
|
+
options?: NodeOptions,
|
|
27
|
+
args?: string[],
|
|
28
|
+
useGlobalArguments?: boolean
|
|
22
29
|
): Node;
|
|
23
30
|
|
|
24
31
|
/**
|
|
@@ -182,4 +189,22 @@ declare module 'rclnodejs' {
|
|
|
182
189
|
* @returns An array of the names and types.
|
|
183
190
|
*/
|
|
184
191
|
function getActionNamesAndTypes(node: Node): NamesAndTypesQueryResult;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Serialize a message to a Buffer.
|
|
195
|
+
*
|
|
196
|
+
* @param message - The message to be serialized.
|
|
197
|
+
* @param typeClass - The type class of the message.
|
|
198
|
+
* @returns A Buffer containing the serialized message.
|
|
199
|
+
*/
|
|
200
|
+
function serializeMessage(message: object, typeClass: Class): Buffer;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Deserialize a message from a Buffer.
|
|
204
|
+
*
|
|
205
|
+
* @param buffer - The Buffer containing the serialized message.
|
|
206
|
+
* @param typeClass - The type class of the message.
|
|
207
|
+
* @returns An Object representing the deserialized message.
|
|
208
|
+
*/
|
|
209
|
+
function deserializeMessage(buffer: Buffer, typeClass: Class): object;
|
|
185
210
|
}
|
package/types/lifecycle.d.ts
CHANGED
|
@@ -333,6 +333,13 @@ declare module 'rclnodejs' {
|
|
|
333
333
|
* @returns {boolean} true if the state machine is initialized; otherwise false.
|
|
334
334
|
*/
|
|
335
335
|
get isInitialized(): boolean;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Log the state machine data.
|
|
339
|
+
*
|
|
340
|
+
* @returns {undefined} void.
|
|
341
|
+
*/
|
|
342
|
+
print(): void;
|
|
336
343
|
}
|
|
337
344
|
} // lifecycle namespace
|
|
338
345
|
} // rclnodejs namespace
|
package/types/node.d.ts
CHANGED
|
@@ -750,21 +750,45 @@ declare module 'rclnodejs' {
|
|
|
750
750
|
getServiceNamesAndTypes(): Array<NamesAndTypesQueryResult>;
|
|
751
751
|
|
|
752
752
|
/**
|
|
753
|
-
*
|
|
753
|
+
* Return a list of publishers on a given topic.
|
|
754
754
|
*
|
|
755
|
-
*
|
|
756
|
-
*
|
|
757
|
-
*
|
|
755
|
+
* The returned parameter is a list of TopicEndpointInfo objects, where each will contain
|
|
756
|
+
* the node name, node namespace, topic type, topic endpoint's GID, and its QoS profile.
|
|
757
|
+
*
|
|
758
|
+
* When the `no_mangle` parameter is `true`, the provided `topic` should be a valid
|
|
759
|
+
* topic name for the middleware (useful when combining ROS with native middleware (e.g. DDS)
|
|
760
|
+
* apps). When the `no_mangle` parameter is `false`, the provided `topic` should
|
|
761
|
+
* follow ROS topic name conventions.
|
|
762
|
+
*
|
|
763
|
+
* `topic` may be a relative, private, or fully qualified topic name.
|
|
764
|
+
* A relative or private topic will be expanded using this node's namespace and name.
|
|
765
|
+
* The queried `topic` is not remapped.
|
|
766
|
+
*
|
|
767
|
+
* @param topic - The topic on which to find the publishers.
|
|
768
|
+
* @param [noDemangle=false] - If `true`, `topic` needs to be a valid middleware topic
|
|
769
|
+
* name, otherwise it should be a valid ROS topic name. Defaults to `false`.
|
|
758
770
|
* @returns An array of publishers.
|
|
759
771
|
*/
|
|
760
772
|
getPublishersInfoByTopic(topic: string, noDemangle: boolean): Array<object>;
|
|
761
773
|
|
|
762
774
|
/**
|
|
763
|
-
*
|
|
775
|
+
* Return a list of subscriptions on a given topic.
|
|
764
776
|
*
|
|
765
|
-
*
|
|
766
|
-
*
|
|
767
|
-
*
|
|
777
|
+
* The returned parameter is a list of TopicEndpointInfo objects, where each will contain
|
|
778
|
+
* the node name, node namespace, topic type, topic endpoint's GID, and its QoS profile.
|
|
779
|
+
*
|
|
780
|
+
* When the `no_mangle` parameter is `true`, the provided `topic` should be a valid
|
|
781
|
+
* topic name for the middleware (useful when combining ROS with native middleware (e.g. DDS)
|
|
782
|
+
* apps). When the `no_mangle` parameter is `false`, the provided `topic` should
|
|
783
|
+
* follow ROS topic name conventions.
|
|
784
|
+
*
|
|
785
|
+
* `topic` may be a relative, private, or fully qualified topic name.
|
|
786
|
+
* A relative or private topic will be expanded using this node's namespace and name.
|
|
787
|
+
* The queried `topic` is not remapped.
|
|
788
|
+
*
|
|
789
|
+
* @param topic - The topic on which to find the subscriptions..
|
|
790
|
+
* @param [noDemangle=false] - If `true`, `topic` needs to be a valid middleware topic
|
|
791
|
+
name, otherwise it should be a valid ROS topic name. Defaults to `false`.
|
|
768
792
|
* @returns An array of subscriptions.
|
|
769
793
|
*/
|
|
770
794
|
getSubscriptionsInfoByTopic(
|
|
@@ -838,5 +862,21 @@ declare module 'rclnodejs' {
|
|
|
838
862
|
* @returns - The RMW implementation identifier.
|
|
839
863
|
*/
|
|
840
864
|
getRMWImplementationIdentifier(): string;
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Return a topic name expanded and remapped.
|
|
868
|
+
* @param topicName - Topic name to be expanded and remapped.
|
|
869
|
+
* @param onlyExpand - If `true`, remapping rules won't be applied, default is false.
|
|
870
|
+
* @returns A fully qualified topic name.
|
|
871
|
+
*/
|
|
872
|
+
resolveTopicName(topicName: string, onlyExpand?: boolean): string;
|
|
873
|
+
|
|
874
|
+
/**
|
|
875
|
+
* Return a service name expanded and remapped.
|
|
876
|
+
* @param service - Service name to be expanded and remapped.
|
|
877
|
+
* @param onlyExpand - If `true`, remapping rules won't be applied, default is false.
|
|
878
|
+
* @returns A fully qualified service name.
|
|
879
|
+
*/
|
|
880
|
+
resolveServiceName(service: string, onlyExpand?: boolean): string;
|
|
841
881
|
}
|
|
842
882
|
}
|