husky_hardware.cpp
Go to the documentation of this file.
00001 
00032 #include "husky_base/husky_hardware.h"
00033 #include <boost/assign/list_of.hpp>
00034 
00035 namespace
00036 {
00037   const uint8_t LEFT = 0, RIGHT = 1;
00038 };
00039 
00040 namespace husky_base
00041 {
00042 
00046   HuskyHardware::HuskyHardware(ros::NodeHandle nh, ros::NodeHandle private_nh, double target_control_freq)
00047     :
00048     nh_(nh),
00049     private_nh_(private_nh),
00050     system_status_task_(husky_status_msg_),
00051     power_status_task_(husky_status_msg_),
00052     safety_status_task_(husky_status_msg_),
00053     software_status_task_(husky_status_msg_, target_control_freq)
00054   {
00055     private_nh_.param<double>("wheel_diameter", wheel_diameter_, 0.3302);
00056     private_nh_.param<double>("max_accel", max_accel_, 5.0);
00057     private_nh_.param<double>("max_speed", max_speed_, 1.0);
00058     private_nh_.param<double>("polling_timeout_", polling_timeout_, 10.0);
00059 
00060     std::string port;
00061     private_nh_.param<std::string>("port", port, "/dev/prolific");
00062 
00063     horizon_legacy::connect(port);
00064     horizon_legacy::configureLimits(max_speed_, max_accel_);
00065     resetTravelOffset();
00066     initializeDiagnostics();
00067     registerControlInterfaces();
00068   }
00069 
00073   void HuskyHardware::resetTravelOffset()
00074   {
00075     horizon_legacy::Channel<clearpath::DataEncoders>::Ptr enc = horizon_legacy::Channel<clearpath::DataEncoders>::requestData(
00076       polling_timeout_);
00077     if (enc)
00078     {
00079       for (int i = 0; i < 4; i++)
00080       {
00081         joints_[i].position_offset = linearToAngular(enc->getTravel(i % 2));
00082       }
00083     }
00084     else
00085     {
00086       ROS_ERROR("Could not get encoder data to calibrate travel offset");
00087     }
00088   }
00089 
00093   void HuskyHardware::initializeDiagnostics()
00094   {
00095     horizon_legacy::Channel<clearpath::DataPlatformInfo>::Ptr info =
00096       horizon_legacy::Channel<clearpath::DataPlatformInfo>::requestData(polling_timeout_);
00097     std::ostringstream hardware_id_stream;
00098     hardware_id_stream << "Husky " << info->getModel() << "-" << info->getSerial();
00099 
00100     diagnostic_updater_.setHardwareID(hardware_id_stream.str());
00101     diagnostic_updater_.add(system_status_task_);
00102     diagnostic_updater_.add(power_status_task_);
00103     diagnostic_updater_.add(safety_status_task_);
00104     diagnostic_updater_.add(software_status_task_);
00105     diagnostic_publisher_ = nh_.advertise<husky_msgs::HuskyStatus>("status", 10);
00106   }
00107 
00108 
00112   void HuskyHardware::registerControlInterfaces()
00113   {
00114     ros::V_string joint_names = boost::assign::list_of("front_left_wheel")
00115       ("front_right_wheel")("rear_left_wheel")("rear_right_wheel");
00116     for (unsigned int i = 0; i < joint_names.size(); i++)
00117     {
00118       hardware_interface::JointStateHandle joint_state_handle(joint_names[i],
00119                                                               &joints_[i].position, &joints_[i].velocity,
00120                                                               &joints_[i].effort);
00121       joint_state_interface_.registerHandle(joint_state_handle);
00122 
00123       hardware_interface::JointHandle joint_handle(
00124         joint_state_handle, &joints_[i].velocity_command);
00125       velocity_joint_interface_.registerHandle(joint_handle);
00126     }
00127     registerInterface(&joint_state_interface_);
00128     registerInterface(&velocity_joint_interface_);
00129   }
00130 
00134   void HuskyHardware::updateDiagnostics()
00135   {
00136     diagnostic_updater_.force_update();
00137     husky_status_msg_.header.stamp = ros::Time::now();
00138     diagnostic_publisher_.publish(husky_status_msg_);
00139   }
00140 
00144   void HuskyHardware::updateJointsFromHardware()
00145   {
00146 
00147     horizon_legacy::Channel<clearpath::DataEncoders>::Ptr enc = horizon_legacy::Channel<clearpath::DataEncoders>::requestData(
00148       polling_timeout_);
00149     if (enc)
00150     {
00151       ROS_DEBUG_STREAM("Received travel information (L:" << enc->getTravel(LEFT) << " R:" << enc->getTravel(RIGHT) << ")");
00152       for (int i = 0; i < 4; i++)
00153       {
00154         double delta = linearToAngular(enc->getTravel(i % 2)) - joints_[i].position - joints_[i].position_offset;
00155 
00156         // detect suspiciously large readings, possibly from encoder rollover
00157         if (std::abs(delta) < 1.0)
00158         {
00159           joints_[i].position += delta;
00160         }
00161         else
00162         {
00163           // suspicious! drop this measurement and update the offset for subsequent readings
00164           joints_[i].position_offset += delta;
00165           ROS_DEBUG("Dropping overflow measurement from encoder");
00166         }
00167       }
00168     }
00169 
00170     horizon_legacy::Channel<clearpath::DataDifferentialSpeed>::Ptr speed = horizon_legacy::Channel<clearpath::DataDifferentialSpeed>::requestData(
00171       polling_timeout_);
00172     if (speed)
00173     {
00174       ROS_DEBUG_STREAM("Received linear speed information (L:" << speed->getLeftSpeed() << " R:" << speed->getRightSpeed() << ")");
00175       for (int i = 0; i < 4; i++)
00176       {
00177         if (i % 2 == LEFT)
00178         {
00179           joints_[i].velocity = linearToAngular(speed->getLeftSpeed());
00180         }
00181         else
00182         { // assume RIGHT
00183           joints_[i].velocity = linearToAngular(speed->getRightSpeed());
00184         }
00185       }
00186     }
00187   }
00188 
00192   void HuskyHardware::writeCommandsToHardware()
00193   {
00194     double diff_speed_left = angularToLinear(joints_[LEFT].velocity_command);
00195     double diff_speed_right = angularToLinear(joints_[RIGHT].velocity_command);
00196 
00197     limitDifferentialSpeed(diff_speed_left, diff_speed_right);
00198 
00199     horizon_legacy::controlSpeed(diff_speed_left, diff_speed_right, max_accel_, max_accel_);
00200   }
00201 
00205   void HuskyHardware::reportLoopDuration(const ros::Duration &duration)
00206   {
00207     software_status_task_.updateControlFrequency(1 / duration.toSec());
00208   }
00209 
00213   void HuskyHardware::limitDifferentialSpeed(double &diff_speed_left, double &diff_speed_right)
00214   {
00215     double large_speed = std::max(std::abs(diff_speed_left), std::abs(diff_speed_right));
00216 
00217     if (large_speed > max_speed_)
00218     {
00219       diff_speed_left *= max_speed_ / large_speed;
00220       diff_speed_right *= max_speed_ / large_speed;
00221     }
00222   }
00223 
00227   double HuskyHardware::linearToAngular(const double &travel) const
00228   {
00229     return travel / wheel_diameter_ * 2;
00230   }
00231 
00235   double HuskyHardware::angularToLinear(const double &angle) const
00236   {
00237     return angle * wheel_diameter_ / 2;
00238   }
00239 
00240 
00241 }  // namespace husky_base


husky_base
Author(s): Mike Purvis , Paul Bovbel
autogenerated on Sat Jun 8 2019 18:26:01