param.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009, Willow Garage, Inc.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *   * Redistributions of source code must retain the above copyright notice,
00007  *     this list of conditions and the following disclaimer.
00008  *   * Redistributions in binary form must reproduce the above copyright
00009  *     notice, this list of conditions and the following disclaimer in the
00010  *     documentation and/or other materials provided with the distribution.
00011  *   * Neither the names of Willow Garage, Inc. nor the names of its
00012  *     contributors may be used to endorse or promote products derived from
00013  *     this software without specific prior written permission.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025  * POSSIBILITY OF SUCH DAMAGE.
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     // Lock around the execute to the master in case we get a parameter update on this value between
00061     // executing on the master and setting the parameter in the g_params list.
00062     boost::mutex::scoped_lock lock(g_params_mutex);
00063 
00064     if (master::execute("setParam", params, result, payload, true))
00065     {
00066       // Update our cached params list now so that if get() is called immediately after param::set()
00067       // we already have the cached state and our value will be correct
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   // construct xmlrpc_c::value object of the std::string and
00079   // call param::set(key, xmlvalue);
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   // construct xmlrpc_c::value object of the std::string and
00087   // call param::set(key, xmlvalue);
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   //params[1] = key;
00117   // We don't loop here, because validateXmlrpcResponse() returns false
00118   // both when we can't contact the master and when the master says, "I
00119   // don't have that param."
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   // We don't loop here, because validateXmlrpcResponse() returns false
00152   // both when we can't contact the master and when the master says, "I
00153   // don't have that param."
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       // parameter we've never seen before, register for update from the master
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   // We don't loop here, because validateXmlrpcResponse() returns false
00218   // both when we can't contact the master and when the master says, "I
00219   // don't have that param."
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   // searchParam needs a separate form of remapping -- remapping on the unresolved name, rather than the
00375   // resolved one.
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   // We don't loop here, because validateXmlrpcResponse() returns false
00386   // both when we can't contact the master and when the master says, "I
00387   // don't have that param."
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 } // namespace param
00488 
00489 } // namespace ros


roscpp
Author(s): Morgan Quigley mquigley@cs.stanford.edu, Josh Faust jfaust@willowgarage.com, Brian Gerkey gerkey@willowgarage.com, Troy Straszheim straszheim@willowgarage.com
autogenerated on Sat Dec 28 2013 17:35:52