dynamic_parameters.h
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // Copyright (c) 2019, Southwest Research Institute® (SwRI®)
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Southwest Research Institute® (SwRI®) nor the
14 // names of its contributors may be used to endorse or promote products
15 // derived from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL SOUTHWEST RESEARCH INSTITUTE BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // *****************************************************************************
29 
30 #ifndef SWRI_ROSCPP_DYNAMIC_PARAMETERS_H_
31 #define SWRI_ROSCPP_DYNAMIC_PARAMETERS_H_
32 
33 #include <map>
34 #include <string>
35 
36 #include <boost/thread/mutex.hpp>
37 
38 #include <ros/console.h>
39 #include <ros/node_handle.h>
40 
41 #include <dynamic_reconfigure/Config.h>
42 #include <dynamic_reconfigure/ConfigDescription.h>
43 #include <dynamic_reconfigure/GroupState.h>
44 #include <dynamic_reconfigure/Reconfigure.h>
45 
46 namespace swri
47 {
48  struct DynamicValue
49  {
50  enum Type
51  {
52  Bool = 0,
53  Float = 1,
54  Double = 2,
55  Int = 3,
56  String = 4
57  };
58 
60  std::string name;
61  std::string description;
62 
63  //pointer to the parameter to update on change
69 
70  // Defaults, maximum and minimum values for this parameter
71  union
72  {
73  double d;
74  bool b;
75  int i;
76  } Default;
77  union
78  {
79  double d;
80  int i;
81  } Min;
82  union
83  {
84  double d;
85  int i;
86  } Max;
87  std::string default_string;// to get around union issues with strings
88  };
89 
90  template <class T>
91  struct TypedParam
92  {
95 
96  inline
97  T operator* ()
98  {
99  return *data;
100  }
101 
102  T get()
103  {
104  mutex->lock();
105  T d = *data;
106  mutex->unlock();
107 
108  return d;
109  }
110  };
111 
117 
118 
120  {
125 
126  std::map<std::string, DynamicValue> values_;
127 
128  boost::function<void(DynamicParameters&)> on_change_;
129 
130 
132 
133  bool setConfigCallback(dynamic_reconfigure::Reconfigure::Request &req,
134  dynamic_reconfigure::Reconfigure::Response &rsp)
135  {
136  ROS_DEBUG("Got configuration change request");
137 
138  boost::mutex::scoped_lock lock(*mutex_);
139 
140  // update the parameters
141  for (int i = 0; i < req.config.doubles.size(); i++)
142  {
143  dynamic_reconfigure::DoubleParameter param = req.config.doubles[i];
144  std::map<std::string, DynamicValue>::iterator iter = values_.find(param.name);
145  if (iter == values_.end())
146  {
147  ROS_ERROR("Could not find parameter '%s'", param.name.c_str());
148  continue;
149  }
150 
151  if (iter->second.type != DynamicValue::Double && iter->second.type != DynamicValue::Float)
152  {
153  ROS_ERROR("Value '%s' was not a double type.", param.name.c_str());
154  continue;
155  }
156 
157  if (iter->second.type == DynamicValue::Double)
158  {
159  *iter->second.dbl = param.value;
160  }
161 
162  if (iter->second.type == DynamicValue::Float)
163  {
164  *iter->second.flt = (float)param.value;
165  }
166  }
167 
168  for (int i = 0; i < req.config.ints.size(); i++)
169  {
170  dynamic_reconfigure::IntParameter param = req.config.ints[i];
171  std::map<std::string, DynamicValue>::iterator iter = values_.find(param.name);
172  if (iter == values_.end())
173  {
174  ROS_ERROR("Could not find parameter '%s'", param.name.c_str());
175  continue;
176  }
177 
178  if (iter->second.type != DynamicValue::Int)
179  {
180  ROS_ERROR("Value '%s' was not a int type.", param.name.c_str());
181  continue;
182  }
183 
184  *iter->second.integer = param.value;
185  }
186 
187  for (int i = 0; i < req.config.bools.size(); i++)
188  {
189  dynamic_reconfigure::BoolParameter param = req.config.bools[i];
190  std::map<std::string, DynamicValue>::iterator iter = values_.find(param.name);
191  if (iter == values_.end())
192  {
193  ROS_ERROR("Could not find parameter '%s'", param.name.c_str());
194  continue;
195  }
196 
197  if (iter->second.type != DynamicValue::Bool)
198  {
199  ROS_ERROR("Value '%s' was not a bool type.", param.name.c_str());
200  continue;
201  }
202 
203  *iter->second.boolean = param.value;
204  }
205 
206  for (int i = 0; i < req.config.strs.size(); i++)
207  {
208  dynamic_reconfigure::StrParameter param = req.config.strs[i];
209  std::map<std::string, DynamicValue>::iterator iter = values_.find(param.name);
210  if (iter == values_.end())
211  {
212  ROS_ERROR("Could not find parameter '%s'", param.name.c_str());
213  continue;
214  }
215 
216  if (iter->second.type != DynamicValue::String)
217  {
218  ROS_ERROR("Value '%s' was not a string type.", param.name.c_str());
219  continue;
220  }
221 
222  *iter->second.str = param.value;
223  }
224 
225  updateCurrent(rsp.config);
226 
227  if (on_change_)
228  {
229  on_change_(*this);
230  }
231 
232  return true;
233  }
234 
235  // Updates a config with the current parameter values
236  void updateCurrent(dynamic_reconfigure::Config& config)
237  {
238  for (std::map<std::string, DynamicValue>::iterator value = values_.begin(); value != values_.end(); value++)
239  {
240  if (value->second.type == DynamicValue::Double)
241  {
242  dynamic_reconfigure::DoubleParameter param;
243  param.name = value->first;
244  param.value = *value->second.dbl;
245  config.doubles.push_back(param);
246  }
247  else if (value->second.type == DynamicValue::Float)
248  {
249  dynamic_reconfigure::DoubleParameter param;
250  param.name = value->first;
251  param.value = *value->second.flt;
252  config.doubles.push_back(param);
253  }
254  else if (value->second.type == DynamicValue::Int)
255  {
256  dynamic_reconfigure::IntParameter param;
257  param.name = value->first;
258  param.value = *value->second.integer;
259  config.ints.push_back(param);
260  }
261  else if (value->second.type == DynamicValue::Bool)
262  {
263  dynamic_reconfigure::BoolParameter param;
264  param.name = value->first;
265  param.value = *value->second.boolean;
266  config.bools.push_back(param);
267  }
268  else if (value->second.type == DynamicValue::String)
269  {
270  dynamic_reconfigure::StrParameter param;
271  param.name = value->first;
272  param.value = *value->second.str;
273  config.strs.push_back(param);
274  }
275  }
276 
277  dynamic_reconfigure::GroupState gs;
278  gs.name = "Default";
279  gs.state = true;
280  gs.id = 0;
281  gs.parent = 0;
282  config.groups.push_back(gs);
283  update_pub_.publish(config);
284  }
285 
286  public:
287 
288  DynamicParameters() : mutex_(new boost::mutex)
289  {
290 
291  }
292 
293  // Sets up the node handle and publishers. Be sure to call this before finalize or any of the 'get*' calls.
295  {
296  boost::mutex::scoped_lock lock(*mutex_);
297  nh_ = pnh;
298 
299  descr_pub_ = nh_.advertise<dynamic_reconfigure::ConfigDescription>("parameter_descriptions", 1, true);
300  update_pub_ = nh_.advertise<dynamic_reconfigure::Config>("parameter_updates", 1, true);
301  }
302 
303  // Publishes the configuration parameters that have been added
304  void finalize()
305  {
306  boost::mutex::scoped_lock lock(*mutex_);
307 
308  // publish the configs as one group
309  dynamic_reconfigure::ConfigDescription rdesc;
310  dynamic_reconfigure::Group group;
311  group.name = "Default";
312  group.type = "";
313  group.id = 0;
314  group.parent = 0;
315 
316  dynamic_reconfigure::GroupState gs;
317  gs.name = "Default";
318  gs.state = true;
319  gs.id = 0;
320  gs.parent = 0;
321  for (std::map<std::string, DynamicValue>::iterator param = values_.begin(); param != values_.end(); param++)
322  {
323  std::string type;
324  if (param->second.type == DynamicValue::Bool)
325  {
326  type = "bool";
327 
328  dynamic_reconfigure::BoolParameter desc;
329  desc.name = param->first;
330  desc.value = true;
331  rdesc.max.bools.push_back(desc);
332  desc.value = false;
333  rdesc.min.bools.push_back(desc);
334  desc.value = param->second.Default.b;
335  rdesc.dflt.bools.push_back(desc);
336  }
337  else if (param->second.type == DynamicValue::Float)
338  {
339  type = "double";
340 
341  dynamic_reconfigure::DoubleParameter desc;
342  desc.name = param->first;
343  desc.value = param->second.Max.d;
344  rdesc.max.doubles.push_back(desc);
345  desc.value = param->second.Min.d;
346  rdesc.min.doubles.push_back(desc);
347  desc.value = param->second.Default.d;
348  rdesc.dflt.doubles.push_back(desc);
349  }
350  else if (param->second.type == DynamicValue::Double)
351  {
352  type = "double";
353 
354  dynamic_reconfigure::DoubleParameter desc;
355  desc.name = param->first;
356  desc.value = param->second.Max.d;
357  rdesc.max.doubles.push_back(desc);
358  desc.value = param->second.Min.d;
359  rdesc.min.doubles.push_back(desc);
360  desc.value = param->second.Default.d;
361  rdesc.dflt.doubles.push_back(desc);
362  }
363  else if (param->second.type == DynamicValue::Int)
364  {
365  type = "int";
366 
367  dynamic_reconfigure::IntParameter desc;
368  desc.name = param->first;
369  desc.value = param->second.Max.i;
370  rdesc.max.ints.push_back(desc);
371  desc.value = param->second.Min.i;
372  rdesc.min.ints.push_back(desc);
373  desc.value = param->second.Default.i;
374  rdesc.dflt.ints.push_back(desc);
375  }
376  else if (param->second.type == DynamicValue::String)
377  {
378  type = "string";
379  dynamic_reconfigure::StrParameter desc;
380  desc.name = param->first;
381  desc.value = "";
382  rdesc.max.strs.push_back(desc);
383  desc.value = "";
384  rdesc.min.strs.push_back(desc);
385  desc.value = param->second.default_string;
386  rdesc.dflt.strs.push_back(desc);
387  }
388 
389  dynamic_reconfigure::ParamDescription desc;
390  desc.name = param->first;
391  desc.type = type;
392  desc.level = 0;
393  desc.description = param->second.description;
394  desc.edit_method = "";
395  group.parameters.push_back(desc);
396  }
397  rdesc.max.groups.push_back(gs);
398  rdesc.min.groups.push_back(gs);
399  rdesc.dflt.groups.push_back(gs);
400  rdesc.groups.push_back(group);
401  descr_pub_.publish(rdesc);
402 
403  dynamic_reconfigure::Config config;
404  updateCurrent(config);
405 
406  set_service_ = nh_.advertiseService("set_parameters",
408  }
409 
410  void setCallback(boost::function<void(DynamicParameters&)> fun)
411  {
412  on_change_ = fun;
413  }
414 
415  //for use in the on change callback
416  double getDouble(const std::string& name)
417  {
418  std::map<std::string, DynamicValue>::iterator iter = values_.find(name);
419  if (iter == values_.end())
420  {
421  ROS_ERROR("Tried to get nonexistant param %s", name.c_str());
422  return 0.0;
423  }
424  if (iter->second.type != DynamicValue::Double)
425  {
426  ROS_ERROR("Tried to load parameter %s with the wrong type: double.", name.c_str());
427  return 0.0;
428  }
429 
430  return *iter->second.dbl;
431  }
432 
433  //for use in the on change callback
434  float getFloat(const std::string& name)
435  {
436  std::map<std::string, DynamicValue>::iterator iter = values_.find(name);
437  if (iter == values_.end())
438  {
439  ROS_ERROR("Tried to get nonexistant param %s", name.c_str());
440  return 0.0f;
441  }
442  if (iter->second.type != DynamicValue::Float)
443  {
444  ROS_ERROR("Tried to load parameter %s with the wrong type: float.", name.c_str());
445  return 0.0f;
446  }
447 
448  return *iter->second.flt;
449  }
450 
451  int getInt(const std::string& name)
452  {
453  std::map<std::string, DynamicValue>::iterator iter = values_.find(name);
454  if (iter == values_.end())
455  {
456  ROS_ERROR("Tried to get nonexistant param %s", name.c_str());
457  return 0.0f;
458  }
459  if (iter->second.type != DynamicValue::Int)
460  {
461  ROS_ERROR("Tried to load parameter %s with the wrong type: int.", name.c_str());
462  return 0.0f;
463  }
464 
465  return *iter->second.integer;
466  }
467 
468  //for use in the on change callback
469  bool getBool(const std::string& name)
470  {
471  std::map<std::string, DynamicValue>::iterator iter = values_.find(name);
472  if (iter == values_.end())
473  {
474  ROS_ERROR("Tried to get nonexistant param %s", name.c_str());
475  return false;
476  }
477  if (iter->second.type != DynamicValue::Bool)
478  {
479  ROS_ERROR("Tried to load parameter %s with the wrong type: bool.", name.c_str());
480  return false;
481  }
482 
483  return *iter->second.boolean;
484  }
485 
486  //for use in the on change callback
487  std::string getString(const std::string& name)
488  {
489  std::map<std::string, DynamicValue>::iterator iter = values_.find(name);
490  if (iter == values_.end())
491  {
492  ROS_ERROR("Tried to get nonexistant param %s", name.c_str());
493  return "";
494  }
495  if (iter->second.type != DynamicValue::String)
496  {
497  ROS_ERROR("Tried to load parameter %s with the wrong type: string.", name.c_str());
498  return "";
499  }
500 
501  return *iter->second.str;
502  }
503 
504 
505  inline
506  boost::mutex& mutex()
507  {
508  return *mutex_;
509  }
510 
511  inline
512  boost::mutex::scoped_lock lock_guard()
513  {
514  return boost::mutex::scoped_lock(*mutex_);
515  }
516 
517  // for use with on change callbacks
518  inline
519  void get(const std::string &name,
520  float &variable,
521  const float default_value,
522  const std::string description = "None.",
523  const float min = -100,
524  const float max = 100)
525  {
526  DynamicValue value;
527  value.type = DynamicValue::Float;
528  value.description = description;
529  value.Min.d = min;
530  value.Max.d = max;
531  value.Default.d = default_value;
532  value.flt = boost::shared_ptr<float>(new float);
533  values_[name] = value;
534 
535  std::string resolved_name = nh_.resolveName(name);
536  //_used_params.insert(resolved_name);
537  nh_.param(name, *value.flt, default_value);
538  variable = *value.flt;
539  ROS_INFO("Read dynamic parameter %s = %f", name.c_str(), variable);
540  }
541 
542  inline
543  void get(const std::string &name,
544  FloatParam &variable,
545  const float default_value,
546  const std::string description = "None.",
547  const float min = -100,
548  const float max = 100)
549  {
550  DynamicValue value;
551  value.type = DynamicValue::Float;
552  value.description = description;
553  value.Min.d = min;
554  value.Max.d = max;
555  value.Default.d = default_value;
556  value.flt = boost::shared_ptr<float>(new float);
557  values_[name] = value;
558 
559  variable.data = value.flt;
560  variable.mutex = mutex_;
561 
562  std::string resolved_name = nh_.resolveName(name);
563  //_used_params.insert(resolved_name);
564  nh_.param(name, *value.flt, default_value);
565  ROS_INFO("Read dynamic parameter %s = %f", name.c_str(), *variable);
566  }
567 
568  // for use with on change callbacks
569  inline
570  void get(const std::string &name,
571  double &variable,
572  const double default_value,
573  const std::string description = "None.",
574  const double min = -100,
575  const double max = 100)
576  {
577  DynamicValue value;
578  value.type = DynamicValue::Double;
579  value.description = description;
580  value.Min.d = min;
581  value.Max.d = max;
582  value.Default.d = default_value;
583  value.dbl = boost::shared_ptr<double>(new double);
584  values_[name] = value;
585 
586  std::string resolved_name = nh_.resolveName(name);
587  //_used_params.insert(resolved_name);
588  nh_.param(name, *value.dbl, default_value);
589  variable = *value.dbl;
590  ROS_INFO("Read dynamic parameter %s = %lf", name.c_str(), variable);
591  }
592 
593  inline
594  void get(const std::string &name,
595  DoubleParam &variable,
596  const double default_value,
597  const std::string description = "None.",
598  const double min = -100,
599  const double max = 100)
600  {
601  DynamicValue value;
602  value.type = DynamicValue::Double;
603  value.description = description;
604  value.Min.d = min;
605  value.Max.d = max;
606  value.Default.d = default_value;
607  value.dbl = boost::shared_ptr<double>(new double);
608  values_[name] = value;
609 
610  variable.data = value.dbl;
611  variable.mutex = mutex_;
612 
613  std::string resolved_name = nh_.resolveName(name);
614  //_used_params.insert(resolved_name);
615  nh_.param(name, *value.dbl, default_value);
616  ROS_INFO("Read dynamic parameter %s = %lf", name.c_str(), *variable);
617  }
618 
619  inline
620  void get(const std::string &name,
621  int &variable,
622  const int default_value,
623  const std::string description = "None.",
624  const int min = -100,
625  const int max = 100)
626  {
627  DynamicValue value;
628  value.type = DynamicValue::Int;
629  value.description = description;
630  value.Min.i = min;
631  value.Max.i = max;
632  value.Default.i = default_value;
633  value.integer = boost::shared_ptr<int>(new int);
634  values_[name] = value;
635 
636  std::string resolved_name = nh_.resolveName(name);
637  //_used_params.insert(resolved_name);
638  nh_.param(name, *value.integer, default_value);
639  variable = *value.integer;
640  ROS_INFO("Read dynamic parameter %s = %i", name.c_str(), variable);
641  }
642 
643  inline
644  void get(const std::string &name,
645  IntParam &variable,
646  const int default_value,
647  const std::string description = "None.",
648  const int min = -100,
649  const int max = 100)
650  {
651  DynamicValue value;
652  value.type = DynamicValue::Int;
653  value.description = description;
654  value.Min.i = min;
655  value.Max.i = max;
656  value.Default.i = default_value;
657  value.integer = boost::shared_ptr<int>(new int);
658  values_[name] = value;
659 
660  variable.data = value.integer;
661  variable.mutex = mutex_;
662 
663  std::string resolved_name = nh_.resolveName(name);
664  //_used_params.insert(resolved_name);
665  nh_.param(name, *value.integer, default_value);
666  ROS_INFO("Read dynamic parameter %s = %i", name.c_str(), *variable);
667  }
668 
669  // for use with on change callbacks
670  inline
671  void get(const std::string &name,
672  bool &variable,
673  const bool default_value,
674  const std::string description = "None.")
675  {
676  DynamicValue value;
677  value.type = DynamicValue::Bool;
678  value.description = description;
679  value.Default.b = default_value;
680  value.boolean = boost::shared_ptr<bool>(new bool);
681  values_[name] = value;
682 
683  std::string resolved_name = nh_.resolveName(name);
684  //_used_params.insert(resolved_name);
685  nh_.param(name, *value.boolean, default_value);
686  variable = *value.boolean;
687  ROS_INFO("Read dynamic parameter %s = %s", name.c_str(), variable ? "true" : "false");
688  }
689 
690  inline
691  void get(const std::string &name,
692  BoolParam &variable,
693  const bool default_value,
694  const std::string description = "None.")
695  {
696  DynamicValue value;
697  value.type = DynamicValue::Bool;
698  value.description = description;
699  value.Default.b = default_value;
700  value.boolean = boost::shared_ptr<bool>(new bool);
701  values_[name] = value;
702 
703  variable.data = value.boolean;
704  variable.mutex = mutex_;
705 
706  std::string resolved_name = nh_.resolveName(name);
707  //_used_params.insert(resolved_name);
708  nh_.param(name, *value.boolean, default_value);
709  ROS_INFO("Read dynamic parameter %s = %s", name.c_str(), *variable ? "true" : "false");
710  }
711 
712  // for use with on change callbacks
713  inline
714  void get(const std::string &name,
715  std::string &variable,
716  const std::string default_value,
717  const std::string description = "None.")
718  {
719  DynamicValue value;
720  value.type = DynamicValue::Bool;
721  value.description = description;
722  value.default_string = default_value;
723  value.str = boost::shared_ptr<std::string>(new std::string());
724  values_[name] = value;
725 
726  std::string resolved_name = nh_.resolveName(name);
727  //_used_params.insert(resolved_name);
728  nh_.param(name, *value.str, default_value);
729  variable = *value.str;
730  ROS_INFO("Read dynamic parameter %s = %s", name.c_str(), variable.c_str());
731  }
732 
733  inline
734  void get(const std::string &name,
735  StringParam &variable,
736  const std::string default_value,
737  const std::string description = "None.")
738  {
739  DynamicValue value;
740  value.type = DynamicValue::Bool;
741  value.description = description;
742  value.default_string = default_value;
743  value.str = boost::shared_ptr<std::string>(new std::string());
744  values_[name] = value;
745 
746  variable.data = value.str;
747  variable.mutex = mutex_;
748 
749  std::string resolved_name = nh_.resolveName(name);
750  //_used_params.insert(resolved_name);
751  nh_.param(name, *value.str, default_value);
752  ROS_INFO("Read dynamic parameter %s = %s", name.c_str(), (*variable).c_str());
753  }
754  };
755 } // namespace swri_param
756 #endif // SWRI_ROSCPP_DYNAMIC_PARAMETERS_H_
boost::shared_ptr< boost::mutex > mutex
void publish(const boost::shared_ptr< M > &message) const
std::string resolveName(const std::string &name, bool remap=true) const
void initialize(ros::NodeHandle &pnh)
void updateCurrent(dynamic_reconfigure::Config &config)
float getFloat(const std::string &name)
boost::shared_ptr< std::string > str
std::string getString(const std::string &name)
bool setConfigCallback(dynamic_reconfigure::Reconfigure::Request &req, dynamic_reconfigure::Reconfigure::Response &rsp)
std::map< std::string, DynamicValue > values_
bool getBool(const std::string &name)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
boost::shared_ptr< double > dbl
TypedParam< bool > BoolParam
union swri::DynamicValue::@1 Min
double getDouble(const std::string &name)
boost::mutex::scoped_lock lock_guard()
void setCallback(boost::function< void(DynamicParameters &)> fun)
static void param(const ros::NodeHandle &nh, const std::string &name, int &variable, const int default_value)
Definition: parameters.h:102
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
boost::shared_ptr< bool > boolean
def default_value(type)
boost::shared_ptr< boost::mutex > mutex_
boost::shared_ptr< float > flt
boost::shared_ptr< int > integer
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
TypedParam< double > DoubleParam
TypedParam< int > IntParam
boost::function< void(DynamicParameters &)> on_change_
TypedParam< std::string > StringParam
boost::shared_ptr< T > data
union swri::DynamicValue::@0 Default
int min(int a, int b)
TypedParam< float > FloatParam
std::string default_string
int getInt(const std::string &name)
ros::ServiceServer set_service_
union swri::DynamicValue::@2 Max
#define ROS_ERROR(...)
#define ROS_DEBUG(...)


swri_roscpp
Author(s):
autogenerated on Fri Jun 7 2019 22:05:50