12   _chassisParams = chassisParams;
 
   14   if(_chassisParams.direction>0) _chassisParams.
direction = 1;
 
   15   else _chassisParams.direction = -1;
 
   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);
 
   27   _shield->setIMURawFormat(
false);
 
   28   _shield->setDriftWeight(0.02
f);
 
   29   _shield->calibrateIMU();
 
   32   _rpm2rad    = 1.0 / _rad2rpm;
 
   34   _rpm2ms     = 1.0 / _ms2rpm;
 
   35   _vMax       = motorParams.
rpmMax * _rpm2ms;
 
   36   _omegaMax   = motorParams.
rpmMax * _rpm2rad;
 
   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);
 
   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;
 
   94     bool lag = (dt.
toSec()>0.5);
 
  103       _shield->setRPM(_rpm);
 
  110       _shield->setRPM(_rpm);
 
  114     const std::vector<float> vToF = _shield->getRangeMeasurements();
 
  116     _pubToF.publish(msgToF);
 
  118     const std::vector<float> vRPM = _shield->getRPM();
 
  120     _pubRPM.publish(msgRPM);
 
  122     float voltage = _shield->getSystemVoltage();
 
  123     msgVoltage.data = voltage;
 
  124     _pubVoltage.publish(msgVoltage);
 
  126     float current = _shield->getLoadCurrent();
 
  127     msgCurrent.data = current;
 
  128     _pubCurrent.publish(msgCurrent);
 
  130     float temperature = _shield->getTemperature();
 
  131     msgTemp.data = temperature;
 
  132     _pubTemp.publish(msgTemp);
 
  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);
 
  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);
 
  167 bool IOTBot::enableCallback(std_srvs::SetBool::Request& request, std_srvs::SetBool::Response& response)
 
  169    if(request.data==
true)
 
  183 bool IOTBot::calibrateCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response)
 
  186    _shield->calibrateIMU();
 
  190 bool IOTBot::fixIMUZAxisCallback(std_srvs::SetBool::Request& request, std_srvs::SetBool::Response& response)
 
  192    ROS_INFO(
"Fixing Z-Axis: %d", request.data);
 
  193    _shield->fixIMUZAxis(request.data);
 
  198 void IOTBot::joyCallback(
const sensor_msgs::Joy::ConstPtr& joy)
 
  201   float fwd      = joy->axes[1];            
 
  202   float left     = joy->axes[0];            
 
  203   float turn     = joy->axes[2];            
 
  204   float throttle = (joy->axes[3]+1.0)/2.0;  
 
  207   if(!joy->buttons[11])
 
  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];
 
  219   if(joy->buttons[9] && !btn9Prev)
 
  224   else if(joy->buttons[10] && !btn10Prev)
 
  230   if(joy->buttons[0] && !btn0Prev)
 
  235   if(joy->buttons[1] && !btn1Prev)
 
  243   if(joy->buttons[2] && !btn2Prev)
 
  245      ROS_INFO(
"Setting flash light on left side");
 
  251   if(joy->buttons[3] && !btn3Prev)
 
  253      ROS_INFO(
"Setting flash light on right side");
 
  259   if(joy->buttons[4] && !btn4Prev)
 
  261      ROS_INFO(
"Setting rotational light");
 
  267   if(joy->buttons[5] && !btn5Prev)
 
  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];
 
  284   if(!btn0Prev && !btn1Prev && !btn2Prev && !btn3Prev && !btn4Prev && !btn5Prev)
 
  287   float vFwd  = throttle * fwd  * _vMax;
 
  288   float vLeft = throttle * left * _vMax;
 
  289   float omega = throttle * turn * _omegaMax;
 
  291   controlMotors(vFwd, vLeft, omega);
 
  294 void IOTBot::velocityCallback(
const geometry_msgs::Twist::ConstPtr& cmd)
 
  296   controlMotors(cmd->linear.x, cmd->linear.y, cmd->angular.z);
 
  299 void IOTBot::controlMotors(
float vFwd, 
float vLeft, 
float omega)
 
  301   float rpmFwd   = vFwd  * _ms2rpm;
 
  302   float rpmLeft  = vLeft * _ms2rpm;
 
  303   float rpmOmega = omega * _rad2rpm;
 
  306   if(!_chassisParams.enableYMotion)
 
  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;
 
  316   _rpm[0] *= _chassisParams.direction;
 
  317   _rpm[1] *= _chassisParams.direction;
 
  318   _rpm[2] *= _chassisParams.direction;
 
  319   _rpm[3] *= _chassisParams.direction;
 
  322   float rpmMax = std::abs(_rpm[0]);
 
  323   for(
int i=1; i<4; i++)
 
  325     if(std::abs(_rpm[i]) > _motorParams->rpmMax)
 
  326       rpmMax = std::abs(_rpm[i]);
 
  329   if(rpmMax > _motorParams->rpmMax)
 
  331     float factor = _motorParams->rpmMax / rpmMax;
 
  332     for(
int i=0; i<4; i++)