sync_params.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
2 #include <ros/console.h>
3 #include <vector>
4 #include <map>
5 #include <regex>
6 #include <algorithm>
7 #include <chrono>
8 #include <thread>
9 #include <sync_params/ParameterMsg.h>
10 
11 /* Nick Sullivan, The University of Adelaide, 2018.
12  This file periodically reads from the parameter server, publishes it to a
13  global topic, then writes to the parameter server. It's intended to work
14  accross multiple masters in multi_master_fkie setups.
15 
16  The parameter server is read in as an XmlRpcValue, turned into an XML string
17  to be published, then restored into an XmlRpcValue.
18 */
19 
20 using std::cout;
21 using std::endl;
22 using std::map;
23 using std::string;
24 using std::vector;
25 using sync_params::ParameterMsg;
26 
27 bool debug; //extra printouts if true
28 bool use_wall_time; //explanation in 'main'
29 bool use_death_timer; //if node should die after some time
30 double death_timer; //seconds
31 double rate; //parameter poll rate
32 ros::NodeHandle* n_ptr; //to write to the parameter server
33 map<string, string> param_map; //stores parameters we've seen already
34 
35 vector<string> blacklist;
36 vector<string> whitelist;
37 
40 
41 /**************************************************
42  * Helper functions
43  **************************************************/
44 
45 // From https://stackoverflow.com/questions/20406744
46 // /how-to-find-and-replace-all-occurrences-of-a-substring-in-a-string
47 string replaceAll(string const& original, string const& from, string const& to) {
48  string results;
49  string::const_iterator end = original.end();
50  string::const_iterator current = original.begin();
51  string::const_iterator next = std::search( current, end, from.begin(), from.end() );
52  while ( next != end ) {
53  results.append( current, next );
54  results.append( to );
55  current = next + from.size();
56  next = std::search( current, end, from.begin(), from.end() );
57  }
58  results.append( current, next );
59  return results;
60 }
61 
62 /**************************************************
63  * Whitelist/Blacklist functions
64  **************************************************/
65 
66 bool isOnBlackList( string key ){
67  if(debug) ROS_WARN_STREAM("Blacklist check: " << key);
68  for( int i=0; i< blacklist.size(); i++ ){
69  std::regex reg(blacklist[i]);
70  if( regex_match(key, reg) ){
71  if(debug) ROS_WARN_STREAM(" TRUE ");;
72  return true;
73  }
74  }
75  if(debug) ROS_WARN_STREAM(" FALSE ");
76  return false;
77 }
78 
79 bool isOnWhiteList( string key ){
80  if(debug) ROS_WARN_STREAM("Whitelist check: " << key);
81  for( int i=0; i< whitelist.size(); i++ ){
82  std::regex reg(whitelist[i]);
83  if( regex_match(key, reg) ){
84  if(debug) ROS_WARN_STREAM(" TRUE " <<endl);
85  return true;
86  }
87  }
88  if(debug) ROS_WARN_STREAM( " FALSE " <<endl);
89  return false;
90 }
91 
92 /**************************************************
93  * Publisher functions
94  **************************************************/
95 
96 void publishParam(ParameterMsg param){
97  if(debug) ROS_WARN_STREAM("Publishing: " << param.key);
98  param_pub.publish(param);
99 }
100 
101 /**************************************************
102  * Subscriber functions
103  **************************************************/
104 
105 // Writes a parameter to the parameter server, if the parameter is new.
106 void subscribeParam(const ParameterMsg::ConstPtr& msg) {
107  string key = msg->key;
108  string xml = msg->xml;
109  if( isOnBlackList(key) && !isOnWhiteList(key) ) return;
110  bool new_entry = param_map.insert( make_pair(key,xml) ).second;
111  if( !new_entry ){
112  return;
113  }
114  if(debug) ROS_WARN_STREAM("SyncParams: Synchronising parameter [" << key << "]");
115  int offset = 0;
116  string const &xml2 = xml;
117  XmlRpc::XmlRpcValue v(xml2, &offset);
118  n_ptr->setParam(key, v);
119 }
120 
121 /**************************************************
122  * Initialising functions
123  **************************************************/
124 
126  param_sub = n.subscribe("/params", 100, subscribeParam);
127 }
128 
130  param_pub = n.advertise<sync_params::ParameterMsg>("/params", 100);
131 }
132 
135  string s;
136  if( n_priv.getParam("whitelist", v) ){
138  for(int i=0; i < v.size(); i++) {
139  s = replaceAll( v[i] , "*", ".*");
140  whitelist.push_back(s);
141  }
142  }
143  if( n_priv.getParam("blacklist", v) ){
145  for(int i=0; i < v.size(); i++) {
146  s = replaceAll( v[i] , "*", ".*");
147  blacklist.push_back(s);
148  }
149  }
150  n_priv.param("debug", debug, false);
151  n_priv.param("use_wall_time", use_wall_time, false);
152  n_priv.param("rate", rate, 1.0);
153  n_priv.param("death_timer", death_timer, -1.0);
154  use_death_timer = false;
155  if( death_timer > 0.0 ){
156  use_death_timer = true;
157  }
158 }
159 
160 /**************************************************
161  * Main
162  **************************************************/
163 
164 // We might not use the in-built ROS rate because deadlock can occur for gazebo
165 // spawning. Basically Gazebo pauses the clock when loading a robot, and it
166 // waits for the robot_description parameter. But that parameter never gets
167 // synced without the clock going.
168 int main(int argc, char** argv){
169  ros::init(argc, argv, "sync_params");
170  ros::NodeHandle n;
171  ros::NodeHandle n_priv("~");
172  n_ptr = &n;
173  loadPubs(n);
174  loadSubs(n);
175  loadParams(n_priv);
176 
177  string key;
179  ParameterMsg msg;
180  vector<string> param_keys;
181  ros::Time start_time = ros::Time::now();
182  bool dead = false;
183 
184  ros::Rate r(rate);
185  ros::WallRate wr(rate);
186  while( ros::ok() ){
187  // For each key, add it to the map and publish.
188  n.getParamNames(param_keys);
189  for( int i=0; i<param_keys.size(); i++ ){
190  key = param_keys[i];
191  if( isOnBlackList(key) && !isOnWhiteList(key) ) continue;
192  n_ptr->getParam(key, v);
193  msg.key = key;
194  msg.xml = v.toXml();
195  publishParam(msg);
196  }
197  // Handle callbacks.
198  ros::spinOnce();
199  if( use_wall_time ){
200  wr.sleep();
201  } else {
202  r.sleep();
203  }
204  if( use_death_timer && ros::Time::now()-start_time > ros::Duration(death_timer) ){
205  ROS_INFO("SyncParams has finished polling.");
206  ros::spin();
207  }
208  }
209  return 0;
210 };
211 
ros::Subscriber param_sub
Definition: sync_params.cpp:39
bool debug
Definition: sync_params.cpp:27
bool use_death_timer
Definition: sync_params.cpp:29
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle * n_ptr
Definition: sync_params.cpp:32
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
int size() const
XmlRpcServer s
vector< string > blacklist
Definition: sync_params.cpp:35
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
double rate
Definition: sync_params.cpp:31
void publishParam(ParameterMsg param)
Definition: sync_params.cpp:96
bool isOnWhiteList(string key)
Definition: sync_params.cpp:79
bool isOnBlackList(string key)
Definition: sync_params.cpp:66
Type const & getType() const
void subscribeParam(const ParameterMsg::ConstPtr &msg)
std::string toXml() const
void loadSubs(ros::NodeHandle n)
string replaceAll(string const &original, string const &from, string const &to)
Definition: sync_params.cpp:47
#define ROS_INFO(...)
bool use_wall_time
Definition: sync_params.cpp:28
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ROSCPP_DECL bool ok()
double death_timer
Definition: sync_params.cpp:30
bool getParamNames(std::vector< std::string > &keys) const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ROSCPP_DECL void spin()
vector< string > whitelist
Definition: sync_params.cpp:36
#define ROS_WARN_STREAM(args)
map< string, string > param_map
Definition: sync_params.cpp:33
bool sleep()
void loadParams(ros::NodeHandle n_priv)
void loadPubs(ros::NodeHandle n)
bool getParam(const std::string &key, std::string &s) const
static Time now()
#define ROS_ASSERT(cond)
ROSCPP_DECL void spinOnce()
int main(int argc, char **argv)
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const
ros::Publisher param_pub
Definition: sync_params.cpp:38


sync_params
Author(s): Nick Sullivan
autogenerated on Mon Jun 10 2019 15:26:23