31 #include <dynamic_reconfigure/server.h>
33 #include "std_msgs/String.h"
35 #include <ubiquity_motor/PIDConfig.h>
39 #include <boost/thread.hpp>
44 static const double BILLION = 1000000000.0;
51 #define WHEEL_SLIP_THRESHOLD (0.08) // Rotation below which we null excess wheel torque in 4wd drive_type
61 if (level == 0xFFFFFFFF) {
67 }
else if (level == 2) {
69 }
else if (level == 4) {
71 }
else if (level == 8) {
73 }
else if (level == 16) {
75 }
else if (level == 32) {
77 }
else if (level == 64) {
80 ROS_ERROR(
"Unsupported dynamic_reconfigure level %u", level);
88 ROS_DEBUG(
"System control msg with content: '%s']",
msg->data.c_str());
95 ROS_INFO(
"Received System control msg to ENABLE control of the MCB");
100 ROS_INFO(
"Received System control msg to DISABLE control of the MCB");
110 ROS_INFO(
"Received System control msg to ENABLE control of motor speed");
115 ROS_INFO(
"Received System control msg to DISABLE control of motor speed");
133 robot->forcePidParamUpdates();
139 ROS_INFO(
"Default wheel_type of 'standard' will be used.");
145 ROS_INFO(
"Host is specifying wheel_type of '%s'",
"standard");
148 ROS_INFO(
"Host is specifying wheel_type of '%s'",
"thin");
152 ROS_INFO(
"Default to drive_type of 4wd when THIN wheels unless option drive_type is set");
156 ROS_WARN(
"Invalid wheel_type of '%s' specified! Using wheel type of standard",
163 robot->setWheelType(wheel_type);
164 robot->wheel_type = wheel_type;
177 ROS_INFO(
"Default drive_type of 'standard' will be used.");
183 ROS_INFO(
"Host is specifying drive_type of '%s'",
"standard");
186 ROS_INFO(
"Host is specifying drive_type of '%s'",
"4wd");
188 ROS_WARN(
"Invalid drive_type of '%s' specified! Using drive type of standard",
195 robot->setDriveType(drive_type);
196 robot->drive_type = drive_type;
199 int32_t wheel_direction = 0;
202 ROS_INFO(
"Firmware default wheel_direction will be used.");
207 ROS_INFO(
"Host is specifying wheel_direction of '%s'",
"standard");
210 ROS_INFO(
"Host is specifying wheel_direction of '%s'",
"reverse");
212 ROS_WARN(
"Invalid wheel_direction of '%s' specified! Using wheel direction of standard",
218 robot->setWheelDirection(wheel_direction);
225 ROS_INFO_ONCE(
"Firmware is version %d. Setting Controller board version to %d",
228 ROS_DEBUG(
"Controller board version has been set to %d",
235 ROS_ERROR_ONCE(
"Firmware is version V%d. We strongly recommend minimum firmware version of at least V%d",
239 ROS_INFO_ONCE(
"Firmware is version V%d. This meets the recommend minimum firmware versionof V%d",
251 ROS_INFO(
"Wheel slip nulling will be enabled for this 4wd system when velocity remains at zero.");
265 robot->setSystemEvents(0);
266 robot->system_events = 0;
288 int main(
int argc,
char* argv[]) {
298 int lastMcbEnabled = 1;
304 std::unique_ptr<MotorHardware> robot =
nullptr;
308 while (
ros::ok() && robot.get() ==
nullptr) {
316 ctrlLoopDelay.
sleep();
329 dynamic_reconfigure::Server<ubiquity_motor::PIDConfig> server;
330 dynamic_reconfigure::Server<ubiquity_motor::PIDConfig>::CallbackType
f;
333 server.setCallback(
f);
336 robot->requestFirmwareVersion();
343 robot->diag_updater.broadcast(0,
"Establishing communication with motors");
346 while (
ros::ok() && robot->firmware_version == 0) {
348 ROS_ERROR(
"The Firmware not reporting its version");
349 robot->requestFirmwareVersion();
350 robot->readInputs(0);
358 ROS_INFO(
"Requesting Firmware daycode ");
359 robot->requestFirmwareDate();
365 ROS_INFO(
"Initialization of MCB completed.");
369 robot->setSystemEvents(0);
370 robot->system_events = 0;
376 for (
int i = 0; i < robot->num_fw_params; i++) {
386 robot->clearCommands();
388 double leftLastWheelPos = 0.0;
389 double rightLastWheelPos = 0.0;
390 double leftWheelPos = 0.0;
391 double rightWheelPos = 0.0;
392 robot-> getWheelJointPositions(leftLastWheelPos, rightWheelPos);
397 int wheelSlipEvents = 0;
399 ROS_INFO(
"Starting motor control node now");
402 double estopReleaseDeadtime = 0.8;
403 double estopReleaseDelay = 0.0;
412 ros::Time last_sys_maint_time = last_loop_time;
413 ros::Time last_joint_time = last_loop_time;
414 ctrlLoopDelay.
sleep();
415 uint32_t loopIdx = 0;
419 elapsed_loop_time = current_time - last_loop_time;
420 last_loop_time = current_time;
426 if (lastMcbEnabled == 1) {
427 ROS_WARN(
"Motor controller going offline and closing MCB serial port");
431 ctrlLoopDelay.
sleep();
435 if (lastMcbEnabled == 0) {
438 ROS_WARN(
"Motor controller went from offline to online!");
439 portOpenStatus = robot->openPort();
440 if (portOpenStatus ==
true) {
441 robot->setSystemEvents(0);
442 robot->system_events = 0;
447 ROS_WARN(
"Motor controller has been re-initialized as we go back online");
450 ROS_ERROR(
"ERROR in re-opening of the Motor controller!");
456 if (elapsed_time > jointUpdatePeriod) {
458 double leftWheelVel = 0.0;
459 double rightWheelVel = 0.0;
460 robot-> getWheelJointPositions(leftWheelPos, rightWheelPos);
461 leftWheelVel = (leftWheelPos - leftLastWheelPos) / elapsed_time.
toSec();
462 rightWheelVel = (rightWheelPos - rightLastWheelPos) / elapsed_time.
toSec();
463 robot->setWheelJointVelocities(leftWheelVel, rightWheelVel);
464 leftLastWheelPos = leftWheelPos;
465 rightLastWheelPos = rightWheelPos;
468 robot->publishMotorState();
476 zeroVelocityTime += jointUpdatePeriod;
477 if (zeroVelocityTime > wheelSlipNullingPeriod) {
480 ROS_DEBUG(
"Applying wheel slip relief now with slip period of %4.1f sec ",
481 wheelSlipNullingPeriod.
toSec());
482 wheelSlipEvents += 1;
483 robot->nullWheelErrors();
494 robot->readInputs(loopIdx);
509 if ((minCycleTime < elapsed_loop_time) && (elapsed_loop_time < maxCycleTime)) {
510 cm.
update(current_time, elapsed_loop_time);
513 ROS_WARN(
"Resetting controller due to time jump %f seconds",
514 elapsed_loop_time.
toSec());
516 robot->clearCommands();
523 elapsed_time = current_time - last_sys_maint_time;
525 robot->requestSystemEvents();
530 std::string batStatus =
"OK";
536 ROS_INFO(
"Battery = %5.2f volts [%s], MCB system events 0x%x, PidCtrl 0x%x, WheelType '%s' DriveType '%s' GearRatio %6.3f",
537 robot->getBatteryVoltage(), batStatus.c_str(), robot->system_events, robot->getPidControlWord(),
543 ROS_WARN(
"Detected Motor controller PowerOn event!");
544 robot->setSystemEvents(0);
545 robot->system_events = 0;
550 ROS_WARN(
"Motor controller has been re-initialized");
557 robot->setWheelType(robot->wheel_type);
563 robot->setDriveType(robot->drive_type);
569 if (robot->getEstopState()) {
570 robot->writeSpeedsInRadians(0.0, 0.0);
571 estopReleaseDelay = estopReleaseDeadtime;
573 if (estopReleaseDelay > 0.0) {
576 robot->writeSpeedsInRadians(0.0, 0.0);
579 robot->writeSpeeds();
581 robot->writeSpeedsInRadians(0.0, 0.0);
586 robot->diag_updater.update();
587 ctrlLoopDelay.
sleep();