robot_layer.h
Go to the documentation of this file.
00001 
00002 #ifndef CANOPEN_MOTOR_NODE_ROBOT_LAYER_H_
00003 #define CANOPEN_MOTOR_NODE_ROBOT_LAYER_H_
00004 
00005 #include <hardware_interface/joint_command_interface.h>
00006 #include <hardware_interface/joint_state_interface.h>
00007 #include <hardware_interface/robot_hw.h>
00008 #include <joint_limits_interface/joint_limits_interface.h>
00009 #include <urdf/model.h>
00010 #include <canopen_402/base.h>
00011 #include <filters/filter_chain.h>
00012 #include <boost/function.hpp>
00013 #include <boost/scoped_ptr.hpp>
00014 
00015 #include "muParser.h"
00016 
00017 // forward declarations
00018 namespace controller_manager {
00019     class ControllerManager;
00020 }
00021 
00022 class ObjectVariables {
00023     const boost::shared_ptr<canopen::ObjectStorage> storage_;
00024     struct Getter {
00025         boost::shared_ptr<double> val_ptr;
00026         boost::function<bool(double&)> func;
00027         bool operator ()() { return func(*val_ptr); }
00028         template<typename T> Getter(const canopen::ObjectStorage::Entry<T> &entry): func(boost::bind(&Getter::readObject<T>, entry, _1)), val_ptr(new double) { }
00029         template<typename T> static bool readObject(canopen::ObjectStorage::Entry<T> &entry, double &res){
00030             T val;
00031             if(!entry.get(val)) return false;
00032             res = val;
00033             return true;
00034         }
00035         operator double*() const { return val_ptr.get(); }
00036     };
00037     boost::unordered_map<canopen::ObjectDict::Key, Getter> getters_;
00038     boost::mutex mutex_;
00039 public:
00040     template<const uint16_t dt> static double* func(ObjectVariables &list, const canopen::ObjectDict::Key &key){
00041         typedef typename canopen::ObjectStorage::DataType<dt>::type type;
00042         return list.getters_.insert(std::make_pair(key, Getter(list.storage_->entry<type>(key)))).first->second;
00043     }
00044     ObjectVariables(const boost::shared_ptr<canopen::ObjectStorage> storage) : storage_(storage) {}
00045     bool sync(){
00046         boost::mutex::scoped_lock lock(mutex_);
00047         bool ok = true;
00048         for(boost::unordered_map<canopen::ObjectDict::Key, Getter>::iterator it = getters_.begin(); it != getters_.end(); ++it){
00049             ok = it->second() && ok;
00050         }
00051         return ok;
00052     }
00053     double * getVariable(const std::string &n) {
00054         boost::mutex::scoped_lock lock(mutex_);
00055         try{
00056             if(n.find("obj") == 0){
00057                 canopen::ObjectDict::Key key(n.substr(3));
00058                 boost::unordered_map<canopen::ObjectDict::Key, Getter>::const_iterator it = getters_.find(key);
00059                 if(it != getters_.end()) return it->second;
00060                 return canopen::branch_type<ObjectVariables, double * (ObjectVariables &list, const canopen::ObjectDict::Key &k)>(storage_->dict_->get(key)->data_type)(*this, key);
00061             }
00062         }
00063         catch( const std::exception &e){
00064             ROS_ERROR_STREAM("Could not find variable '" << n << "', reason: " << boost::diagnostic_information(e));
00065         }
00066         return 0;
00067     }
00068 };
00069 
00070 template<> inline double* ObjectVariables::func<canopen::ObjectDict::DEFTYPE_VISIBLE_STRING >(ObjectVariables &, const canopen::ObjectDict::Key &){ return 0; }
00071 template<> inline double* ObjectVariables::func<canopen::ObjectDict::DEFTYPE_OCTET_STRING >(ObjectVariables &, const canopen::ObjectDict::Key &){ return 0; }
00072 template<> inline double* ObjectVariables::func<canopen::ObjectDict::DEFTYPE_UNICODE_STRING >(ObjectVariables &, const canopen::ObjectDict::Key &){ return 0; }
00073 template<> inline double* ObjectVariables::func<canopen::ObjectDict::DEFTYPE_DOMAIN >(ObjectVariables &, const canopen::ObjectDict::Key &){ return 0; }
00074 
00075 class UnitConverter{
00076 public:
00077     typedef boost::function<double * (const std::string &) > get_var_func_type;
00078 
00079     UnitConverter(const std::string &expression, get_var_func_type var_func = get_var_func_type());
00080     void reset();
00081     double evaluate() { int num; return parser_.Eval(num)[0]; }
00082 private:
00083     typedef boost::shared_ptr<double> variable_ptr;
00084     typedef std::list<variable_ptr> variable_ptr_list;
00085 
00086     static double* createVariable(const char *name, void * userdata);
00087     variable_ptr_list var_list_;
00088     get_var_func_type var_func_;
00089 
00090     mu::Parser parser_;
00091 
00092     static double rad2deg(double r){
00093         return r*180.0/M_PI;
00094     }
00095     static double deg2rad(double d){
00096         return d*M_PI/180.0;
00097     }
00098     static double norm(double val, double min, double max){
00099         while(val >= max) val -= (max-min);
00100         while(val < min) val += (max-min);
00101         return val;
00102     }
00103     static double smooth(double val, double old_val, double alpha){
00104         if(isnan(val)) return 0;
00105         if(isnan(old_val)) return val;
00106         return alpha*val + (1.0-alpha)*old_val;
00107     }
00108     static double avg(const double *vals, int num)
00109     {
00110         double s = 0.0;
00111         int i=0;
00112         for (; i<num; ++i){
00113             const double &val = vals[i];
00114             if(isnan(val)) break;
00115             s += val;
00116         }
00117         return s / double(i+1);
00118     }
00119 };
00120 
00121 class LimitsHandleBase {
00122 public:
00123     virtual void enforce(const ros::Duration &period) = 0;
00124     virtual void reset() = 0;
00125     virtual ~LimitsHandleBase();
00126     typedef boost::shared_ptr<LimitsHandleBase> Ptr;
00127 };
00128 
00129 class HandleLayer: public canopen::Layer{
00130     boost::shared_ptr<canopen::MotorBase> motor_;
00131     double pos_, vel_, eff_;
00132 
00133     double cmd_pos_, cmd_vel_, cmd_eff_;
00134 
00135     ObjectVariables variables_;
00136     boost::scoped_ptr<UnitConverter>  conv_target_pos_, conv_target_vel_, conv_target_eff_;
00137     boost::scoped_ptr<UnitConverter>  conv_pos_, conv_vel_, conv_eff_;
00138 
00139     filters::FilterChain<double> filter_pos_, filter_vel_, filter_eff_;
00140     XmlRpc::XmlRpcValue options_;
00141 
00142     hardware_interface::JointStateHandle jsh_;
00143     hardware_interface::JointHandle jph_, jvh_, jeh_;
00144     boost::atomic<hardware_interface::JointHandle*> jh_;
00145     boost::atomic<bool> forward_command_;
00146 
00147     typedef boost::unordered_map< canopen::MotorBase::OperationMode,hardware_interface::JointHandle* > CommandMap;
00148     CommandMap commands_;
00149 
00150     template <typename T> hardware_interface::JointHandle* addHandle( T &iface, hardware_interface::JointHandle *jh,  const std::vector<canopen::MotorBase::OperationMode> & modes){
00151 
00152         bool supported = false;
00153         for(size_t i=0; i < modes.size(); ++i){
00154             if(motor_->isModeSupported(modes[i])){
00155                 supported = true;
00156                 break;
00157             }
00158         }
00159         if(!supported) return 0;
00160 
00161         iface.registerHandle(*jh);
00162 
00163         for(size_t i=0; i < modes.size(); ++i){
00164             commands_[modes[i]] = jh;
00165         }
00166         return jh;
00167     }
00168 
00169     bool select(const canopen::MotorBase::OperationMode &m);
00170     std::vector<LimitsHandleBase::Ptr> limits_;
00171     bool enable_limits_;
00172 public:
00173     HandleLayer(const std::string &name, const boost::shared_ptr<canopen::MotorBase> & motor, const boost::shared_ptr<canopen::ObjectStorage> storage,  XmlRpc::XmlRpcValue & options);
00174     static double * assignVariable(const std::string &name, double * ptr, const std::string &req) { return name == req ? ptr : 0; }
00175 
00176     enum CanSwitchResult{
00177         NotSupported,
00178         NotReadyToSwitch,
00179         ReadyToSwitch,
00180         NoNeedToSwitch
00181     };
00182 
00183     CanSwitchResult canSwitch(const canopen::MotorBase::OperationMode &m);
00184     bool switchMode(const canopen::MotorBase::OperationMode &m);
00185     bool forwardForMode(const canopen::MotorBase::OperationMode &m);
00186 
00187     void registerHandle(hardware_interface::JointStateInterface &iface){
00188         iface.registerHandle(jsh_);
00189     }
00190     hardware_interface::JointHandle* registerHandle(hardware_interface::PositionJointInterface &iface,
00191                                                     const joint_limits_interface::JointLimits &limits,
00192                                                     const joint_limits_interface::SoftJointLimits *soft_limits = 0);
00193     hardware_interface::JointHandle* registerHandle(hardware_interface::VelocityJointInterface &iface,
00194                                                     const joint_limits_interface::JointLimits &limits,
00195                                                     const joint_limits_interface::SoftJointLimits *soft_limits = 0);
00196     hardware_interface::JointHandle* registerHandle(hardware_interface::EffortJointInterface &iface,
00197                                                     const joint_limits_interface::JointLimits &limits,
00198                                                     const joint_limits_interface::SoftJointLimits *soft_limits = 0);
00199 
00200     void enforceLimits(const ros::Duration &period, bool reset);
00201     void enableLimits(bool enable);
00202 
00203     bool prepareFilters(canopen::LayerStatus &status);
00204 
00205 private:
00206     virtual void handleRead(canopen::LayerStatus &status, const LayerState &current_state);
00207     virtual void handleWrite(canopen::LayerStatus &status, const LayerState &current_state);
00208     virtual void handleInit(canopen::LayerStatus &status);
00209     virtual void handleDiag(canopen::LayerReport &report) { /* nothing to do */ }
00210     virtual void handleShutdown(canopen::LayerStatus &status) { /* nothing to do */ }
00211     virtual void handleHalt(canopen::LayerStatus &status) { /* TODO */ }
00212     virtual void handleRecover(canopen::LayerStatus &status) { /* nothing to do */ }
00213 
00214 };
00215 
00216 
00217 
00218 class RobotLayer : public canopen::LayerGroupNoDiag<HandleLayer>, public hardware_interface::RobotHW{
00219     hardware_interface::JointStateInterface state_interface_;
00220     hardware_interface::PositionJointInterface pos_interface_;
00221     hardware_interface::VelocityJointInterface vel_interface_;
00222     hardware_interface::EffortJointInterface eff_interface_;
00223 
00224     joint_limits_interface::PositionJointSoftLimitsInterface pos_soft_limits_interface_;
00225     joint_limits_interface::PositionJointSaturationInterface pos_saturation_interface_;
00226     joint_limits_interface::VelocityJointSoftLimitsInterface vel_soft_limits_interface_;
00227     joint_limits_interface::VelocityJointSaturationInterface vel_saturation_interface_;
00228     joint_limits_interface::EffortJointSoftLimitsInterface eff_soft_limits_interface_;
00229     joint_limits_interface::EffortJointSaturationInterface eff_saturation_interface_;
00230 
00231     ros::NodeHandle nh_;
00232     urdf::Model urdf_;
00233 
00234     typedef boost::unordered_map< std::string, boost::shared_ptr<HandleLayer> > HandleMap;
00235     HandleMap handles_;
00236     struct SwitchData {
00237         boost::shared_ptr<HandleLayer> handle;
00238         canopen::MotorBase::OperationMode mode;
00239         bool enforce_limits;
00240     };
00241     typedef std::vector<SwitchData>  SwitchContainer;
00242     typedef boost::unordered_map<std::string, SwitchContainer>  SwitchMap;
00243     SwitchMap switch_map_;
00244 
00245     boost::atomic<bool> first_init_;
00246 
00247     void stopControllers(const std::vector<std::string> controllers);
00248 public:
00249     void add(const std::string &name, boost::shared_ptr<HandleLayer> handle);
00250     RobotLayer(ros::NodeHandle nh);
00251     boost::shared_ptr<const urdf::Joint> getJoint(const std::string &n) const { return urdf_.getJoint(n); }
00252 
00253     virtual void handleInit(canopen::LayerStatus &status);
00254     void enforce(const ros::Duration &period, bool reset);
00255     virtual bool prepareSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list);
00256     virtual void doSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list);
00257 };
00258 
00259 
00260 class ControllerManagerLayer : public canopen::Layer {
00261     boost::shared_ptr<controller_manager::ControllerManager> cm_;
00262     boost::shared_ptr<RobotLayer> robot_;
00263     ros::NodeHandle nh_;
00264 
00265     canopen::time_point last_time_;
00266     boost::atomic<bool> recover_;
00267     const ros::Duration fixed_period_;
00268 
00269 public:
00270     ControllerManagerLayer(const boost::shared_ptr<RobotLayer> robot, const ros::NodeHandle &nh, const ros::Duration &fixed_period)
00271     :Layer("ControllerManager"), robot_(robot), nh_(nh), fixed_period_(fixed_period) {
00272     }
00273 
00274     virtual void handleRead(canopen::LayerStatus &status, const LayerState &current_state);
00275     virtual void handleWrite(canopen::LayerStatus &status, const LayerState &current_state);    virtual void handleDiag(canopen::LayerReport &report) { /* nothing to do */ }
00276     virtual void handleHalt(canopen::LayerStatus &status) { /* nothing to do (?) */ }
00277     virtual void handleInit(canopen::LayerStatus &status);
00278     virtual void handleRecover(canopen::LayerStatus &status);
00279     virtual void handleShutdown(canopen::LayerStatus &status);
00280 };
00281 
00282 #endif


canopen_motor_node
Author(s): Mathias Lüdtke
autogenerated on Thu Jun 6 2019 20:44:07