command_to_pwm.cpp
Go to the documentation of this file.
00001 /*
00002 * Copyright (c) 2013, Shadow Robot Company, All rights reserved.
00003 *
00004 * This library is free software; you can redistribute it and/or
00005 * modify it under the terms of the GNU Lesser General Public
00006 * License as published by the Free Software Foundation; either
00007 * version 3.0 of the License, or (at your option) any later version.
00008 *
00009 * This library is distributed in the hope that it will be useful,
00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00012 * Lesser General Public License for more details.
00013 *
00014 * You should have received a copy of the GNU Lesser General Public
00015 * License along with this library.
00016 */
00017 
00024 #include "sr_ronex_transmissions/mapping/general_io/command_to_pwm.hpp"
00025 #include <ros_ethercat_model/robot_state.hpp>
00026 #include <boost/lexical_cast.hpp>
00027 #include <math.h>
00028 
00029 namespace ronex
00030 {
00031   namespace mapping
00032   {
00033     namespace general_io
00034     {
00035       CommandToPWM::CommandToPWM(TiXmlElement* mapping_el, ros_ethercat_model::RobotState* robot)
00036         : RonexMapping(), pin_out_of_bound_(true)
00037       {
00038         const char *ronex_name = mapping_el ? mapping_el->Attribute("ronex") : NULL;
00039         if (!ronex_name)
00040         {
00041           ROS_ERROR("RonexTransmission transmission did not specify the ronex name");
00042           return;
00043         }
00044 
00045         init_timer_ = nh_.createTimer(ros::Duration(0.01),
00046                                       boost::bind(&CommandToPWM::try_init_cb_, this, _1, mapping_el, robot, ronex_name));
00047       }
00048 
00049       bool CommandToPWM::try_init_cb_(const ros::TimerEvent&, TiXmlElement* mapping_el, ros_ethercat_model::RobotState* robot, const char* ronex_name)
00050       {
00051         //has the ronex been added by the driver?
00052         if( robot->getCustomHW(ronex_name) == NULL )
00053           return false;
00054 
00055         general_io_ = static_cast<ronex::GeneralIO*>( robot->getCustomHW(ronex_name) );
00056         if(!general_io_)
00057         {
00058           ROS_ERROR_STREAM("The RoNeX: " << ronex_name << " was not found on the system.");
00059           return false;
00060         }
00061 
00062         //read PWM module index from urdf
00063         const char *pwm_module = mapping_el ? mapping_el->Attribute("pwm_module") : NULL;
00064         if (!pwm_module)
00065         {
00066           ROS_ERROR("RonexTransmission transmission did not specify the pwm module.");
00067           return false;
00068         }
00069         //convert to size_t
00070         try
00071         {
00072           pwm_module_ = boost::lexical_cast<size_t>( pwm_module );
00073         }
00074         catch( boost::bad_lexical_cast const& )
00075         {
00076           ROS_ERROR("RonexTransmission: Couldn't parse pwm_module to a size_t.");
00077           return false;
00078         }
00079 
00080         //read PWM pin index from urdf
00081         const char *pin = mapping_el ? mapping_el->Attribute("pwm_pin") : NULL;
00082         if (!pin)
00083         {
00084           ROS_ERROR("RonexTransmission transmission did not specify the pwm pin.");
00085           return false;
00086         }
00087         //convert to size_t
00088         try
00089         {
00090           pwm_pin_index_ = boost::lexical_cast<size_t>( pin );
00091         }
00092         catch( boost::bad_lexical_cast const& )
00093         {
00094           ROS_ERROR("RonexTransmission: Couldn't parse pwm_pin to a size_t.");
00095           return false;
00096         }
00097 
00098         //read motor direction pin index from urdf
00099         const char *d_pin = mapping_el ? mapping_el->Attribute("direction_pin") : NULL;
00100         if (!d_pin)
00101         {
00102           ROS_ERROR("RonexTransmission transmission did not specify the direction pin.");
00103           return false;
00104         }
00105         //convert to size_t
00106         try
00107         {
00108           digital_pin_index_ = boost::lexical_cast<size_t>( d_pin );
00109         }
00110         catch( boost::bad_lexical_cast const& )
00111         {
00112           ROS_ERROR("RonexTransmission: Couldn't parse direction_pin to a size_t.");
00113           return false;
00114         }
00115 
00116         ROS_DEBUG_STREAM("RoNeX" << ronex_name << " is initialised now.");
00117         //stopping timer
00118         init_timer_.stop();
00119 
00120         is_initialized_ = true;
00121         return true;
00122       }
00123 
00124       bool CommandToPWM::check_pins_in_bound_()
00125       {
00126         //we ignore the first iteration as the array is not yet initialised.
00127         if( first_iteration_ )
00128         {
00129           pin_out_of_bound_ = true;
00130           first_iteration_ = false;
00131           return false;
00132         }
00133 
00134         //we have to check here for the size otherwise the general io hasn't been updated.
00135         if( pin_out_of_bound_ )
00136         {
00137           if( pwm_module_ >= general_io_->command_.pwm_.size() )
00138           {
00139             //size_t is always >= 0 so no need to check lower bound
00140             ROS_ERROR_STREAM("Specified PWM module index is out of bound: " << pwm_pin_index_ << " / max = " << general_io_->command_.pwm_.size() << ", not propagating the command to the RoNeX.");
00141             pin_out_of_bound_ = true;
00142             return false;
00143           }
00144           if( pwm_pin_index_ > 1 )
00145           {
00146             //size_t is always >= 0 so no need to check lower bound
00147             ROS_ERROR_STREAM("Specified PWM pin is out of bound: " << pwm_pin_index_ << " / max = 1, not propagating the command to the RoNeX.");
00148             pin_out_of_bound_ = true;
00149             return false;
00150           }
00151           if( digital_pin_index_ > general_io_->command_.digital_.size() )
00152           {
00153             //size_t is always >= 0 so no need to check lower bound
00154             ROS_ERROR_STREAM("Specified direction pin is out of bound: " << digital_pin_index_ << " / max = " << general_io_->command_.digital_.size() << " , not propagating the command to the RoNeX.");
00155             pin_out_of_bound_ = true;
00156             return false;
00157           }
00158         }
00159 
00160         pin_out_of_bound_ = false;
00161         return true;
00162       }
00163 
00164       void CommandToPWM::propagateToRonex(ros_ethercat_model::JointState *js)
00165       {
00166         if( !is_initialized_ )
00167           return;
00168 
00169         if( check_pins_in_bound_() )
00170         {
00171           if( pwm_pin_index_ == 0 )
00172             general_io_->command_.pwm_[pwm_module_].on_time_0 = static_cast<unsigned short int>((static_cast<double>(general_io_->command_.pwm_[pwm_module_].period) * js->commanded_effort_ ) / 100);
00173           else
00174             general_io_->command_.pwm_[pwm_module_].on_time_1 = static_cast<unsigned short int>((static_cast<double>(general_io_->command_.pwm_[pwm_module_].period) * js->commanded_effort_ ) / 100);
00175 
00176           // This is assigned by convention: negative effort sets the direction pin to 1.
00177           general_io_->command_.digital_[digital_pin_index_] = (js->commanded_effort_ < 0.0);
00178        }
00179       }
00180     }
00181   }
00182 }
00183 /* For the emacs weenies in the crowd.
00184 Local Variables:
00185 c-basic-offset: 2
00186 End:
00187 */


sr_ronex_transmissions
Author(s): Ugo Cupcic, Toni Oliver, Mark Pitchless
autogenerated on Fri Aug 28 2015 13:12:29