Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 #ifndef ROSOPTION_HPP_
00009 #define ROSOPTION_HPP_
00010 
00011 #include <telekyb_defines/telekyb_defines.hpp>
00012 #include <telekyb_base/ROS/ROSOptionController.hpp>
00013 #include <telekyb_base/Tools/XmlRpcConversion.hpp>
00014 
00015 
00016 #include <telekyb_base/Tools/YamlHelper.hpp>
00017 
00018 
00019 #include <telekyb_base/Tools/OperatorOverload.hpp>
00020 
00021 
00022 #include <telekyb_srvs/StringInput.h>
00023 #include <telekyb_srvs/StringOutput.h>
00024 
00025 namespace TELEKYB_NAMESPACE
00026 {
00027 
00028 template < class _T >
00029 class ROSOption : public ROSBaseOption, public OptionListener<_T>
00030 {
00031 protected:
00032         
00033         Option<_T>* option;
00034         _T valueOnRos;
00035 
00036         
00037         
00038         ros::ServiceServer getService;
00039         ros::ServiceServer setService;
00040 
00041         bool getServiceCallBack(
00042                         telekyb_srvs::StringOutput::Request& request,
00043                         telekyb_srvs::StringOutput::Response& response) {
00044                 ROS_INFO_STREAM("SYNC: Option " << option->getNSName() << " received getSerivce . Answered: " << YamlHelper::parseValueToString(option->getValue()));
00045 
00046                 return YamlHelper::parseValueToString(option->getValue(), response.output);
00047         }
00048 
00049         bool setServiceCallBack(
00050                         telekyb_srvs::StringInput::Request& request,
00051                         telekyb_srvs::StringInput::Response& response) {
00052                 
00053 
00054                 
00055                 YAML::Node node;
00056                 if ( ! YamlHelper::parseStringToNode(request.input, node)) {
00057                         ROS_INFO_STREAM("SYNC: Option " << option->getNSName() << " unable to convert from Yaml." );
00058                         return false;
00059                 }
00060 
00061                 return option->set(node);
00062 
00063 
00064 
00065 
00066 
00067 
00068                 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083                 
00084 
00085 
00086 
00087         }
00088 
00089         
00090         virtual void createGetService() {
00091                 
00092                 if (!ROSOptionController::hasInstance()) {
00093                         ROS_ERROR_STREAM("createSetService() called on ROSOption " << option->getNSName() << ", ROSOptionController is not initialized yet.");
00094                         return;
00095                 }
00096                 ros::NodeHandle serviceHandle(ROSOptionController::Instance().getOptionNodeHandle(), getNSName());
00097                 getService = serviceHandle.advertiseService(OPTION_GETSERVICE_NAME, &ROSOption::getServiceCallBack, this);
00098         }
00099 
00100         
00101         virtual void createSetService() {
00102                 
00103                 if (!ROSOptionController::hasInstance()) {
00104                         ROS_ERROR_STREAM("createSetService() called on ROSOption " << option->getNSName() << ", ROSOptionController is not initialized yet.");
00105                         return;
00106                 }
00107                 ros::NodeHandle serviceHandle(ROSOptionController::Instance().getOptionNodeHandle(), getNSName());
00108                 setService = serviceHandle.advertiseService(OPTION_SETSERVICE_NAME, &ROSOption::setServiceCallBack, this);
00109         }
00110 
00111         virtual void shutdownGetService() {
00112                 getService.shutdown();
00113         }
00114 
00115         virtual void shutdownSetService() {
00116                 setService.shutdown();
00117         }
00118 
00119         
00120 
00121         
00122         virtual void setToParameterServer() {
00123                 if (!ROSOptionController::hasInstance()) {
00124                         ROS_ERROR_STREAM("setToParameterServer() called on ROSOption " << option->getNSName() << ", ROSOptionController is not initialized yet.");
00125                         return;
00126                 }
00127                 XmlRpc::XmlRpcValue value;
00128                 
00129                 
00130                 
00131                 try {
00132                         option->getValue() >> value;
00133                         ros::NodeHandle optionHandle = ROSOptionController::Instance().getOptionNodeHandle();
00134                         optionHandle.setParam(option->getNSName(), value);
00135                         valueOnRos = option->getValue();
00136                 } catch (XmlRpc::XmlRpcException &e) {
00137                         ROS_ERROR_STREAM("Could not convert Option " << option->getNSName() << " to XmlRpcValue! " << e.getMessage());
00138                 }
00139         }
00140 
00141         virtual bool updateFromParameterServer() {
00142                 if (!ROSOptionController::hasInstance()) {
00143                         ROS_ERROR_STREAM("updateFromParameterServer() called on ROSOption " << option->getNSName() << ", ROSOptionController is not initialized yet.");
00144                         return false;
00145                 }
00146 
00147                 ros::NodeHandle optionHandle = ROSOptionController::Instance().getOptionNodeHandle();
00148 
00149                 XmlRpc::XmlRpcValue value;
00150                 optionHandle.getParam(option->getNSName(), value);
00151 
00152                 
00153                 
00154 
00155 
00156                 
00157 
00158                 
00159                 try {
00160                         value >> valueOnRos;
00161                 } catch (XmlRpc::XmlRpcException &e) {
00162                         
00163                         ROS_ERROR_STREAM("Could not convert Option " << option->getNSName() << " FROM XmlRpcValue! " << e.getMessage() << " Reverting..");
00164                         setToParameterServer();
00165                         return false;
00166                 }
00167                 
00168 
00169                 if (valueOnRos == option->getValue()) {
00170                         
00171                         return true;
00172                 }
00173                 
00174 
00175                 if (option->isReadOnly()) {
00176                         
00177                         ROS_WARN_STREAM("ASYNC: Read-only Option " << option->getNSName() << " was changed on ROS Parameter server. Reverting...");
00178                         setToParameterServer();
00179                         return false;
00180                 }
00181                 
00182 
00183                 
00184                 if (option->hasBounds() && !option->isWithinBounds(valueOnRos)) {
00185                         ROS_WARN_STREAM("ASYNC: Option " << option->getNSName() << " was changed on ROS Parameter server, but is out of bounds! Reverting...");
00186                         setToParameterServer();
00187                         return false;
00188                 }
00189                 
00190 
00191                 
00192                 ROS_INFO_STREAM("ASYNC: Updating Option " << option->getNSName() << " to " << YamlHelper::parseValueToString(valueOnRos));
00193                 option->setValue(valueOnRos);
00194 
00195                 return true;
00196         }
00197 
00198         virtual bool deleteFromParameterServer() {
00199                 if (!ROSOptionController::hasInstance()) {
00200                         ROS_ERROR_STREAM("deleteFromParameterServer() called on ROSOption " << option->getNSName() << ", ROSOptionController is not initialized yet.");
00201 
00202 
00203                         return false;
00204                 }
00205 
00206                 
00207 
00208                 ros::NodeHandle optionHandle = ROSOptionController::Instance().getOptionNodeHandle();
00209 
00210                 return optionHandle.deleteParam(option->getNSName());
00211         }
00212 
00213         friend class ROSOptionController;
00214 
00215 public:
00216         ROSOption(Option<_T>* option_) {
00217                 option = option_;
00218         }
00219         virtual ~ROSOption() {
00220 
00221         }
00222 
00223         virtual void optionDidChange(const Option<_T>* option_) {
00224                 
00225                 if(option_->getValue() != valueOnRos) {
00226                         setToParameterServer();
00227                 }
00228         }
00229         virtual void optionShouldDelete(const Option<_T>* option_) {
00230                 
00231                 
00232         }
00233 
00234 
00235 
00236         virtual std::string getName() const {
00237                 return option->getName();
00238         }
00239         virtual std::string getDescription() const {
00240                 return option->getDescription();
00241         }
00242         virtual std::string getNamespace() const {
00243                 return option->getNamespace();
00244         }
00245         virtual std::string getNSName() const {
00246                 return option->getNSName();
00247         }
00248 
00249 
00250 
00251 
00252 
00253 };
00254 
00255 } 
00256 
00257 #endif