@@ -96,8 +96,7 @@ class RosServiceNode : public BT::ActionNodeBase
96
96
*/
97
97
static PortsList providedBasicPorts (PortsList addition)
98
98
{
99
- PortsList basic = { InputPort<std::string>(" service_name" , " __default__placeholder__" ,
100
- " Service name" ) };
99
+ PortsList basic = { InputPort<std::string>(" service_name" , " " , " Service name" ) };
101
100
basic.insert (addition.begin (), addition.end ());
102
101
return basic;
103
102
}
@@ -111,7 +110,7 @@ class RosServiceNode : public BT::ActionNodeBase
111
110
return providedBasicPorts ({});
112
111
}
113
112
114
- NodeStatus tick () override final ;
113
+ NodeStatus tick () override ;
115
114
116
115
// / The default halt() implementation.
117
116
void halt () override ;
@@ -157,6 +156,9 @@ class RosServiceNode : public BT::ActionNodeBase
157
156
return action_client_mutex;
158
157
}
159
158
159
+ // method to set the service name programmatically
160
+ void setServiceName (const std::string& service_name);
161
+
160
162
rclcpp::Logger logger ()
161
163
{
162
164
if (auto node = node_.lock ())
@@ -186,7 +188,7 @@ class RosServiceNode : public BT::ActionNodeBase
186
188
187
189
std::weak_ptr<rclcpp::Node> node_;
188
190
std::string service_name_;
189
- bool service_name_may_change_ = false ;
191
+ bool service_name_should_be_checked_ = false ;
190
192
const std::chrono::milliseconds service_timeout_;
191
193
const std::chrono::milliseconds wait_for_service_timeout_;
192
194
@@ -233,51 +235,30 @@ inline RosServiceNode<T>::RosServiceNode(const std::string& instance_name,
233
235
{
234
236
const std::string& bb_service_name = portIt->second ;
235
237
236
- if (bb_service_name. empty () || bb_service_name == " __default__placeholder__ " )
238
+ if (isBlackboardPointer ( bb_service_name) )
237
239
{
238
- if (params.default_port_value .empty ())
239
- {
240
- throw std::logic_error (" Both [service_name] in the InputPort and the "
241
- " RosNodeParams are empty." );
242
- }
243
- else
244
- {
245
- createClient (params.default_port_value );
246
- }
240
+ // unknown value at construction time. postpone to tick
241
+ service_name_should_be_checked_ = true ;
247
242
}
248
- else if (!isBlackboardPointer ( bb_service_name))
243
+ else if (!bb_service_name. empty ( ))
249
244
{
250
- // If the content of the port "service_name" is not
251
- // a pointer to the blackboard, but a static string, we can
252
- // create the client in the constructor.
245
+ // "hard-coded" name in the bb_service_name. Use it.
253
246
createClient (bb_service_name);
254
247
}
255
- else
256
- {
257
- service_name_may_change_ = true ;
258
- // createClient will be invoked in the first tick().
259
- }
260
248
}
261
- else
249
+ // no port value or it is empty. Use the default port value
250
+ if (!srv_instance_ && !params.default_port_value .empty ())
262
251
{
263
- if (params.default_port_value .empty ())
264
- {
265
- throw std::logic_error (" Both [service_name] in the InputPort and the RosNodeParams "
266
- " are empty." );
267
- }
268
- else
269
- {
270
- createClient (params.default_port_value );
271
- }
252
+ createClient (params.default_port_value );
272
253
}
273
254
}
274
255
275
256
template <class T >
276
257
inline bool RosServiceNode<T>::createClient(const std::string& service_name)
277
258
{
278
- if (service_name.empty ())
259
+ if (service_name.empty () || service_name == " __default__placeholder__ " )
279
260
{
280
- throw RuntimeError (" service_name is empty" );
261
+ throw RuntimeError (" service_name is empty or invalid " );
281
262
}
282
263
283
264
std::unique_lock lk (getMutex ());
@@ -314,6 +295,13 @@ inline bool RosServiceNode<T>::createClient(const std::string& service_name)
314
295
return found;
315
296
}
316
297
298
+ template <class T >
299
+ inline void RosServiceNode<T>::setServiceName(const std::string& service_name)
300
+ {
301
+ service_name_ = service_name;
302
+ createClient (service_name);
303
+ }
304
+
317
305
template <class T >
318
306
inline NodeStatus RosServiceNode<T>::tick()
319
307
{
@@ -326,7 +314,7 @@ inline NodeStatus RosServiceNode<T>::tick()
326
314
// First, check if the service_client is valid and that the name of the
327
315
// service_name in the port didn't change.
328
316
// otherwise, create a new client
329
- if (!srv_instance_ || (status () == NodeStatus::IDLE && service_name_may_change_ ))
317
+ if (!srv_instance_ || (status () == NodeStatus::IDLE && service_name_should_be_checked_ ))
330
318
{
331
319
std::string service_name;
332
320
getInput (" service_name" , service_name);
@@ -336,6 +324,12 @@ inline NodeStatus RosServiceNode<T>::tick()
336
324
}
337
325
}
338
326
327
+ if (!srv_instance_)
328
+ {
329
+ throw BT::RuntimeError (" RosServiceNode: no service client was specified neither as "
330
+ " default or in the ports" );
331
+ }
332
+
339
333
auto CheckStatus = [](NodeStatus status) {
340
334
if (!isStatusCompleted (status))
341
335
{
0 commit comments