BaseController.cpp
Go to the documentation of this file.
1 
20 #include <stdlib.h>
21 #include <sys/socket.h>
22 #include <linux/sockios.h>
23 #include <linux/can.h>
24 #include <linux/if.h>
25 #include "BaseController.h"
26 #include "geometry_msgs/Twist.h"
27 #include "UseAX10420.h"
28 #include "AX10420_types.h"
29 #include <algorithm>
30 
31 /* AX10420 foo */
32 // Out Bits
33 #define MOTOR_ENABLE_BIT 2
34 #define EMERGENCY_STOP_BIT 1
35 #define INDICATOR_BIT 0x80
36 // In Bits
37 #define EMERGENCY_STOP_SCANNER_BIT 1
38 #define KEY_SWITCH_STATUS_BIT 2
39 #define EMERGENCY_STOP_BUTTON_BIT 4
40 #define SCANNER_WEAK_BIT 8
41 #define EXTRA_BUTTON_BIT 32
42 #define SCANNER_OSSD2_BIT 0x10
43 
44 
46 {
47  //We use only one cart (nr.0) and use only the first group (eG1).
48  //Port A is set to Out (0).
49  //Port B is set to In (1).
50  //Port C upper and lower is set to In (1).
51  int ax10420 = AX10420_OpenDevice("/dev/ax104200");
52  int ret = AX10420_Init(ax10420, eG1, 0, 1, 1, 1);
53  if (ret!=0)
54  {
55  ROS_ERROR("BaseController: AX10420_Init() failed, error code %d", ret);
56  }
57  return ax10420;
58 }
59 
60 void BaseController::writeDataToCan(float vleft, float vright, float max_speed)
61 {
62  unsigned short outputleft;
63  unsigned short outputright;
64  struct can_frame frame;
65  frame.can_id = 0xb;
66  frame.can_dlc = 8;
67  //Left.
68  outputleft=(unsigned short)(vleft/max_speed*0x7f+0x7f);
69  ROS_DEBUG("BaseController: outputleft = %i", outputleft);
70 
71  //Right.
72  outputright=(unsigned short)(vright/max_speed*0x7f+0x7f);
73  ROS_DEBUG("BaseController: outputright = %i", outputright);
74 
75  //********************************************************************************//
76  //Writing the Velocities in the CAN-Frame
77  //********************************************************************************//
78  frame.data[0] = outputright & 0xff;
79  frame.data[1] = outputright >> 8;
80  frame.data[2] = outputleft & 0xff;
81  frame.data[3] = outputleft >> 8;
82 
83  //Writing on the CAN-Bus.
84  write(state->getSocket(), &frame, sizeof(struct can_frame));
85 }
86 
87 bool BaseController::enableMotor(int ax10420)
88 {
89  unsigned char outbyte = 0;
90  //Enable motor.
91  outbyte |= MOTOR_ENABLE_BIT;
92  ROS_DEBUG("BaseController: Motor enable.");
93  //Disable emergency stop.
94  outbyte |= EMERGENCY_STOP_BIT;
95  outbyte |= INDICATOR_BIT;
96  ROS_DEBUG("BaseController: Disable emergency stop.");
97 
98  //Now put value to port A of Group 1.
99  int ret = AX10420_SetOutput(ax10420, eG1, ePA, outbyte);
100  if (ret!=0)
101  {
102  ROS_ERROR("BaseController: AX10420_SetOutput() failed, error code %d", ret);
103  }
104  return true;
105 }
106 
107 float BaseController::calculateVelocity(bool left, float speed, float velocity_old)
108 {
109  float next = 0;
110  // 0.3315 = wheel_distance/2, in meter, multiply with speedfaktor.
111  {
112  boost::mutex::scoped_lock scoped_lock(mutex);
113  if(left)
114  {
115  next = 100 * ( cmd.linear.x - (cmd.angular.z*0.3315))*speed;
116  }
117  else
118  {
119  next = 100 * ( cmd.linear.x + (cmd.angular.z*0.3315))*speed;
120  }
121  }
122 
123  //Smoothing the moves. With weighting 4/6.
124  return velocity_old * 0.40 + next * 0.60;
125 }
126 //This function handles all the mild_base_driving bus/motor/relais board related stuff.
127 //The AX10420 is the controller for the relais board.
129 {
130  //subscribing to the velocity commands
131  ros::Subscriber sub = state->n->subscribe("cmd_vel", 1,
133  this);
134 
135  int ax10420 = initAX10420();
136  float speed;
137  state->n->param("velocity", speed, 1.0f);
138 
139  //********************************************************************************//
140  // Initialisation
141  //********************************************************************************//
142  float vleft2 = 0;
143  float vright2 = 0;
144  float max_speed = 612;
145  bool motorEnabled = false;
146 
147  ros::Rate rate(50);
148 
149  bool first = true;
150 
151  //Adaptiation for right/left velocity.
152  double right_adapter = 0;
153  double left_adapter = 0;
154 
155  //Driving loop until node is stopped. Processing velocity commands each time being passed.
156  while ( ros::ok() )
157  {
158  float vleft = 0;
159  float vright = 0;
160 
161  //********************************************************************************//
162  //Transforming the velovity commands into differential drive velocities
163  //********************************************************************************//
164 
165  vleft = calculateVelocity(true, speed, vleft2);
166  vright = calculateVelocity(false, speed, vright2);
167 
168  ROS_DEBUG("BaseController: 1. vleft: %f, vright: %f", vleft, vright);
169 
170  vleft2 = vleft;
171  vright2 = vright;
172 
173  if(vright == 0)
174  {
175  right_adapter = 0;
176  }
177  if(vleft == 0)
178  {
179  left_adapter = 0;
180  }
181 
182  //We got an effective driving command.
183  if ((vleft != 0) || (vright != 0))
184  {
185  //Adapt the velocity linear to the required velocity, if the real velocity is different to the required.
186  right_adapter = calculateAdapter(vright, canListener->get_velocity_right(), right_adapter);
187  vright += right_adapter;
188 
189  left_adapter = calculateAdapter(vleft, canListener->get_velocity_left(), left_adapter);
190  vleft += left_adapter;
191 
192  ROS_DEBUG("BaseController: 2. vleft: %f, vright: %f", vleft, vright);
193 
194  motorEnabled = enableMotor(ax10420);
195 
196  vleft = std::min(vleft, max_speed);
197  vleft = std::max(vleft, -max_speed);
198  vright = std::min(vright, max_speed);
199  vright = std::max(vright, -max_speed);
200 
201  //We need inverse speeds because of the iaim wiring.
202  vleft = -vleft;
203 
204  writeDataToCan(vleft, vright, max_speed);
205  }
206  else if (motorEnabled)
207  {
208  ROS_DEBUG("BaseController: Motor disabled");
209  //Disable motor.
210  motorEnabled = false;
211  AX10420_SetOutput(ax10420, eG1, ePA, 0);
212  }
213  if(first)
214  {
215  ROS_INFO("BaseController: Started successfully. With speedup x%f\n", speed);
216  first = false;
217  }
218 
219  rate.sleep();
220  }
221 
222  //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.
223  AX10420_SetOutput(ax10420, eG1, ePA, 0);
224 }
225 
226 double BaseController::calculateAdapter(double required_velocity, double real_velocity, double adapter)
227 {
228  double adapter_value = 0;
229  double difference = std::abs(std::abs(required_velocity) - std::abs(real_velocity*100.f));
230  if(required_velocity > 0)
231  {
232  adapter_value = difference/10.f;
233  }
234  else
235  {
236  adapter_value = -difference/10.f;
237  }
238  ROS_DEBUG("BaseController: difference %f, adapter %f", difference, adapter);
239 
240  if(std::abs(required_velocity) > std::abs(real_velocity*100.f))
241  {
242  adapter += adapter_value;
243  }
244  else
245  {
246  adapter -= adapter_value;
247  }
248  if(std::abs(adapter) > std::abs(required_velocity/2))
249  {
250  adapter = required_velocity/2;
251  }
252  return adapter;
253 }
254 
255 //This function is triggered when a Twist message is received.
256 void BaseController::setTargetVelocity(const geometry_msgs::Twist &twist)
257 {
258  boost::mutex::scoped_lock scoped_lock(mutex);
259  cmd = twist;
260 }
int getSocket()
Definition: RobotState.h:109
int AX10420_OpenDevice(const char *device_name)
Definition: UseAX10420.h:36
f
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
int AX10420_Init(int fd, tAXGroup group, tAXIOConfigure port_a, tAXIOConfigure port_b, tAXIOConfigure port_c_upper, tAXIOConfigure port_c_lower)
Definition: UseAX10420.h:56
void writeDataToCan(float vleft, float vright, float max_speed)
boost::mutex mutex
float calculateVelocity(bool left, float speed, float velocity_old)
bool enableMotor(int ax10420)
double get_velocity_left()
double calculateAdapter(double required_velocity, double real_velocity, double adapter)
geometry_msgs::Twist cmd
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
int AX10420_SetOutput(int fd, tAXGroup group, tAXPort port, unsigned value)
Definition: UseAX10420.h:172
RobotState * state
ROSCPP_DECL bool ok()
CanListener * canListener
#define MOTOR_ENABLE_BIT
#define EMERGENCY_STOP_BIT
bool sleep()
void setTargetVelocity(const geometry_msgs::Twist &twist)
#define INDICATOR_BIT
ros::NodeHandle * n
Definition: RobotState.h:55
double get_velocity_right()
#define ROS_ERROR(...)
#define ROS_DEBUG(...)


asr_mild_base_driving
Author(s): Aumann Florian, Borella Jocelyn, Dehmani Souheil, Marek Felix, Meißner Pascal, Reckling Reno
autogenerated on Mon Jun 10 2019 12:43:40