IOTBot.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include "IOTBot.h"
3 
4 using namespace std;
5 
6 namespace iotbot
7 {
8 
9 IOTBot::IOTBot(ChassisParams &chassisParams, MotorParams &motorParams)
10 {
11  _motorParams = new MotorParams(motorParams);
12  _chassisParams = chassisParams;
13  // ensure that the direction parameter is set properly (either 1 or -1)
14  if(_chassisParams.direction>0) _chassisParams.direction = 1;
15  else _chassisParams.direction = -1;
16 
17  _shield = new IOTShield();
18  _shield->setGearRatio(_motorParams->gearRatio);
19  _shield->setTicksPerRev(_motorParams->encoderRatio);
20  _shield->setKp(_motorParams->kp);
21  _shield->setKi(_motorParams->ki);
22  _shield->setKd(_motorParams->kd);
23  _shield->setControlFrequency(_motorParams->controlFrequency);
24  _shield->setLowPassSetPoint(_motorParams->lowPassInputFilter);
25  _shield->setLowPassEncoder(_motorParams->lowPassEncoderTicks);
26  _shield->setLighting(iotbot::dimLight, _rgb);
27  _shield->setIMURawFormat(false);
28  _shield->setDriftWeight(0.02f);
29  _shield->calibrateIMU();
30 
31  _rad2rpm = (chassisParams.wheelBase+chassisParams.track)/chassisParams.wheelDiameter; // (lx+ly)/2 * 1/r
32  _rpm2rad = 1.0 / _rad2rpm;
33  _ms2rpm = 60.0/(chassisParams.wheelDiameter*M_PI);
34  _rpm2ms = 1.0 / _ms2rpm;
35  _vMax = motorParams.rpmMax * _rpm2ms;
36  _omegaMax = motorParams.rpmMax * _rpm2rad;
37 
38  _subJoy = _nh.subscribe<sensor_msgs::Joy>("joy", 1, &IOTBot::joyCallback, this);
39  _subVel = _nh.subscribe<geometry_msgs::Twist>("vel/teleop", 1, &IOTBot::velocityCallback, this);
40  _srvEnable = _nh.advertiseService("enable", &IOTBot::enableCallback, this);
41  _srvCali = _nh.advertiseService("calibrate", &IOTBot::calibrateCallback, this);
42  _srvFix = _nh.advertiseService("fix_imu_z_axis", &IOTBot::fixIMUZAxisCallback, this);
43  _pubToF = _nh.advertise<std_msgs::Float32MultiArray>("tof", 1);
44  _pubRPM = _nh.advertise<std_msgs::Float32MultiArray>("rpm", 1);
45  _pubVoltage = _nh.advertise<std_msgs::Float32>("voltage", 1);
46  _pubCurrent = _nh.advertise<std_msgs::Float32>("current", 1);
47  _pubTemp = _nh.advertise<std_msgs::Float32>("temperature", 1);
48  _pubIMU = _nh.advertise<sensor_msgs::Imu>("imu", 1);
49  _pubPose = _nh.advertise<geometry_msgs::PoseStamped>("pose", 1);
50 
51  _rpm[0] = 0.0;
52  _rpm[1] = 0.0;
53  _rpm[2] = 0.0;
54  _rpm[3] = 0.0;
55 
56  _rgb[0] = 0;
57  _rgb[1] = 0;
58  _rgb[2] = 0;
59 
60  ROS_INFO_STREAM("Initialized IOTBot with vMax: " << _vMax << " m/s");
61 }
62 
63 IOTBot::~IOTBot()
64 {
65  _shield->setLighting(iotbot::pulsation, _rgb);
66  delete _shield;
67  delete _motorParams;
68 }
69 
70 void IOTBot::run()
71 {
72  ros::Rate rate(100);
73  _lastCmd = ros::Time::now();
74 
75  bool run = true;
76 
77  float r[4];
78  float voltage;
79  int state = 0;
80  unsigned int cnt = 0;
81  std_msgs::Float32MultiArray msgToF;
82  std_msgs::Float32MultiArray msgRPM;
83  std_msgs::Float32 msgVoltage;
84  std_msgs::Float32 msgCurrent;
85  std_msgs::Float32 msgTemp;
86  sensor_msgs::Imu msgIMU;
87  bool lagPrev = false;
88  while(run)
89  {
90  ros::spinOnce();
91 
92  ros::Time tNow = ros::Time::now();
93  ros::Duration dt = tNow - _lastCmd;
94  bool lag = (dt.toSec()>0.5);
95  if(lag)
96  {
97  if(!lagPrev)
98  ROS_WARN_STREAM("Lag detected ... deactivate motor control");
99  _rpm[0] = 0.0;
100  _rpm[1] = 0.0;
101  _rpm[2] = 0.0;
102  _rpm[3] = 0.0;
103  _shield->setRPM(_rpm);
104  _shield->disable();
105  }
106  else
107  {
108  if(lagPrev)
109  ROS_WARN_STREAM("Connection stabilized ... motor control unlocked");
110  _shield->setRPM(_rpm);
111  }
112  lagPrev = lag;
113 
114  const std::vector<float> vToF = _shield->getRangeMeasurements();
115  msgToF.data = vToF;
116  _pubToF.publish(msgToF);
117 
118  const std::vector<float> vRPM = _shield->getRPM();
119  msgRPM.data = vRPM;
120  _pubRPM.publish(msgRPM);
121 
122  float voltage = _shield->getSystemVoltage();
123  msgVoltage.data = voltage;
124  _pubVoltage.publish(msgVoltage);
125 
126  float current = _shield->getLoadCurrent();
127  msgCurrent.data = current;
128  _pubCurrent.publish(msgCurrent);
129 
130  float temperature = _shield->getTemperature();
131  msgTemp.data = temperature;
132  _pubTemp.publish(msgTemp);
133 
134  const std::vector<float> vAcceleration = _shield->getAcceleration();
135  const std::vector<float> vAngularRate = _shield->getAngularRate();
136  msgIMU.header.frame_id = "odom";
137  msgIMU.header.stamp = tNow;
138  msgIMU.orientation_covariance = { 0, 0, 0, 0, 0, 0, 0, 0, 0};
139  msgIMU.linear_acceleration.x = vAcceleration[0];
140  msgIMU.linear_acceleration.y = vAcceleration[1];
141  msgIMU.linear_acceleration.z = vAcceleration[2];
142  msgIMU.angular_velocity.x = vAngularRate[0];
143  msgIMU.angular_velocity.y = vAngularRate[1];
144  msgIMU.angular_velocity.z = vAngularRate[2];
145  msgIMU.angular_velocity_covariance = { 0, 0, 0, 0, 0, 0, 0, 0, 0};
146  _pubIMU.publish(msgIMU);
147 
148  const std::vector<float> vQ = _shield->getOrientation();
149  geometry_msgs::PoseStamped msgPose;
150  msgPose.header.frame_id = "map";
151  msgPose.header.stamp = tNow;
152  msgPose.pose.position.x = 0;
153  msgPose.pose.position.y = 0;
154  msgPose.pose.position.z = 0;
155  msgPose.pose.orientation.x = vQ[1];
156  msgPose.pose.orientation.y = vQ[2];
157  msgPose.pose.orientation.z = vQ[3];
158  msgPose.pose.orientation.w = vQ[0];
159  _pubPose.publish(msgPose);
160 
161  rate.sleep();
162 
163  run = ros::ok();
164  }
165 }
166 
167 bool IOTBot::enableCallback(std_srvs::SetBool::Request& request, std_srvs::SetBool::Response& response)
168 {
169  if(request.data==true)
170  {
171  ROS_INFO("Enabling robot");
172  _shield->enable();
173  }
174  else
175  {
176  ROS_INFO("Disabling robot");
177  _shield->disable();
178  }
179  response.success = true;
180  return true;
181 }
182 
183 bool IOTBot::calibrateCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response)
184 {
185  ROS_INFO("Calibrating IMU");
186  _shield->calibrateIMU();
187  return true;
188 }
189 
190 bool IOTBot::fixIMUZAxisCallback(std_srvs::SetBool::Request& request, std_srvs::SetBool::Response& response)
191 {
192  ROS_INFO("Fixing Z-Axis: %d", request.data);
193  _shield->fixIMUZAxis(request.data);
194  response.success = true;
195  return true;
196 }
197 
198 void IOTBot::joyCallback(const sensor_msgs::Joy::ConstPtr& joy)
199 {
200  // Assignment of joystick axes to motor commands
201  float fwd = joy->axes[1]; // Range of values [-1:1]
202  float left = joy->axes[0]; // Range of values [-1:1]
203  float turn = joy->axes[2]; // Range of values [-1:1]
204  float throttle = (joy->axes[3]+1.0)/2.0; // Range of values [0:1]
205 
206  // Enable movement in the direction of the y-axis only when the button 12 is pressed
207  if(!joy->buttons[11])
208  left = 0;
209 
210  static int32_t btn0Prev = joy->buttons[0];
211  static int32_t btn1Prev = joy->buttons[1];
212  static int32_t btn2Prev = joy->buttons[2];
213  static int32_t btn3Prev = joy->buttons[3];
214  static int32_t btn4Prev = joy->buttons[4];
215  static int32_t btn5Prev = joy->buttons[5];
216  static int32_t btn9Prev = joy->buttons[9];
217  static int32_t btn10Prev = joy->buttons[10];
218 
219  if(joy->buttons[9] && !btn9Prev)
220  {
221  ROS_INFO("Disabling robot");
222  _shield->disable();
223  }
224  else if(joy->buttons[10] && !btn10Prev)
225  {
226  ROS_INFO("Enabling robot");
227  _shield->enable();
228  }
229 
230  if(joy->buttons[0] && !btn0Prev)
231  {
232  ROS_INFO("Setting beam light");
233  _shield->setLighting(iotbot::beamLight, _rgb);
234  }
235  if(joy->buttons[1] && !btn1Prev)
236  {
237  ROS_INFO("Setting warning light");
238  _rgb[0] = 0xFF;
239  _rgb[1] = 0x88;
240  _rgb[2] = 0x00;
241  _shield->setLighting(iotbot::warningLight, _rgb);
242  }
243  if(joy->buttons[2] && !btn2Prev)
244  {
245  ROS_INFO("Setting flash light on left side");
246  _rgb[0] = 0xFF;
247  _rgb[1] = 0x88;
248  _rgb[2] = 0x00;
249  _shield->setLighting(iotbot::flashLeft, _rgb);
250  }
251  if(joy->buttons[3] && !btn3Prev)
252  {
253  ROS_INFO("Setting flash light on right side");
254  _rgb[0] = 0xFF;
255  _rgb[1] = 0x88;
256  _rgb[2] = 0x00;
257  _shield->setLighting(iotbot::flashRight, _rgb);
258  }
259  if(joy->buttons[4] && !btn4Prev)
260  {
261  ROS_INFO("Setting rotational light");
262  _rgb[0] = 0x00;
263  _rgb[1] = 0x00;
264  _rgb[2] = 0xFF;
265  _shield->setLighting(iotbot::rotation, _rgb);
266  }
267  if(joy->buttons[5] && !btn5Prev)
268  {
269  ROS_INFO("Setting running light");
270  _rgb[0] = 0xFF;
271  _rgb[1] = 0x00;
272  _rgb[2] = 0x00;
273  _shield->setLighting(iotbot::running, _rgb);
274  }
275  btn0Prev = joy->buttons[0];
276  btn1Prev = joy->buttons[1];
277  btn2Prev = joy->buttons[2];
278  btn3Prev = joy->buttons[3];
279  btn4Prev = joy->buttons[4];
280  btn5Prev = joy->buttons[5];
281  btn9Prev = joy->buttons[9];
282  btn10Prev = joy->buttons[10];
283 
284  if(!btn0Prev && !btn1Prev && !btn2Prev && !btn3Prev && !btn4Prev && !btn5Prev)
285  _shield->setLighting(iotbot::dimLight, _rgb);
286 
287  float vFwd = throttle * fwd * _vMax;
288  float vLeft = throttle * left * _vMax;
289  float omega = throttle * turn * _omegaMax;
290 
291  controlMotors(vFwd, vLeft, omega);
292 }
293 
294 void IOTBot::velocityCallback(const geometry_msgs::Twist::ConstPtr& cmd)
295 {
296  controlMotors(cmd->linear.x, cmd->linear.y, cmd->angular.z);
297 }
298 
299 void IOTBot::controlMotors(float vFwd, float vLeft, float omega)
300 {
301  float rpmFwd = vFwd * _ms2rpm;
302  float rpmLeft = vLeft * _ms2rpm;
303  float rpmOmega = omega * _rad2rpm;
304 
305  // deactivated movement in y-direction for certain kinematic concepts, e.g., skid steering.
306  if(!_chassisParams.enableYMotion)
307  rpmLeft = 0;
308 
309  // leading signs -> see derivation: Stefan May, Skriptum Mobile Robotik
310  _rpm[_chassisParams.chFrontLeft] = rpmFwd - rpmLeft - rpmOmega;
311  _rpm[_chassisParams.chFrontRight] = -rpmFwd - rpmLeft - rpmOmega;
312  _rpm[_chassisParams.chRearLeft] = rpmFwd + rpmLeft - rpmOmega;
313  _rpm[_chassisParams.chRearRight] = -rpmFwd + rpmLeft - rpmOmega;
314 
315  // possibility to flip directions
316  _rpm[0] *= _chassisParams.direction;
317  _rpm[1] *= _chassisParams.direction;
318  _rpm[2] *= _chassisParams.direction;
319  _rpm[3] *= _chassisParams.direction;
320 
321  // Normalize values, if any value exceeds the maximum
322  float rpmMax = std::abs(_rpm[0]);
323  for(int i=1; i<4; i++)
324  {
325  if(std::abs(_rpm[i]) > _motorParams->rpmMax)
326  rpmMax = std::abs(_rpm[i]);
327  }
328 
329  if(rpmMax > _motorParams->rpmMax)
330  {
331  float factor = _motorParams->rpmMax / rpmMax;
332  for(int i=0; i<4; i++)
333  _rpm[i] *= factor;
334  }
335 
336  _lastCmd = ros::Time::now();
337 }
338 
339 } // end namespace
response
const std::string response
iotbot::MotorParams::rpmMax
float rpmMax
Definition: IOTBot.h:30
iotbot::flashRight
@ flashRight
Definition: IOTShield.h:67
iotbot::ChassisParams
Definition: IOTBot.h:77
iotbot::warningLight
@ warningLight
Definition: IOTShield.h:65
IOTBot.h
iotbot::flashLeft
@ flashLeft
Definition: IOTShield.h:66
ros::spinOnce
ROSCPP_DECL void spinOnce()
ros::ok
ROSCPP_DECL bool ok()
f
f
iotbot::IOTShield
Interface class to IOTShield via UART.
Definition: IOTShield.h:78
iotbot::ChassisParams::wheelDiameter
float wheelDiameter
Definition: IOTBot.h:81
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
iotbot::beamLight
@ beamLight
Definition: IOTShield.h:64
iotbot
Definition: IOTBot.cpp:6
iotbot::ChassisParams::wheelBase
float wheelBase
Definition: IOTBot.h:80
iotbot::MotorParams
Definition: IOTBot.h:26
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
iotbot::ChassisParams::direction
int direction
Definition: IOTBot.h:86
ros::Rate::sleep
bool sleep()
ros::Time
std
iotbot::pulsation
@ pulsation
Definition: IOTShield.h:68
iotbot::rotation
@ rotation
Definition: IOTShield.h:69
ros::Rate
DurationBase< Duration >::toSec
double toSec() const
iotbot::dimLight
@ dimLight
Definition: IOTShield.h:63
ROS_INFO
#define ROS_INFO(...)
ros::Duration
iotbot::ChassisParams::track
float track
Definition: IOTBot.h:79
ros::Time::now
static Time now()
iotbot::running
@ running
Definition: IOTShield.h:70


iotbot
Author(s): Stefan May (EduArt Robotik)
autogenerated on Wed May 24 2023 02:13:39