BaseController.cpp
Go to the documentation of this file.
00001 
00020 #include <stdlib.h>
00021 #include <sys/socket.h>
00022 #include <linux/sockios.h>
00023 #include <linux/can.h>
00024 #include <linux/if.h>
00025 #include "BaseController.h"
00026 #include "geometry_msgs/Twist.h"
00027 #include "UseAX10420.h"
00028 #include "AX10420_types.h"
00029 #include <algorithm>
00030 
00031 /* AX10420 foo */
00032 // Out Bits
00033 #define MOTOR_ENABLE_BIT 2
00034 #define EMERGENCY_STOP_BIT 1
00035 #define INDICATOR_BIT 0x80
00036 // In Bits
00037 #define EMERGENCY_STOP_SCANNER_BIT 1
00038 #define KEY_SWITCH_STATUS_BIT 2
00039 #define EMERGENCY_STOP_BUTTON_BIT 4
00040 #define SCANNER_WEAK_BIT 8
00041 #define EXTRA_BUTTON_BIT 32
00042 #define SCANNER_OSSD2_BIT 0x10
00043 
00044 
00045 int BaseController::initAX10420()
00046 {
00047     //We use only one cart (nr.0) and use only the first group (eG1).
00048     //Port A is set to Out (0).
00049     //Port B is set to In (1).
00050     //Port C upper and lower is set to In (1).
00051     int ax10420 = AX10420_OpenDevice("/dev/ax104200");
00052     int ret = AX10420_Init(ax10420, eG1, 0, 1, 1, 1);
00053     if (ret!=0)
00054     {
00055         ROS_ERROR("BaseController: AX10420_Init() failed, error code %d", ret);
00056     }
00057     return ax10420;
00058 }
00059 
00060 void BaseController::writeDataToCan(float vleft, float vright,  float max_speed)
00061 {
00062     unsigned short outputleft;
00063     unsigned short outputright;
00064     struct can_frame frame;
00065     frame.can_id = 0xb;
00066     frame.can_dlc = 8;
00067     //Left.
00068     outputleft=(unsigned short)(vleft/max_speed*0x7f+0x7f);
00069     ROS_DEBUG("BaseController: outputleft = %i", outputleft);
00070 
00071     //Right.
00072     outputright=(unsigned short)(vright/max_speed*0x7f+0x7f);
00073     ROS_DEBUG("BaseController: outputright = %i", outputright);
00074 
00075     //********************************************************************************//
00076     //Writing the Velocities in the CAN-Frame
00077     //********************************************************************************//
00078     frame.data[0] = outputright & 0xff;
00079     frame.data[1] = outputright >> 8;
00080     frame.data[2] = outputleft & 0xff;
00081     frame.data[3] = outputleft >> 8;
00082 
00083     //Writing on the CAN-Bus.
00084     write(state->getSocket(), &frame, sizeof(struct can_frame));
00085 }
00086 
00087 bool BaseController::enableMotor(int ax10420)
00088 {
00089     unsigned char outbyte = 0;
00090     //Enable motor.
00091     outbyte |= MOTOR_ENABLE_BIT;
00092     ROS_DEBUG("BaseController: Motor enable.");
00093     //Disable emergency stop.
00094     outbyte |= EMERGENCY_STOP_BIT;
00095     outbyte |= INDICATOR_BIT;
00096     ROS_DEBUG("BaseController: Disable emergency stop.");
00097 
00098     //Now put value to port A of Group 1.
00099     int ret = AX10420_SetOutput(ax10420, eG1, ePA, outbyte);
00100     if (ret!=0)
00101     {
00102         ROS_ERROR("BaseController: AX10420_SetOutput() failed, error code %d", ret);
00103     }
00104     return true;
00105 }
00106 
00107 float BaseController::calculateVelocity(bool left, float speed, float velocity_old)
00108 {
00109     float next = 0;
00110     // 0.3315 = wheel_distance/2, in meter, multiply with speedfaktor.
00111     {
00112         boost::mutex::scoped_lock scoped_lock(mutex);
00113         if(left)
00114         {
00115             next =  100 * ( cmd.linear.x - (cmd.angular.z*0.3315))*speed;
00116         }
00117         else
00118         {
00119             next =  100 * ( cmd.linear.x + (cmd.angular.z*0.3315))*speed;
00120         }
00121     }
00122 
00123     //Smoothing the moves. With weighting 4/6.
00124     return velocity_old * 0.40 + next * 0.60;
00125 }
00126 //This function handles all the mild_base_driving bus/motor/relais board related stuff.
00127 //The AX10420 is the controller for the relais board.
00128 void BaseController::run()
00129 {
00130     //subscribing to the velocity commands
00131     ros::Subscriber sub = state->n->subscribe("cmd_vel", 1,
00132                           &BaseController::setTargetVelocity,
00133                           this);
00134 
00135     int ax10420 = initAX10420();
00136     float speed;
00137     state->n->param("velocity", speed, 1.0f);
00138 
00139     //********************************************************************************//
00140     // Initialisation
00141     //********************************************************************************//
00142     float vleft2 = 0;
00143     float vright2 = 0;
00144     float max_speed = 612;
00145     bool motorEnabled = false;
00146 
00147     ros::Rate rate(50);
00148 
00149     bool first = true;
00150 
00151     //Adaptiation for right/left velocity.
00152     double right_adapter = 0;
00153     double left_adapter = 0;
00154 
00155     //Driving loop until node is stopped. Processing velocity commands each time being passed.
00156     while ( ros::ok() )
00157     {
00158         float vleft = 0;
00159         float vright = 0;
00160 
00161         //********************************************************************************//
00162         //Transforming the velovity commands into differential drive velocities
00163         //********************************************************************************//
00164 
00165         vleft = calculateVelocity(true, speed, vleft2);
00166         vright = calculateVelocity(false, speed, vright2);
00167 
00168         ROS_DEBUG("BaseController: 1. vleft: %f, vright: %f", vleft, vright);
00169 
00170         vleft2 = vleft;
00171         vright2 = vright;
00172 
00173         if(vright == 0)
00174         {
00175             right_adapter = 0;
00176         }
00177         if(vleft == 0)
00178         {
00179             left_adapter = 0;
00180         }
00181 
00182         //We got an effective driving command.
00183         if ((vleft != 0) || (vright != 0))
00184         {
00185             //Adapt the velocity linear to the required velocity, if the real velocity is different to the required.
00186             right_adapter = calculateAdapter(vright, canListener->get_velocity_right(), right_adapter);
00187             vright += right_adapter;
00188 
00189             left_adapter = calculateAdapter(vleft, canListener->get_velocity_left(), left_adapter);
00190             vleft += left_adapter;
00191 
00192             ROS_DEBUG("BaseController: 2. vleft: %f, vright: %f", vleft, vright);
00193 
00194             motorEnabled = enableMotor(ax10420);
00195 
00196             vleft = std::min(vleft, max_speed);
00197             vleft = std::max(vleft, -max_speed);
00198             vright = std::min(vright, max_speed);
00199             vright = std::max(vright, -max_speed);
00200 
00201             //We need inverse speeds because of the iaim wiring.
00202             vleft = -vleft;
00203 
00204             writeDataToCan(vleft, vright, max_speed);
00205         }
00206         else if (motorEnabled)
00207         {
00208             ROS_DEBUG("BaseController: Motor disabled");
00209             //Disable motor.
00210             motorEnabled = false;
00211             AX10420_SetOutput(ax10420, eG1, ePA, 0);
00212         }
00213         if(first)
00214         {
00215             ROS_INFO("BaseController: Started successfully. With speedup x%f\n", speed);
00216             first = false;
00217         }
00218 
00219         rate.sleep();
00220     }
00221 
00222     //Disable motor and close breaks, because when platform stands with zero velocity commands and open breaks, platform may drift either real or just concerning its sensors values.
00223     AX10420_SetOutput(ax10420, eG1, ePA, 0);
00224 }
00225 
00226 double BaseController::calculateAdapter(double required_velocity, double real_velocity, double adapter)
00227 {
00228     double adapter_value = 0;
00229     double difference = std::abs(std::abs(required_velocity) - std::abs(real_velocity*100.f));
00230     if(required_velocity > 0)
00231     {
00232         adapter_value = difference/10.f;
00233     }
00234     else
00235     {
00236         adapter_value = -difference/10.f;
00237     }
00238     ROS_DEBUG("BaseController: difference %f, adapter %f", difference, adapter);
00239 
00240     if(std::abs(required_velocity) > std::abs(real_velocity*100.f))
00241     {
00242         adapter += adapter_value;
00243     }
00244     else
00245     {
00246         adapter -= adapter_value;
00247     }
00248     if(std::abs(adapter) > std::abs(required_velocity/2))
00249     {
00250         adapter = required_velocity/2;
00251     }
00252     return adapter;
00253 }
00254 
00255 //This function is triggered when a Twist message is received.
00256 void BaseController::setTargetVelocity(const geometry_msgs::Twist &twist)
00257 {
00258     boost::mutex::scoped_lock scoped_lock(mutex);
00259     cmd = twist;
00260 }


asr_mild_base_driving
Author(s): Aumann Florian, Borella Jocelyn, Dehmani Souheil, Marek Felix, Meißner Pascal, Reckling Reno
autogenerated on Thu Jun 6 2019 22:02:58