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
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 ¤t_state);
00207 virtual void handleWrite(canopen::LayerStatus &status, const LayerState ¤t_state);
00208 virtual void handleInit(canopen::LayerStatus &status);
00209 virtual void handleDiag(canopen::LayerReport &report) { }
00210 virtual void handleShutdown(canopen::LayerStatus &status) { }
00211 virtual void handleHalt(canopen::LayerStatus &status) { }
00212 virtual void handleRecover(canopen::LayerStatus &status) { }
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 ¤t_state);
00275 virtual void handleWrite(canopen::LayerStatus &status, const LayerState ¤t_state); virtual void handleDiag(canopen::LayerReport &report) { }
00276 virtual void handleHalt(canopen::LayerStatus &status) { }
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