00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "ros/param.h"
00029 #include "ros/master.h"
00030 #include "ros/xmlrpc_manager.h"
00031 #include "ros/this_node.h"
00032 #include "ros/names.h"
00033
00034 #include <ros/console.h>
00035
00036 #include <boost/thread/mutex.hpp>
00037 #include <boost/lexical_cast.hpp>
00038
00039 namespace ros
00040 {
00041
00042 namespace param
00043 {
00044
00045 typedef std::map<std::string, XmlRpc::XmlRpcValue> M_Param;
00046 M_Param g_params;
00047 boost::mutex g_params_mutex;
00048 S_string g_subscribed_params;
00049
00050 void set(const std::string &key, const XmlRpc::XmlRpcValue &v)
00051 {
00052 std::string mapped_key = ros::names::resolve(key);
00053
00054 XmlRpc::XmlRpcValue params, result, payload;
00055 params[0] = this_node::getName();
00056 params[1] = mapped_key;
00057 params[2] = v;
00058
00059 {
00060
00061
00062 boost::mutex::scoped_lock lock(g_params_mutex);
00063
00064 if (master::execute("setParam", params, result, payload, true))
00065 {
00066
00067
00068 if (g_subscribed_params.find(mapped_key) != g_subscribed_params.end())
00069 {
00070 g_params[mapped_key] = v;
00071 }
00072 }
00073 }
00074 }
00075
00076 void set(const std::string &key, const std::string &s)
00077 {
00078
00079
00080 XmlRpc::XmlRpcValue v(s);
00081 ros::param::set(key, v);
00082 }
00083
00084 void set(const std::string &key, const char* s)
00085 {
00086
00087
00088 std::string sxx = std::string(s);
00089 XmlRpc::XmlRpcValue v(sxx);
00090 ros::param::set(key, v);
00091 }
00092
00093 void set(const std::string &key, double d)
00094 {
00095 XmlRpc::XmlRpcValue v(d);
00096 ros::param::set(key, v);
00097 }
00098
00099 void set(const std::string &key, int i)
00100 {
00101 XmlRpc::XmlRpcValue v(i);
00102 ros::param::set(key, v);
00103 }
00104
00105 void set(const std::string& key, bool b)
00106 {
00107 XmlRpc::XmlRpcValue v(b);
00108 ros::param::set(key, v);
00109 }
00110
00111 bool has(const std::string &key)
00112 {
00113 XmlRpc::XmlRpcValue params, result, payload;
00114 params[0] = this_node::getName();
00115 params[1] = ros::names::resolve(key);
00116
00117
00118
00119
00120 if (!master::execute("hasParam", params, result, payload, false))
00121 {
00122 return false;
00123 }
00124
00125 return payload;
00126 }
00127
00128 bool del(const std::string &key)
00129 {
00130 std::string mapped_key = ros::names::resolve(key);
00131
00132 {
00133 boost::mutex::scoped_lock lock(g_params_mutex);
00134
00135 S_string::iterator sub_it = g_subscribed_params.find(mapped_key);
00136 if (sub_it != g_subscribed_params.end())
00137 {
00138 g_subscribed_params.erase(sub_it);
00139
00140 M_Param::iterator param_it = g_params.find(mapped_key);
00141 if (param_it != g_params.end())
00142 {
00143 g_params.erase(param_it);
00144 }
00145 }
00146 }
00147
00148 XmlRpc::XmlRpcValue params, result, payload;
00149 params[0] = this_node::getName();
00150 params[1] = mapped_key;
00151
00152
00153
00154 if (!master::execute("deleteParam", params, result, payload, false))
00155 {
00156 return false;
00157 }
00158
00159 return true;
00160 }
00161
00162 bool getImpl(const std::string &key, XmlRpc::XmlRpcValue &v, bool use_cache)
00163 {
00164 std::string mapped_key = ros::names::resolve(key);
00165
00166 if (use_cache)
00167 {
00168 boost::mutex::scoped_lock lock(g_params_mutex);
00169
00170 if (g_subscribed_params.find(mapped_key) != g_subscribed_params.end())
00171 {
00172 M_Param::iterator it = g_params.find(mapped_key);
00173 if (it != g_params.end())
00174 {
00175 if (it->second.valid())
00176 {
00177 ROS_DEBUG_NAMED("cached_parameters", "Using cached parameter value for key [%s]", mapped_key.c_str());
00178
00179 v = it->second;
00180 return true;
00181 }
00182 else
00183 {
00184 ROS_DEBUG_NAMED("cached_parameters", "Cached parameter is invalid for key [%s]", mapped_key.c_str());
00185 return false;
00186 }
00187 }
00188 }
00189 else
00190 {
00191
00192 if (g_subscribed_params.insert(mapped_key).second)
00193 {
00194 XmlRpc::XmlRpcValue params, result, payload;
00195 params[0] = this_node::getName();
00196 params[1] = XMLRPCManager::instance()->getServerURI();
00197 params[2] = mapped_key;
00198
00199 if (!master::execute("subscribeParam", params, result, payload, false))
00200 {
00201 ROS_DEBUG_NAMED("cached_parameters", "Subscribe to parameter [%s]: call to the master failed", mapped_key.c_str());
00202 g_subscribed_params.erase(mapped_key);
00203 use_cache = false;
00204 }
00205 else
00206 {
00207 ROS_DEBUG_NAMED("cached_parameters", "Subscribed to parameter [%s]", mapped_key.c_str());
00208 }
00209 }
00210 }
00211 }
00212
00213 XmlRpc::XmlRpcValue params, result;
00214 params[0] = this_node::getName();
00215 params[1] = mapped_key;
00216
00217
00218
00219
00220 bool ret = master::execute("getParam", params, result, v, false);
00221
00222 if (use_cache)
00223 {
00224 boost::mutex::scoped_lock lock(g_params_mutex);
00225
00226 ROS_DEBUG_NAMED("cached_parameters", "Caching parameter [%s] with value type [%d]", mapped_key.c_str(), v.getType());
00227 g_params[mapped_key] = v;
00228 }
00229
00230 return ret;
00231 }
00232
00233 bool getImpl(const std::string &key, std::string &s, bool use_cache)
00234 {
00235 XmlRpc::XmlRpcValue v;
00236 if (!getImpl(key, v, use_cache))
00237 return false;
00238 if (v.getType() != XmlRpc::XmlRpcValue::TypeString)
00239 return false;
00240 s = std::string(v);
00241 return true;
00242 }
00243
00244 bool getImpl(const std::string &key, double &d, bool use_cache)
00245 {
00246 XmlRpc::XmlRpcValue v;
00247 if (!getImpl(key, v, use_cache))
00248 {
00249 return false;
00250 }
00251
00252 if (v.getType() == XmlRpc::XmlRpcValue::TypeInt)
00253 {
00254 d = (int)v;
00255 }
00256 else if (v.getType() != XmlRpc::XmlRpcValue::TypeDouble)
00257 {
00258 return false;
00259 }
00260 else
00261 {
00262 d = v;
00263 }
00264
00265 return true;
00266 }
00267
00268 bool getImpl(const std::string &key, int &i, bool use_cache)
00269 {
00270 XmlRpc::XmlRpcValue v;
00271 if (!getImpl(key, v, use_cache))
00272 {
00273 return false;
00274 }
00275
00276 if (v.getType() == XmlRpc::XmlRpcValue::TypeDouble)
00277 {
00278 double d = v;
00279
00280 if (fmod(d, 1.0) < 0.5)
00281 {
00282 d = floor(d);
00283 }
00284 else
00285 {
00286 d = ceil(d);
00287 }
00288
00289 i = d;
00290 }
00291 else if (v.getType() != XmlRpc::XmlRpcValue::TypeInt)
00292 {
00293 return false;
00294 }
00295 else
00296 {
00297 i = v;
00298 }
00299
00300 return true;
00301 }
00302
00303 bool getImpl(const std::string &key, bool &b, bool use_cache)
00304 {
00305 XmlRpc::XmlRpcValue v;
00306 if (!getImpl(key, v, use_cache))
00307 return false;
00308 if (v.getType() != XmlRpc::XmlRpcValue::TypeBoolean)
00309 return false;
00310 b = v;
00311 return true;
00312 }
00313
00314 bool get(const std::string& key, std::string& s)
00315 {
00316 return getImpl(key, s, false);
00317 }
00318
00319 bool get(const std::string& key, double& d)
00320 {
00321 return getImpl(key, d, false);
00322 }
00323
00324 bool get(const std::string& key, int& i)
00325 {
00326 return getImpl(key, i, false);
00327 }
00328
00329 bool get(const std::string& key, bool& b)
00330 {
00331 return getImpl(key, b, false);
00332 }
00333
00334 bool get(const std::string& key, XmlRpc::XmlRpcValue& v)
00335 {
00336 return getImpl(key, v, false);
00337 }
00338
00339 bool getCached(const std::string& key, std::string& s)
00340 {
00341 return getImpl(key, s, true);
00342 }
00343
00344 bool getCached(const std::string& key, double& d)
00345 {
00346 return getImpl(key, d, true);
00347 }
00348
00349 bool getCached(const std::string& key, int& i)
00350 {
00351 return getImpl(key, i, true);
00352 }
00353
00354 bool getCached(const std::string& key, bool& b)
00355 {
00356 return getImpl(key, b, true);
00357 }
00358
00359 bool getCached(const std::string& key, XmlRpc::XmlRpcValue& v)
00360 {
00361 return getImpl(key, v, true);
00362 }
00363
00364 bool search(const std::string& key, std::string& result_out)
00365 {
00366 return search(this_node::getName(), key, result_out);
00367 }
00368
00369 bool search(const std::string& ns, const std::string& key, std::string& result_out)
00370 {
00371 XmlRpc::XmlRpcValue params, result, payload;
00372 params[0] = ns;
00373
00374
00375
00376
00377 std::string remapped = key;
00378 M_string::const_iterator it = names::getUnresolvedRemappings().find(key);
00379 if (it != names::getUnresolvedRemappings().end())
00380 {
00381 remapped = it->second;
00382 }
00383
00384 params[1] = remapped;
00385
00386
00387
00388 if (!master::execute("searchParam", params, result, payload, false))
00389 {
00390 return false;
00391 }
00392
00393 result_out = (std::string)payload;
00394
00395 return true;
00396 }
00397
00398 void update(const std::string& key, const XmlRpc::XmlRpcValue& v)
00399 {
00400 std::string clean_key = names::clean(key);
00401 ROS_DEBUG_NAMED("cached_parameters", "Received parameter update for key [%s]", clean_key.c_str());
00402
00403 boost::mutex::scoped_lock lock(g_params_mutex);
00404
00405 g_params[clean_key] = v;
00406 }
00407
00408 void paramUpdateCallback(XmlRpc::XmlRpcValue& params, XmlRpc::XmlRpcValue& result)
00409 {
00410 result[0] = 1;
00411 result[1] = std::string("");
00412 result[2] = 0;
00413
00414 ros::param::update((std::string)params[1], params[2]);
00415 }
00416
00417 void init(const M_string& remappings)
00418 {
00419 M_string::const_iterator it = remappings.begin();
00420 M_string::const_iterator end = remappings.end();
00421 for (; it != end; ++it)
00422 {
00423 const std::string& name = it->first;
00424 const std::string& param = it->second;
00425
00426 if (name.size() < 2)
00427 {
00428 continue;
00429 }
00430
00431 if (name[0] == '_' && name[1] != '_')
00432 {
00433 std::string local_name = "~" + name.substr(1);
00434
00435 bool success = false;
00436
00437 try
00438 {
00439 int32_t i = boost::lexical_cast<int32_t>(param);
00440 ros::param::set(names::resolve(local_name), i);
00441 success = true;
00442 }
00443 catch (boost::bad_lexical_cast&)
00444 {
00445
00446 }
00447
00448 if (success)
00449 {
00450 continue;
00451 }
00452
00453 try
00454 {
00455 double d = boost::lexical_cast<double>(param);
00456 ros::param::set(names::resolve(local_name), d);
00457 success = true;
00458 }
00459 catch (boost::bad_lexical_cast&)
00460 {
00461
00462 }
00463
00464 if (success)
00465 {
00466 continue;
00467 }
00468
00469 if (param == "true" || param == "True" || param == "TRUE")
00470 {
00471 ros::param::set(names::resolve(local_name), true);
00472 }
00473 else if (param == "false" || param == "False" || param == "FALSE")
00474 {
00475 ros::param::set(names::resolve(local_name), false);
00476 }
00477 else
00478 {
00479 ros::param::set(names::resolve(local_name), param);
00480 }
00481 }
00482 }
00483
00484 XMLRPCManager::instance()->bind("paramUpdate", paramUpdateCallback);
00485 }
00486
00487 }
00488
00489 }