command_to_pwm_2_dir_pin.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 
00025 #include "sr_ronex_transmissions/mapping/general_io/command_to_pwm_2_dir_pin.hpp"
00026 #include <ros_ethercat_model/robot_state.hpp>
00027 #include <boost/lexical_cast.hpp>
00028 #include <math.h>
00029 
00030 namespace ronex
00031 {
00032 namespace mapping
00033 {
00034 namespace general_io
00035 {
00036 CommandToPWM2PinDir::CommandToPWM2PinDir(TiXmlElement* mapping_el, ros_ethercat_model::RobotState* robot)
00037   : CommandToPWM(mapping_el, robot)
00038 {
00039   // Stop the timer created by the parent class constructor. It would call the wrong try_init_cb_ (wouldn't it?)
00040   init_timer_.stop();
00041 
00042   const char *ronex_name = mapping_el ? mapping_el->Attribute("ronex") : NULL;
00043   if (!ronex_name)
00044   {
00045     ROS_ERROR("RonexTransmission transmission did not specify the ronex name");
00046     return;
00047   }
00048 
00049   init_timer_ = nh_.createTimer(ros::Duration(0.01),
00050                                 boost::bind(&CommandToPWM2PinDir::try_init_cb_, this, _1, mapping_el,
00051                                             robot, ronex_name));
00052 }
00053 
00054 bool CommandToPWM2PinDir::try_init_cb_(const ros::TimerEvent&, TiXmlElement* mapping_el,
00055                                        ros_ethercat_model::RobotState* robot, const char* ronex_name)
00056 {
00057   if ( !init_(mapping_el, robot, ronex_name) )
00058   {
00059     return false;
00060   }
00061 
00062   ROS_DEBUG_STREAM("RoNeX" << ronex_name << " is initialised now.");
00063   // stopping timer
00064   init_timer_.stop();
00065 
00066   is_initialized_ = true;
00067   return true;
00068 }
00069 
00070 bool CommandToPWM2PinDir::init_(TiXmlElement* mapping_el, ros_ethercat_model::RobotState* robot, const char* ronex_name)
00071 {
00072   if ( !CommandToPWM::init_(mapping_el, robot, ronex_name))
00073   {
00074     return false;
00075   }
00076 
00077   // read motor direction pin 2 index from urdf
00078   const char *d_pin = mapping_el ? mapping_el->Attribute("direction_pin_2") : NULL;
00079   if (!d_pin)
00080   {
00081     ROS_ERROR("RonexTransmission transmission did not specify the direction pin 2.");
00082     return false;
00083   }
00084   // convert to size_t
00085   try
00086   {
00087     digital_pin_index_2_ = boost::lexical_cast<size_t>(d_pin);
00088   }
00089   catch( boost::bad_lexical_cast const& )
00090   {
00091     ROS_ERROR("RonexTransmission: Couldn't parse direction_pin_2 to a size_t.");
00092     return false;
00093   }
00094 
00095   return true;
00096 }
00097 
00098 bool CommandToPWM2PinDir::check_pins_in_bound_()
00099 {
00100   // we ignore the first iteration as the array is not yet initialised.
00101   if ( first_iteration_ )
00102   {
00103     pin_out_of_bound_ = true;
00104     first_iteration_ = false;
00105     return false;
00106   }
00107 
00108   pin_out_of_bound_ = !CommandToPWM::check_pins_in_bound_();
00109 
00110   if ( !pin_out_of_bound_ )
00111   {
00112     if ( digital_pin_index_2_ > general_io_->command_.digital_.size() )
00113     {
00114       // size_t is always >= 0 so no need to check lower bound
00115       ROS_ERROR_STREAM("Specified direction pin 2 is out of bound: " << digital_pin_index_2_ << " / max = " <<
00116                                general_io_->command_.digital_.size() << " , not propagating the command to the RoNeX.");
00117       pin_out_of_bound_ = true;
00118       return false;
00119     }
00120   }
00121 
00122   pin_out_of_bound_ = false;
00123   return true;
00124 }
00125 
00126 void CommandToPWM2PinDir::propagateToRonex(ros_ethercat_model::JointState *js)
00127 {
00128   if ( !is_initialized_ )
00129     return;
00130 
00131   if ( check_pins_in_bound_() )
00132   {
00133     if ( pwm_pin_index_ == 0 )
00134       general_io_->command_.pwm_[pwm_module_].on_time_0 =
00135               static_cast<uint16_t>((static_cast<double>(general_io_->command_.pwm_[pwm_module_].period) *
00136                       abs(js->commanded_effort_) ) / 100);
00137     else
00138       general_io_->command_.pwm_[pwm_module_].on_time_1 =
00139               static_cast<uint16_t>((static_cast<double>(general_io_->command_.pwm_[pwm_module_].period) *
00140                       abs(js->commanded_effort_) ) / 100);
00141 
00142     // This is assigned by convention: negative effort sets the direction pin to 1.
00143     general_io_->command_.digital_[digital_pin_index_] = (js->commanded_effort_ < 0.0);
00144     // The 2nd direction pin is the opposite of the first one
00145     general_io_->command_.digital_[digital_pin_index_2_] = !general_io_->command_.digital_[digital_pin_index_];
00146   }
00147 }
00148 }  // namespace general_io
00149 }  // namespace mapping
00150 }  // namespace ronex
00151 /* For the emacs weenies in the crowd.
00152 Local Variables:
00153 c-basic-offset: 2
00154 End:
00155 */


sr_ronex_transmissions
Author(s): Ugo Cupcic, Toni Oliver, Mark Pitchless
autogenerated on Thu Jun 6 2019 21:21:55