ROSOption.hpp
Go to the documentation of this file.
00001 /*
00002  * ROSOption.hpp
00003  *
00004  *  Created on: Oct 17, 2011
00005  *      Author: mriedel
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 // For Parsing YAML.
00016 #include <telekyb_base/Tools/YamlHelper.hpp>
00017 
00018 // For missing comparision
00019 #include <telekyb_base/Tools/OperatorOverload.hpp>
00020 
00021 // For Setting Options via YAML.
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         //Reference to acutal Option
00033         Option<_T>* option;
00034         _T valueOnRos;
00035 
00036         // -------------- SERVICES ------------- //
00037         // Service Offered to change Option
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                 //ROS_INFO_STREAM("SYNC: Option " << option->getNSName() << " Callback with String: " << request.input);
00053 
00054                 //_T value;
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 //              if (value == option->getValue()) {
00064 //                      // value unchanged
00065 //                      ROS_INFO_STREAM("SYNC: Option " << option->getNSName() << " is already at the defined value!" );
00066 //                      return true;
00067 //              }
00068                 // value changed
00069 
00070 //              if (option->isReadOnly()) {
00071 //                      // readOnly! valid on Ros differs, but should NOT. Revert.
00072 //                      ROS_WARN_STREAM("SYNC: Read-only Option " << option->getNSName() << " cannot be set!");
00073 //                      return false;
00074 //              }
00075 //              // option writeable
00076 //
00077 //              // bounds
00078 //              if (option->hasBounds() && !option->isWithinBounds(value)) {
00079 //                      ROS_WARN_STREAM("SYNC: Cannot set Option " << option->getNSName() << ". Value out-of-bounds !");
00080 //                      return false;
00081 //              }
00082 
00083                 // set
00084 //              ROS_INFO_STREAM("SYNC: Updating Option " << option->getNSName() << " to " << YamlHelper::parseValueToString(value));
00085 //              option->setValue(value);
00086 //              return true;
00087         }
00088 
00089         // Creates the ROS Service to Get the Parameter with YAML Syntax.
00090         virtual void createGetService() {
00091                 // This should never happen.
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         // Creates the ROS Service to Set the Parameter with YAML Syntax.
00101         virtual void createSetService() {
00102                 // This should never happen.
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         // -------------- SERVICES ------------- //
00120 
00121         // Parameter Server Interaction
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                 // convert
00129                 //ToXmlRpcConversion<_T> converter;
00130                 //converter(option->getValue(), value);
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                 // convert
00153                 //FromXmlRpcConversion<_T> converter;
00154 
00155 
00156                 //ROS_DEBUG_STREAM("updateFromParameterServer on Option " << getName() << " currentValue: " << option->getValue() << " valueOnRos: " << valueOnRos);
00157 
00158                 // Conversion
00159                 try {
00160                         value >> valueOnRos;
00161                 } catch (XmlRpc::XmlRpcException &e) {
00162                         // value On Ros is invalid! Revert to Optionvalue.
00163                         ROS_ERROR_STREAM("Could not convert Option " << option->getNSName() << " FROM XmlRpcValue! " << e.getMessage() << " Reverting..");
00164                         setToParameterServer();
00165                         return false;
00166                 }
00167                 // conversion ok.
00168 
00169                 if (valueOnRos == option->getValue()) {
00170                         // value unchanged
00171                         return true;
00172                 }
00173                 // value changed
00174 
00175                 if (option->isReadOnly()) {
00176                         // readOnly! valid on Ros differs, but should NOT. Revert.
00177                         ROS_WARN_STREAM("ASYNC: Read-only Option " << option->getNSName() << " was changed on ROS Parameter server. Reverting...");
00178                         setToParameterServer();
00179                         return false;
00180                 }
00181                 // option writeable
00182 
00183                 // bounds
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                 // either no bounds or within bounds
00190 
00191                 // finally! let's update the option
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 //                      std::cout << "deleteFromParameterServer() called on ROSOption " << option->getNSName() <<
00202 //                                      ", ROSOptionController is not initialized yet." << std::endl;
00203                         return false;
00204                 }
00205 
00206                 //std::cout << "Delete Called on " << option->getNSName() << std::endl;
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                 //Set if Value is differnt
00225                 if(option_->getValue() != valueOnRos) {
00226                         setToParameterServer();
00227                 }
00228         }
00229         virtual void optionShouldDelete(const Option<_T>* option_) {
00230                 // Option is never deleted by this notification, but explicitly via the OptionController in the Option<T> Dest.
00231                 //deleteFromParameterServer();
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 //      void spinOnce() {
00250 //              std::cout << "Option: " << option->getName() << " Value: " << option->getValue() << std::endl;
00251 //      }
00252 
00253 };
00254 
00255 } // namespace
00256 
00257 #endif /* ROSOPTION_HPP_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Defines


telekyb_base
Author(s): Dr. Antonio Franchi and Martin Riedel
autogenerated on Mon Nov 11 2013 11:12:34