robot_layer.cpp
Go to the documentation of this file.
00001 
00002 
00003 #include <joint_limits_interface/joint_limits.h>
00004 #include <joint_limits_interface/joint_limits_urdf.h>
00005 #include <joint_limits_interface/joint_limits_rosparam.h>
00006 
00007 #include <controller_manager/controller_manager.h>
00008 #include <controller_manager_msgs/SwitchController.h>
00009 
00010 #include <canopen_motor_node/robot_layer.h>
00011 
00012 #include <boost/bimap.hpp>
00013 #include <boost/bimap/multiset_of.hpp>
00014 #include <boost/foreach.hpp>
00015 
00016 using namespace canopen;
00017 
00018 UnitConverter::UnitConverter(const std::string &expression, get_var_func_type var_func)
00019 : var_func_(var_func)
00020 {
00021     parser_.SetVarFactory(UnitConverter::createVariable, this);
00022 
00023     parser_.DefineConst("pi", M_PI);
00024     parser_.DefineConst("nan", std::numeric_limits<double>::quiet_NaN());
00025 
00026     parser_.DefineFun("rad2deg", UnitConverter::rad2deg);
00027     parser_.DefineFun("deg2rad", UnitConverter::deg2rad);
00028     parser_.DefineFun("norm", UnitConverter::norm);
00029     parser_.DefineFun("smooth", UnitConverter::smooth);
00030     parser_.DefineFun("avg", UnitConverter::avg);
00031 
00032     parser_.SetExpr(expression);
00033 }
00034 
00035 void UnitConverter::reset(){
00036     for(variable_ptr_list::iterator it = var_list_.begin(); it != var_list_.end(); ++it){
00037         **it = std::numeric_limits<double>::quiet_NaN();
00038     }
00039 }
00040 
00041 double* UnitConverter::createVariable(const char *name, void * userdata){
00042     UnitConverter * uc = static_cast<UnitConverter*>(userdata);
00043     double *p = uc->var_func_ ? uc->var_func_(name) : 0;
00044     if(!p){
00045         p = new double(std::numeric_limits<double>::quiet_NaN());
00046         uc->var_list_.push_back(variable_ptr(p));
00047     }
00048     return p;
00049 }
00050 
00051 
00052 template<typename T > class LimitsHandle {
00053     T limits_handle_;
00054 public:
00055     LimitsHandle(const T &handle) : limits_handle_(handle) {}
00056     virtual void enforce(const ros::Duration &period) { limits_handle_.enforceLimits(period); }
00057     virtual void reset() {}
00058 };
00059 
00060 template<> void LimitsHandle<joint_limits_interface::PositionJointSaturationHandle>::reset() { limits_handle_.reset(); }
00061 template<>void LimitsHandle<joint_limits_interface::PositionJointSoftLimitsHandle>::reset() { limits_handle_.reset(); }
00062 
00063 bool HandleLayer::select(const MotorBase::OperationMode &m){
00064     CommandMap::iterator it = commands_.find(m);
00065     if(it == commands_.end()) return false;
00066     jh_ = it->second;
00067     return true;
00068 }
00069 
00070 HandleLayer::HandleLayer(const std::string &name, const boost::shared_ptr<MotorBase> & motor, const boost::shared_ptr<ObjectStorage> storage,  XmlRpc::XmlRpcValue & options)
00071 : Layer(name + " Handle"), motor_(motor), variables_(storage), jsh_(name, &pos_, &vel_, &eff_), jph_(jsh_, &cmd_pos_), jvh_(jsh_, &cmd_vel_), jeh_(jsh_, &cmd_eff_), jh_(0), forward_command_(false),
00072   filter_pos_("double"), filter_vel_("double"), filter_eff_("double"), options_(options), enable_limits_(true)
00073 {
00074    commands_[MotorBase::No_Mode] = 0;
00075 
00076    std::string p2d("rint(rad2deg(pos)*1000)"), v2d("rint(rad2deg(vel)*1000)"), e2d("rint(eff)");
00077    std::string p2r("deg2rad(obj6064)/1000"), v2r("deg2rad(obj606C)/1000"), e2r("0");
00078 
00079    if(options.hasMember("pos_unit_factor") || options.hasMember("vel_unit_factor") || options.hasMember("eff_unit_factor")){
00080        const std::string reason("*_unit_factor parameters are not supported anymore, please migrate to conversion functions.");
00081        ROS_FATAL_STREAM(reason);
00082        throw std::invalid_argument(reason);
00083    }
00084 
00085    if(options.hasMember("pos_to_device")) p2d = (const std::string&) options["pos_to_device"];
00086    if(options.hasMember("pos_from_device")) p2r = (const std::string&) options["pos_from_device"];
00087 
00088    if(options.hasMember("vel_to_device")) v2d = (const std::string&) options["vel_to_device"];
00089    if(options.hasMember("vel_from_device")) v2r = (const std::string&) options["vel_from_device"];
00090 
00091    if(options.hasMember("eff_to_device")) e2d = (const std::string&) options["eff_to_device"];
00092    if(options.hasMember("eff_from_device")) e2r = (const std::string&) options["eff_from_device"];
00093 
00094    conv_target_pos_.reset(new UnitConverter(p2d, boost::bind(assignVariable, "pos", &cmd_pos_, _1)));
00095    conv_target_vel_.reset(new UnitConverter(v2d, boost::bind(assignVariable, "vel", &cmd_vel_, _1)));
00096    conv_target_eff_.reset(new UnitConverter(e2d, boost::bind(assignVariable, "eff", &cmd_eff_, _1)));
00097 
00098    conv_pos_.reset(new UnitConverter(p2r, boost::bind(&ObjectVariables::getVariable, &variables_, _1)));
00099    conv_vel_.reset(new UnitConverter(v2r, boost::bind(&ObjectVariables::getVariable, &variables_, _1)));
00100    conv_eff_.reset(new UnitConverter(e2r, boost::bind(&ObjectVariables::getVariable, &variables_, _1)));
00101 }
00102 
00103 HandleLayer::CanSwitchResult HandleLayer::canSwitch(const MotorBase::OperationMode &m){
00104     if(!motor_->isModeSupported(m) || commands_.find(m) == commands_.end()){
00105         return NotSupported;
00106     }else if(motor_->getMode() == m){
00107         return NoNeedToSwitch;
00108     }else if(motor_->getLayerState() == Ready){
00109         return ReadyToSwitch;
00110     }else{
00111         return NotReadyToSwitch;
00112     }
00113 }
00114 
00115 bool HandleLayer::switchMode(const MotorBase::OperationMode &m){
00116     if(motor_->getMode() != m){
00117         forward_command_ = false;
00118         jh_ = 0; // disconnect handle
00119         if(!motor_->enterModeAndWait(m)){
00120             ROS_ERROR_STREAM(jsh_.getName() << "could not enter mode " << (int)m);
00121             LayerStatus s;
00122             motor_->halt(s);
00123             return false;
00124         }
00125     }
00126     return select(m);
00127 }
00128 
00129 bool HandleLayer::forwardForMode(const MotorBase::OperationMode &m){
00130     if(motor_->getMode() == m){
00131         forward_command_ = true;
00132         return true;
00133     }
00134     return false;
00135 }
00136 
00137 class InterfaceMapping {
00138     typedef boost::bimap<boost::bimaps::multiset_of<std::string>, boost::bimaps::set_of<MotorBase::OperationMode>  > bimap_type;
00139     bimap_type mapping_;
00140 public:
00141     InterfaceMapping(){
00142         mapping_.insert(bimap_type::value_type("hardware_interface::PositionJointInterface" ,MotorBase::Profiled_Position));
00143         mapping_.insert(bimap_type::value_type("hardware_interface::PositionJointInterface" ,MotorBase::Interpolated_Position));
00144         mapping_.insert(bimap_type::value_type("hardware_interface::PositionJointInterface" ,MotorBase::Cyclic_Synchronous_Position));
00145 
00146         mapping_.insert(bimap_type::value_type("hardware_interface::VelocityJointInterface" ,MotorBase::Velocity));
00147         mapping_.insert(bimap_type::value_type("hardware_interface::VelocityJointInterface" ,MotorBase::Profiled_Velocity));
00148         mapping_.insert(bimap_type::value_type("hardware_interface::VelocityJointInterface" ,MotorBase::Cyclic_Synchronous_Velocity));
00149 
00150         mapping_.insert(bimap_type::value_type("hardware_interface::EffortJointInterface" ,MotorBase::Profiled_Torque));
00151         mapping_.insert(bimap_type::value_type("hardware_interface::EffortJointInterface" ,MotorBase::Cyclic_Synchronous_Torque));
00152     }
00153     std::vector<MotorBase::OperationMode> getInterfaceModes(const std::string &interface){
00154         std::vector<MotorBase::OperationMode> modes;
00155         BOOST_FOREACH(bimap_type::left_reference i, mapping_.left.equal_range(interface)){
00156             modes.push_back(i.second);
00157         }
00158         return modes;
00159     }
00160     bool hasConflict(const std::string &interface, MotorBase::OperationMode mode){
00161         bimap_type::right_const_iterator it;
00162         if((it = mapping_.right.find(mode)) != mapping_.right.end()){
00163             return it->second != interface;
00164         }
00165         return false;
00166     }
00167   
00168 } g_interface_mapping;
00169 
00170 
00171 template<typename T> void addLimitsHandle(std::vector<LimitsHandleBase::Ptr> &limits, const T &t) {
00172     limits.push_back(LimitsHandleBase::Ptr( (LimitsHandleBase *) new LimitsHandle<T> (t) ));
00173 }
00174 
00175 hardware_interface::JointHandle* HandleLayer::registerHandle(hardware_interface::PositionJointInterface &iface,
00176                                                              const joint_limits_interface::JointLimits &limits,
00177                                                              const joint_limits_interface::SoftJointLimits *soft_limits){
00178     hardware_interface::JointHandle* h = addHandle(iface, &jph_, g_interface_mapping.getInterfaceModes("hardware_interface::PositionJointInterface"));
00179     if(h &&  limits.has_position_limits){
00180         addLimitsHandle(limits_, joint_limits_interface::PositionJointSaturationHandle(*h, limits));
00181         if(soft_limits){
00182             addLimitsHandle(limits_, joint_limits_interface::PositionJointSoftLimitsHandle(*h, limits, *soft_limits));
00183         }
00184     }
00185     return h;
00186 }
00187 
00188 hardware_interface::JointHandle* HandleLayer::registerHandle(hardware_interface::VelocityJointInterface &iface,
00189                                                              const joint_limits_interface::JointLimits&limits,
00190                                                              const joint_limits_interface::SoftJointLimits *soft_limits){
00191     hardware_interface::JointHandle* h = addHandle(iface, &jvh_, g_interface_mapping.getInterfaceModes("hardware_interface::VelocityJointInterface"));
00192     if(h &&  limits.has_velocity_limits){
00193         addLimitsHandle(limits_, joint_limits_interface::VelocityJointSaturationHandle(*h, limits));
00194         if(soft_limits){
00195             addLimitsHandle(limits_, joint_limits_interface::VelocityJointSoftLimitsHandle(*h, limits, *soft_limits));
00196         }
00197     }
00198     return h;
00199 }
00200 
00201 hardware_interface::JointHandle* HandleLayer::registerHandle(hardware_interface::EffortJointInterface &iface,
00202                                                              const joint_limits_interface::JointLimits&limits,
00203                                                              const joint_limits_interface::SoftJointLimits *soft_limits){
00204     hardware_interface::JointHandle* h = addHandle(iface, &jeh_, g_interface_mapping.getInterfaceModes("hardware_interface::EffortJointInterface"));
00205     if(h &&  limits.has_effort_limits){
00206         addLimitsHandle(limits_, joint_limits_interface::EffortJointSaturationHandle(*h, limits));
00207         if(soft_limits){
00208             addLimitsHandle(limits_, joint_limits_interface::EffortJointSoftLimitsHandle(*h, limits, *soft_limits));
00209         }
00210     }
00211     return h;
00212 }
00213 
00214 void HandleLayer::handleRead(LayerStatus &status, const LayerState &current_state) {
00215     if(current_state > Shutdown){
00216         variables_.sync();
00217         filter_pos_.update(conv_pos_->evaluate(), pos_);
00218         filter_vel_.update(conv_vel_->evaluate(), vel_);
00219         filter_eff_.update(conv_eff_->evaluate(), eff_);
00220     }
00221 }
00222 void HandleLayer::handleWrite(LayerStatus &status, const LayerState &current_state) {
00223     if(current_state == Ready){
00224         hardware_interface::JointHandle* jh = 0;
00225         if(forward_command_) jh = jh_;
00226         
00227         if(jh == &jph_){
00228             motor_->setTarget(conv_target_pos_->evaluate());
00229             cmd_vel_ = vel_;
00230             cmd_eff_ = eff_;
00231         }else if(jh == &jvh_){
00232             motor_->setTarget(conv_target_vel_->evaluate());
00233             cmd_pos_ = pos_;
00234             cmd_eff_ = eff_;
00235         }else if(jh == &jeh_){
00236             motor_->setTarget(conv_target_eff_->evaluate());
00237             cmd_pos_ = pos_;
00238             cmd_vel_ = vel_;
00239         }else{
00240             cmd_pos_ = pos_;
00241             cmd_vel_ = vel_;
00242             cmd_eff_ = eff_;
00243             if(jh) status.warn("unsupported mode active");
00244         }
00245     }
00246 }
00247 
00248 bool prepareFilter(const std::string& joint_name, const std::string& filter_name,  filters::FilterChain<double> &filter, XmlRpc::XmlRpcValue & options, canopen::LayerStatus &status){
00249     filter.clear();
00250     if(options.hasMember(filter_name)){
00251         if(!filter.configure(options[filter_name],joint_name + "/" + filter_name)){
00252             status.error("could not configure " + filter_name+ " for " + joint_name);
00253             return false;
00254         }
00255     }
00256 
00257     return true;
00258 }
00259 
00260 bool HandleLayer::prepareFilters(canopen::LayerStatus &status){
00261     return prepareFilter(jsh_.getName(), "position_filters", filter_pos_, options_, status) &&
00262        prepareFilter(jsh_.getName(), "velocity_filters", filter_vel_, options_, status) &&
00263        prepareFilter(jsh_.getName(), "effort_filters", filter_eff_, options_, status);
00264 }
00265 
00266 void HandleLayer::handleInit(LayerStatus &status){
00267     // TODO: implement proper init
00268     conv_pos_->reset();
00269     conv_vel_->reset();
00270     conv_eff_->reset();
00271     conv_target_pos_->reset();
00272     conv_target_vel_->reset();
00273     conv_target_eff_->reset();
00274 
00275 
00276     if(prepareFilters(status))
00277     {
00278         handleRead(status, Layer::Ready);
00279     }
00280 }
00281 
00282 void HandleLayer::enforceLimits(const ros::Duration &period, bool reset){
00283     for(std::vector<LimitsHandleBase::Ptr>::iterator it = limits_.begin(); it != limits_.end(); ++it){
00284         if(reset) (*it)->reset();
00285         if(enable_limits_) (*it)->enforce(period);
00286     }
00287 }
00288 
00289 void HandleLayer::enableLimits(bool enable){
00290     enable_limits_ = enable;
00291 }
00292 
00293 
00294 void RobotLayer::stopControllers(const std::vector<std::string> controllers){
00295     controller_manager_msgs::SwitchController srv;
00296     srv.request.stop_controllers = controllers;
00297     srv.request.strictness = srv.request.BEST_EFFORT;
00298     boost::thread call(boost::bind(ros::service::call<controller_manager_msgs::SwitchController>, "controller_manager/switch_controller", srv));
00299     call.detach();
00300 }
00301 
00302 void RobotLayer::add(const std::string &name, boost::shared_ptr<HandleLayer> handle){
00303     LayerGroupNoDiag::add(handle);
00304     handles_.insert(std::make_pair(name, handle));
00305 }
00306 
00307 RobotLayer::RobotLayer(ros::NodeHandle nh) : LayerGroupNoDiag<HandleLayer>("RobotLayer"), nh_(nh), first_init_(true)
00308 {
00309     registerInterface(&state_interface_);
00310     registerInterface(&pos_interface_);
00311     registerInterface(&vel_interface_);
00312     registerInterface(&eff_interface_);
00313 
00314     urdf_.initParam("robot_description");
00315 }
00316 
00317 void RobotLayer::handleInit(LayerStatus &status){
00318     if(first_init_){
00319         for(HandleMap::iterator it = handles_.begin(); it != handles_.end(); ++it){
00320             joint_limits_interface::JointLimits limits;
00321             joint_limits_interface::SoftJointLimits soft_limits;
00322 
00323             boost::shared_ptr<const urdf::Joint> joint = getJoint(it->first);
00324 
00325             if(!joint){
00326                 status.error("joint " + it->first + " not found");
00327                 return;
00328             }
00329 
00330             bool has_joint_limits = joint_limits_interface::getJointLimits(joint, limits);
00331 
00332             has_joint_limits = joint_limits_interface::getJointLimits(it->first, nh_, limits) || has_joint_limits;
00333 
00334             bool has_soft_limits = has_joint_limits && joint_limits_interface::getSoftJointLimits(joint, soft_limits);
00335 
00336             if(!has_joint_limits){
00337                 ROS_WARN_STREAM("No limits found for " << it->first);
00338             }
00339 
00340             it->second->registerHandle(state_interface_);
00341 
00342             const hardware_interface::JointHandle *h  = 0;
00343 
00344             it->second->registerHandle(pos_interface_, limits, has_soft_limits ? &soft_limits : 0);
00345             it->second->registerHandle(vel_interface_, limits, has_soft_limits ? &soft_limits : 0);
00346             it->second->registerHandle(eff_interface_, limits, has_soft_limits ? &soft_limits : 0);
00347         }
00348         first_init_ = false;
00349     }
00350     LayerGroupNoDiag::handleInit(status);
00351 }
00352 
00353 void RobotLayer::enforce(const ros::Duration &period, bool reset){
00354     for(HandleMap::iterator it = handles_.begin(); it != handles_.end(); ++it){
00355         it->second->enforceLimits(period, reset);
00356     }
00357 }
00358 
00359 bool RobotLayer::prepareSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list) {
00360     // compile-time check for mode switching support in ros_control
00361     (void) &hardware_interface::RobotHW::prepareSwitch; // please upgrade to ros_control/contoller_manager 0.9.4 or newer
00362 
00363     // stop handles
00364     for (std::list<hardware_interface::ControllerInfo>::const_iterator controller_it = stop_list.begin(); controller_it != stop_list.end(); ++controller_it){
00365 
00366         if(switch_map_.find(controller_it->name) == switch_map_.end()){
00367             ROS_ERROR_STREAM(controller_it->name << " was not started before");
00368             return false;
00369         }
00370     }
00371 
00372     // start handles
00373     for (std::list<hardware_interface::ControllerInfo>::const_iterator controller_it = start_list.begin(); controller_it != start_list.end(); ++controller_it){
00374         SwitchContainer to_switch;
00375         ros::NodeHandle nh(nh_,controller_it->name);
00376         int mode;
00377         if(nh.getParam("required_drive_mode", mode)){
00378             if(g_interface_mapping.hasConflict(controller_it->hardware_interface,(MotorBase::OperationMode) mode)){
00379                 ROS_ERROR_STREAM(controller_it->hardware_interface << " cannot be provided in mode " << mode);
00380                 return false;
00381             }
00382             SwitchData sd;
00383             sd.enforce_limits = nh.param("enforce_limits", true);
00384             sd.mode = MotorBase::OperationMode(mode);
00385             for (std::set<std::string>::const_iterator res_it = controller_it->resources.begin(); res_it != controller_it->resources.end(); ++res_it){
00386                 boost::unordered_map< std::string, boost::shared_ptr<HandleLayer> >::const_iterator h_it = handles_.find(*res_it);
00387 
00388                 if(h_it == handles_.end()){
00389                     ROS_ERROR_STREAM(*res_it << " not found");
00390                     return false;
00391                 }
00392                 HandleLayer::CanSwitchResult res = h_it->second->canSwitch((MotorBase::OperationMode)mode);
00393 
00394                 switch(res){
00395                     case HandleLayer::NotSupported:
00396                         ROS_ERROR_STREAM("Mode " << mode << " is not available for " << *res_it);
00397                         return false;
00398                     case HandleLayer::NotReadyToSwitch:
00399                         ROS_ERROR_STREAM(*res_it << " is not ready to switch mode");
00400                         return false;
00401                     case HandleLayer::ReadyToSwitch:
00402                     case HandleLayer::NoNeedToSwitch:
00403                         sd.handle = h_it->second;
00404                         to_switch.push_back(sd);
00405                 }
00406             }
00407         }
00408         switch_map_.insert(std::make_pair(controller_it->name, to_switch));
00409     }
00410 
00411     // perform mode switches
00412     boost::unordered_set<boost::shared_ptr<HandleLayer> > to_stop;
00413     std::vector<std::string> failed_controllers;
00414     for (std::list<hardware_interface::ControllerInfo>::const_iterator controller_it = stop_list.begin(); controller_it != stop_list.end(); ++controller_it){
00415         SwitchContainer &to_switch = switch_map_.at(controller_it->name);
00416         for(RobotLayer::SwitchContainer::iterator it = to_switch.begin(); it != to_switch.end(); ++it){
00417             to_stop.insert(it->handle);
00418         }
00419     }
00420     for (std::list<hardware_interface::ControllerInfo>::const_iterator controller_it = start_list.begin(); controller_it != start_list.end(); ++controller_it){
00421         SwitchContainer &to_switch = switch_map_.at(controller_it->name);
00422         bool okay = true;
00423         for(RobotLayer::SwitchContainer::iterator it = to_switch.begin(); it != to_switch.end(); ++it){
00424             it->handle->switchMode(MotorBase::No_Mode); // stop all
00425         }
00426         for(RobotLayer::SwitchContainer::iterator it = to_switch.begin(); it != to_switch.end(); ++it){
00427             if(!it->handle->switchMode(it->mode)){
00428                 failed_controllers.push_back(controller_it->name);
00429                 ROS_ERROR_STREAM("Could not switch one joint for " << controller_it->name << ", will stop all related joints and the controller.");
00430                 for(RobotLayer::SwitchContainer::iterator stop_it = to_switch.begin(); stop_it != to_switch.end(); ++stop_it){
00431                     to_stop.insert(stop_it->handle);
00432                 }
00433                 okay = false;
00434                 break;
00435             }else{
00436                 it->handle->enableLimits(it->enforce_limits);
00437             }
00438             to_stop.erase(it->handle);
00439         }
00440     }
00441     for(boost::unordered_set<boost::shared_ptr<HandleLayer> >::iterator it = to_stop.begin(); it != to_stop.end(); ++it){
00442         (*it)->switchMode(MotorBase::No_Mode);
00443     }
00444     if(!failed_controllers.empty()){
00445         stopControllers(failed_controllers);
00446         // will not return false here since this would prevent other controllers to be started and therefore lead to an inconsistent state
00447     }
00448 
00449     return true;
00450 }
00451 
00452 void RobotLayer::doSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list) {
00453     std::vector<std::string> failed_controllers;
00454     for (std::list<hardware_interface::ControllerInfo>::const_iterator controller_it = start_list.begin(); controller_it != start_list.end(); ++controller_it){
00455         try{
00456             SwitchContainer &to_switch = switch_map_.at(controller_it->name);
00457             for(RobotLayer::SwitchContainer::iterator it = to_switch.begin(); it != to_switch.end(); ++it){
00458                 if(!it->handle->forwardForMode(it->mode)){
00459                     failed_controllers.push_back(controller_it->name);
00460                     ROS_ERROR_STREAM("Could not switch one joint for " << controller_it->name << ", will stop all related joints and the controller.");
00461                     for(RobotLayer::SwitchContainer::iterator stop_it = to_switch.begin(); stop_it != to_switch.end(); ++stop_it){
00462                         it->handle->switchMode(MotorBase::No_Mode);
00463                     }
00464                     break;
00465                 }
00466             }
00467 
00468         }catch(const std::out_of_range&){
00469             ROS_ERROR_STREAM("Conttroller " << controller_it->name << "not found, will stop it");
00470             failed_controllers.push_back(controller_it->name);
00471         }
00472     }
00473     if(!failed_controllers.empty()){
00474         stopControllers(failed_controllers);
00475     }
00476 }
00477 
00478 
00479 void ControllerManagerLayer::handleRead(canopen::LayerStatus &status, const LayerState &current_state) {
00480     if(current_state > Shutdown){
00481         if(!cm_) status.error("controller_manager is not intialized");
00482     }
00483 }
00484 
00485 void ControllerManagerLayer::handleWrite(canopen::LayerStatus &status, const LayerState &current_state) {
00486     if(current_state > Shutdown){
00487         if(!cm_){
00488             status.error("controller_manager is not intialized");
00489         }else{
00490             canopen::time_point abs_now = canopen::get_abs_time();
00491             ros::Time now = ros::Time::now();
00492 
00493             ros::Duration period = fixed_period_;
00494 
00495             if(period.isZero()) {
00496                 period.fromSec(boost::chrono::duration<double>(abs_now -last_time_).count());
00497             }
00498 
00499             last_time_ = abs_now;
00500 
00501             bool recover = recover_.exchange(false);
00502             cm_->update(now, period, recover);
00503             robot_->enforce(period, recover);
00504         }
00505     }
00506 }
00507 
00508 void ControllerManagerLayer::handleInit(canopen::LayerStatus &status) {
00509     if(cm_){
00510         status.warn("controller_manager is already intialized");
00511     }else{
00512         recover_ = true;
00513         last_time_ = canopen::get_abs_time();
00514         cm_.reset(new controller_manager::ControllerManager(robot_.get(), nh_));
00515     }
00516 }
00517 
00518 void ControllerManagerLayer::handleRecover(canopen::LayerStatus &status) {
00519     if(!cm_) status.error("controller_manager is not intialized");
00520     else recover_ = true;
00521 }
00522 
00523 void ControllerManagerLayer::handleShutdown(canopen::LayerStatus &status) {
00524     cm_.reset();
00525 }


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