rtt_rosparam_service.cpp
Go to the documentation of this file.
00001 #include <rtt/RTT.hpp>
00002 #include <rtt/plugin/ServicePlugin.hpp>
00003 #include <rtt/marsh/PropertyBagIntrospector.hpp>
00004 
00005 #include <ros/ros.h>
00006 #include <stack>
00007 
00008 using namespace RTT;
00009 using namespace std;
00010 
00011 class RosParam: public RTT::Service
00012 {
00013 public:
00014     RosParam(TaskContext* owner) :
00015         Service("rosparam", owner)
00016     {
00017         addOperation("storeProperties", &RosParam::storeProperties, this) .doc(
00018                 "Stores all properties of this component to the ros param server");
00019         addOperation("refreshProperties", &RosParam::refreshProperties, this).doc(
00020                 "Refreshes all properties of this component from the ros param server");
00021         addOperation("storeProperty", &RosParam::storeProperty, this) .doc(
00022                 "Stores one property of this component to the ros param server").arg(
00023                 "param_name", "Name of the property.").arg("private",
00024                 "true if parameter should be put in private namespace").arg(
00025                 "relative",
00026                 "true if parameter should be put in the relative (component name) namespace");
00027         addOperation("refreshProperty", &RosParam::refreshProperty, this) .doc(
00028                 "Refreshes one property of this component from the ros param server").arg(
00029                 "param_name", "Name of the property.").arg("private",
00030                 "true if parameter should be found the private namespace").arg(
00031                 "relative",
00032                 "true if parameter should be found in the relative (component name) namespace");
00033         this->doc("Store component properties on the ROS parameter server or refresh them using values on the ROS parameter server");
00034     }
00035 private:
00036 
00037     std::stack<XmlRpc::XmlRpcValue> value_stack;
00038 
00039     bool storeProperties()
00040     {
00041         Property<PropertyBag> bag(getOwner()->getName(), "");
00042         // decompose prop into primitive property types.
00043         marsh::PropertyBagIntrospector pbi(bag.value());
00044         pbi.introspect(*this->getOwner()->properties());
00045         if (PropertyToXmlRpcValue(&bag))
00046         {
00047             bool retval = true;
00048             assert(!value_stack.empty());
00049             try
00050             {
00051                 ros::param::set(string("~") + bag.getName(), value_stack.top());
00052             } catch (ros::InvalidNameException ex)
00053             {
00054                 log(Error) << ex.what() << endlog();
00055                 retval = false;
00056             }
00057             value_stack.pop();
00058             assert(value_stack.empty());
00059             return retval;
00060         }
00061         return false;
00062     }
00063     bool storeProperty(const string& prop_name, bool priv, bool rel)
00064     {
00065         base::PropertyBase* base = this->getOwner()->properties()->getProperty(
00066                 prop_name);
00067         if (base == NULL)
00068         {
00069             log(Error) << this->getOwner()->getName()
00070                     << " does not have a Property with name " << prop_name
00071                     << endlog();
00072             return false;
00073         }
00074         string param_name;
00075         if (priv)
00076             param_name = "~";
00077         if (rel)
00078             param_name += this->getOwner()->getName() + string("/");
00079         param_name += base->getName();
00080         if (PropertyToXmlRpcValue(base))
00081         {
00082             bool retval = true;
00083             assert(!value_stack.empty());
00084             try
00085             {
00086                 ros::param::set(param_name, value_stack.top());
00087             } catch (ros::InvalidNameException ex)
00088             {
00089                 log(Error) << ex.what() << endlog();
00090                 retval = false;
00091             }
00092             value_stack.pop();
00093             assert(value_stack.empty());
00094             return retval;
00095 
00096         }
00097         else
00098         {
00099             //check if base can be decomposed into a PropertyBag, if so we need to decompose it.
00100             PropertyBag bag;
00101             bag.add(base);
00102             // decompose prop into primitive property types.
00103             PropertyBag decomposed_bag;
00104             marsh::PropertyBagIntrospector pbi(decomposed_bag);
00105             pbi.introspect(bag);
00106             if (PropertyToXmlRpcValue(decomposed_bag.getProperty(
00107                     base->getName())))
00108             {
00109                 bool retval = true;
00110                 assert(!value_stack.empty());
00111                 try
00112                 {
00113                     ros::param::set(param_name, value_stack.top());
00114                 } catch (ros::InvalidNameException ex)
00115                 {
00116                     log(Error) << ex.what() << endlog();
00117                     retval = false;
00118                 }
00119                 value_stack.pop();
00120                 assert(value_stack.empty());
00121                 return retval;
00122             }
00123             return false;
00124         }
00125         return false;
00126     }
00127 
00128     bool PropertyToXmlRpcValue(base::PropertyBase* prop)
00129     {
00130         return PropertyToXmlRpcValue<bool> (
00131                 dynamic_cast<Property<bool>*> (prop)) || PropertyToXmlRpcValue<
00132                 int> (dynamic_cast<Property<int>*> (prop))
00133                 || PropertyToXmlRpcValue<double> (
00134                         dynamic_cast<Property<double>*> (prop))
00135                 || PropertyToXmlRpcValue<string> (dynamic_cast<Property<
00136                         std::string>*> (prop)) || PropertyToXmlRpcValue(
00137                 dynamic_cast<Property<PropertyBag>*> (prop));
00138     }
00139 
00140     template<class T>
00141     bool PropertyToXmlRpcValue(Property<T>* prop)
00142     {
00143         if (!prop)
00144             return false;
00145 
00146         value_stack.push(XmlRpc::XmlRpcValue(prop->rvalue()));
00147         return true;
00148     }
00149 
00150     bool PropertyToXmlRpcValue(Property<PropertyBag>* prop)
00151     {
00152         if (!prop)
00153             return false;
00154         PropertyBag& bag = prop->value();
00155         XmlRpc::XmlRpcValue dict;
00156         for (size_t i = 0; i < bag.size(); i++)
00157         {
00158             if (PropertyToXmlRpcValue(bag.getItem(i)))
00159             {
00160                 if (!bag.getItem(i)->getName().empty() && bag.getType()
00161                         != "array")
00162                     dict[bag.getItem(i)->getName()] = value_stack.top();
00163                 else
00164                     dict[i] = value_stack.top();
00165                 value_stack.pop();
00166             }
00167         }
00168         if (bag.size() == 0)
00169             log(Warning) << "Exporting empty property bag " << prop->getName()
00170                     << endlog();
00171         value_stack.push(dict);
00172         return true;
00173     }
00174 
00175     bool refreshProperties()
00176     {
00177         XmlRpc::XmlRpcValue rpcval;
00178         try
00179         {
00180             if (!ros::param::get(string("~") + this->getOwner()->getName(),
00181                     rpcval))
00182             {
00183                 log(Error)
00184                         << "The parameter server does not have a Property with name "
00185                         << this->getOwner()->getName() << endlog();
00186                 return false;
00187             }
00188         } catch (ros::InvalidNameException ex)
00189         {
00190             log(Error) << ex.what() << endlog();
00191             return false;
00192         }
00193         Property<PropertyBag> bag(getOwner()->getName(), "");
00194         // decompose prop into primitive property types.
00195         marsh::PropertyBagIntrospector pbi(bag.value());
00196         pbi.introspect(*this->getOwner()->properties());
00197         for (PropertyBag::iterator it = bag.value().begin(); it
00198                 != bag.value().end(); ++it)
00199         {
00200             if (rpcval.hasMember((*it)->getName()))
00201             {
00202                 if (!XmlRpcValueToProperty(rpcval[(*it)->getName()], (*it)))
00203                     log(Warning) << "Could not update Property "
00204                             << (*it)->getName() << endlog();
00205                 base::PropertyBase* base =
00206                         this->getOwner()->properties()->getProperty(
00207                                 (*it)->getName());
00208                 if (!base->getTypeInfo()->composeType((*it)->getDataSource(),
00209                         base->getDataSource()))
00210                     log(Warning)<<"Could not compose "<<base->getName()<<endlog();
00211             }
00212             else
00213                 log(Warning) << "Could not find Property " << (*it)->getName()
00214                         << endlog();
00215         }
00216         return true;
00217     }
00218 
00219     bool refreshProperty(const string& prop_name, bool priv, bool rel)
00220     {
00221         base::PropertyBase* base = this->getOwner()->properties()->getProperty(
00222                 prop_name);
00223         if (base == NULL)
00224         {
00225             log(Error) << this->getOwner()->getName()
00226                     << " does not have a Property with name " << prop_name
00227                     << endlog();
00228             return false;
00229         }
00230         string param_name;
00231         if (priv)
00232             param_name = "~";
00233         if (rel)
00234             param_name += this->getOwner()->getName() + string("/");
00235         param_name += base->getName();
00236         XmlRpc::XmlRpcValue rpcval;
00237         try
00238         {
00239             if (!ros::param::get(param_name, rpcval))
00240             {
00241                 log(Error)
00242                         << "The parameter server does not have a Property with name "
00243                         << param_name << endlog();
00244                 return false;
00245             }
00246         } catch (ros::InvalidNameException ex)
00247         {
00248             log(Error) << ex.what() << endlog();
00249             return false;
00250         }
00251         PropertyBag bag;
00252         bag.add(base);
00253         // decompose prop into primitive property types.
00254         PropertyBag decomposed_bag;
00255         marsh::PropertyBagIntrospector pbi(decomposed_bag);
00256         pbi.introspect(bag);
00257         if (!XmlRpcValueToProperty(rpcval, decomposed_bag.getProperty(
00258                 base->getName())))
00259             return false;
00260         if (base->getTypeInfo()->composeType(decomposed_bag.getProperty(
00261                 base->getName())->getDataSource(), base->getDataSource()))
00262             return true;
00263         return false;
00264     }
00265 
00266     bool XmlRpcValueToProperty(XmlRpc::XmlRpcValue &val,
00267             base::PropertyBase* prop)
00268     {
00269         switch (val.getType())
00270         {
00271         case XmlRpc::XmlRpcValue::TypeBoolean:
00272         {
00273             Property<bool> tmp("");
00274             tmp.set(val);
00275             if (prop->refresh(&tmp))
00276                 return true;
00277             return false;
00278         }
00279         case XmlRpc::XmlRpcValue::TypeDouble:
00280         {
00281             Property<double> tmp("");
00282             tmp.set(val);
00283             if (prop->refresh(&tmp))
00284                 return true;
00285             return false;
00286         }
00287         case XmlRpc::XmlRpcValue::TypeInt:
00288         {
00289             Property<int> tmp("");
00290             tmp.set(val);
00291             if (prop->refresh(&tmp))
00292                 return true;
00293             return false;
00294         }
00295         case XmlRpc::XmlRpcValue::TypeString:
00296         {
00297             Property<std::string> tmp("");
00298             tmp.set(val);
00299             if (prop->refresh(&tmp))
00300                 return true;
00301             return false;
00302         }
00303         case XmlRpc::XmlRpcValue::TypeArray:
00304         {
00305             Property<PropertyBag> bag("");
00306             bag = prop;
00307             if (!bag.ready())
00308                 return false;
00309             if (val.size() != (int) bag.value().size())
00310                 return false;
00311             for (int i = 0; i < val.size(); i++)
00312             {
00313                 if (!XmlRpcValueToProperty(val[i], bag.value().getItem(i)))
00314                     return false;
00315             }
00316             //is this necessary?
00317             if (prop->getTypeInfo()->composeType(bag.getDataSource(),
00318                     prop->getDataSource()))
00319                 return true;
00320             return false;
00321         }
00322         case XmlRpc::XmlRpcValue::TypeStruct:
00323         {
00324             Property<PropertyBag> bag("");
00325             bag = prop;
00326             if (!bag.ready())
00327                 return false;
00328             if (bag.value().empty())
00329             {
00330                 log(Warning) << "Could not update " << prop->getName()
00331                         << endlog();
00332                 return false;
00333             }
00334             for (PropertyBag::iterator it = bag.value().begin(); it
00335                     != bag.value().end(); ++it)
00336             {
00337                 if (val.hasMember((*it)->getName()))
00338                 {
00339                     if (!XmlRpcValueToProperty(val[(*it)->getName()],
00340                             bag.value().getProperty((*it)->getName())))
00341                         log(Warning) << "Could not convert "
00342                                 << (*it)->getName() << " from XmlRpcValue"
00343                                 << endlog();
00344                 }
00345                 else
00346                     log(Warning) << "Could not find " << (*it)->getName()
00347                             << " in " << prop->getName() << endlog();
00348             }
00349             //is this necessary?
00350             if (prop->getTypeInfo()->composeType(bag.getDataSource(),
00351                     prop->getDataSource()))
00352                 return true;
00353             return false;
00354         }
00355         default:
00356         {
00357             log(Warning) << "Cannot handle the type of " << prop->getName()
00358                     << endlog();
00359             return false;
00360         }
00361         }
00362     }
00363 
00364 };
00365 
00366 
00367 ORO_SERVICE_NAMED_PLUGIN(RosParam, "rosparam")


rtt_rosnode
Author(s): Ruben Smits, ruben.smits@mech.kuleuven.be
autogenerated on Mon Oct 6 2014 07:24:21