Rmp440LE.cpp
Go to the documentation of this file.
00001 /*
00002   COPYRIGHT (c) 2014 SEGWAY Inc.
00003 
00004   Software License Agreement:
00005 
00006   The software supplied herewith by Segway Inc. (the "Company") for its 
00007   RMP Robotic Platforms is intended and supplied to you, the Company's 
00008   customer, for use solely and exclusively with Segway products. The 
00009   software is owned by the Company and/or its supplier, and is protected 
00010   under applicable copyright laws.  All rights are reserved. Any use in 
00011   violation of the foregoing restrictions may subject the user to criminal
00012   sanctions under applicable laws, as well as to civil liability for the 
00013   breach of the terms and conditions of this license. The Company may 
00014   immediately terminate this Agreement upon your use of the software with 
00015   any products that are not Segway products.
00016 
00017   You shall indemnify, defend and hold the Company harmless from any claims, 
00018   demands, liabilities or expenses, including reasonable attorneys fees, incurred 
00019   by the Company as a result of any claim or proceeding against the Company 
00020   arising out of or based upon: 
00021 
00022   (i) The combination, operation or use of the software by you with any hardware, 
00023       products, programs or data not supplied or approved in writing by the Company, 
00024       if such claim or proceeding would have been avoided but for such combination, 
00025       operation or use.
00026 
00027   (ii) The modification of the software by or on behalf of you.
00028 
00029   (iii) Your use of the software.
00030 
00031   THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
00032   WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED
00033   TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00034   PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
00035   IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
00036   CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
00037 */
00038 
00039 #include "Rmp440LE.h"
00040 
00041 #include <sstream>
00042 
00043 #include <nav_msgs/Odometry.h>
00044 #include <sensor_msgs/Imu.h>
00045 #include <tf/transform_datatypes.h>
00046 #include <rmp_msgs/MotorStatus.h>
00047 #include <rmp_msgs/Battery.h>
00048 
00049 #include <RmpConfigurationCommand.h>
00050 
00051 // Constant definitions
00052 static const int PORT_NUMBER_MAX = 65536; 
00053 static const double UPDATE_FREQUENCY_MIN = 0.5; // [Hz]
00054 static const double UPDATE_FREQUENCY_MAX = 100.0; // [Hz]
00055 static const double G_TO_M_S2 = 9.80665;
00056 static const float DEG_TO_RAD = 0.0174532925;
00057 static const double DEADMAN_VALIDITY_PERIOD = 0.5; // [s]
00058 static const double MAX_UPDATE_PERIOD = 0.05; // [s]
00059 static const double UNKNOWN_COV = 99999.0;
00060 static const size_t WHEEL_COUNT = 4;
00061 static const std::string LEFT_FRONT_WHEEL_JOINT_NAME("left_front_wheel");
00062 static const std::string RIGHT_FRONT_WHEEL_JOINT_NAME("right_front_wheel");
00063 static const std::string LEFT_REAR_WHEEL_JOINT_NAME("left_rear_wheel");
00064 static const std::string RIGHT_REAR_WHEEL_JOINT_NAME("right_rear_wheel");
00065 static const size_t LEFT_FRONT_WHEEL_IDX = 0;
00066 static const size_t RIGHT_FRONT_WHEEL_IDX = 1; 
00067 static const size_t LEFT_REAR_WHEEL_IDX = 2;
00068 static const size_t RIGHT_REAR_WHEEL_IDX = 3; 
00069 
00070 Rmp440LE::Rmp440LE()
00071   : m_NodeHandle("~")
00072   , m_OdometryInitialized(false)
00073 {
00074 }
00075 
00076 Rmp440LE::~Rmp440LE()
00077 {
00078   m_Rmp440LEInterface.ShutDown();
00079 }
00080 
00081 void Rmp440LE::Initialize()
00082 {
00083   // Parameters
00084   std::string transportType, ipAddress, devicePort;
00085   int portNumber;
00086   std::string odometryTopic, jointStatesTopic, inertialTopic, pseTopic, motorStatusTopic, batteryTopic, velocityCommandTopic, deadmanTopic, audioCommandTopic, faultStatusTopic;
00087   double updateFrequency, maxTranslationalVelocity, maxTurnRate;
00088   
00089   m_NodeHandle.param("transport_type", transportType, std::string("udp"));
00090   m_NodeHandle.param("ip_address", ipAddress, std::string("192.168.0.40"));
00091   m_NodeHandle.param("port_number", portNumber, 8080);
00092   m_NodeHandle.param("device_port", devicePort, std::string("/dev/ttyACM0"));
00093   m_NodeHandle.param("update_frequency", updateFrequency, 50.0);
00094   m_NodeHandle.param("odometry_topic", odometryTopic, std::string("/rmp440le/odom"));
00095   m_NodeHandle.param("joint_states_topic", jointStatesTopic, std::string("/rmp440le/joint_states"));
00096   m_NodeHandle.param("inertial_topic", inertialTopic, std::string("/rmp440le/inertial"));
00097   m_NodeHandle.param("pse_topic", pseTopic, std::string("/rmp440le/pse"));
00098   m_NodeHandle.param("motor_status_topic", motorStatusTopic, std::string("/rmp440le/motor_status"));
00099   m_NodeHandle.param("battery_topic", batteryTopic, std::string("/rmp440le/battery"));
00100   m_NodeHandle.param("velocity_command_topic", velocityCommandTopic, std::string("/rmp440le/base/vel_cmd"));
00101   m_NodeHandle.param("deadman_topic", deadmanTopic, std::string("/rmp440le/deadman"));
00102   m_NodeHandle.param("audio_command_topic", audioCommandTopic, std::string("/rmp440le/audio_cmd"));
00103   m_NodeHandle.param("fault_status_topic", faultStatusTopic, std::string("/rmp440le/fault_status"));
00104   m_NodeHandle.param("max_translational_velocity", maxTranslationalVelocity, 8.0);
00105   m_NodeHandle.param("max_turn_rate", maxTurnRate, 4.4);
00106 
00107   // Start communication
00108   try 
00109   {
00110     if (transportType == std::string("udp"))
00111     {
00112       if ((portNumber < 0) || (portNumber > PORT_NUMBER_MAX))
00113       {
00114         ROS_ERROR_STREAM("Invalid port number: " << portNumber << " should be between 0 and " << PORT_NUMBER_MAX);
00115         return;
00116       }
00117       
00118       m_Rmp440LEInterface.Initialize(ipAddress, static_cast<uint16_t>(portNumber));
00119     }
00120     else if (transportType == std::string("usb"))
00121     {
00122       m_Rmp440LEInterface.Initialize(devicePort);
00123     }
00124     else
00125     {
00126       ROS_ERROR_STREAM("Unknown/unsupported transport: " << transportType);
00127       return;
00128     }
00129     
00130     m_Rmp440LEInterface.ResetParamsToDefault();
00131 
00132     m_Rmp440LEInterface.SetConfiguration(segway::RmpConfigurationCommandSet::SET_AUDIO_COMMAND, static_cast<uint32_t>(segway::MOTOR_AUDIO_TEST_SWEEP));
00133 
00134     ros::Duration(2.0).sleep();
00135 
00136     // Reset wheel encoders
00137     bool integratorsReset = m_Rmp440LEInterface.ResetIntegrators(segway::RESET_ALL_POSITION_DATA);
00138 
00139     if (!integratorsReset)
00140     {
00141       ROS_WARN_STREAM("Unable to reset position integrators.");
00142     }
00143     else
00144     {
00145       m_Rmp440LEInterface.SetConfiguration(segway::RmpConfigurationCommandSet::SET_AUDIO_COMMAND, static_cast<uint32_t>(segway::MOTOR_AUDIO_TEST_SWEEP));
00146     }
00147 
00148     ros::Duration(2.0).sleep();
00149 
00150     // Set the max speeds
00151     bool maxSpeedSet = m_Rmp440LEInterface.SetConfiguration(segway::RmpConfigurationCommandSet::SET_MAXIMUM_VELOCITY, static_cast<float>(maxTranslationalVelocity));
00152     maxSpeedSet = maxSpeedSet && m_Rmp440LEInterface.SetConfiguration(segway::RmpConfigurationCommandSet::SET_MAXIMUM_TURN_RATE, static_cast<float>(maxTurnRate));
00153 
00154     if (!maxSpeedSet)
00155     {
00156       ROS_WARN_STREAM("Unable to set the maximum speed.");
00157     }
00158     else
00159     {
00160       m_Rmp440LEInterface.SetConfiguration(segway::RmpConfigurationCommandSet::SET_AUDIO_COMMAND, static_cast<uint32_t>(segway::MOTOR_AUDIO_TEST_SWEEP));
00161     }
00162 
00163     // Set up ROS communication
00164     m_OdometryPublisher = m_NodeHandle.advertise<nav_msgs::Odometry>(odometryTopic, 1);
00165     m_JointStatesPublisher = m_NodeHandle.advertise<sensor_msgs::JointState>(jointStatesTopic, 1);
00166     m_InertialPublisher = m_NodeHandle.advertise<sensor_msgs::Imu>(inertialTopic, 1);
00167     m_PsePublisher = m_NodeHandle.advertise<sensor_msgs::Imu>(pseTopic, 1);
00168     m_MotorStatusPublisher = m_NodeHandle.advertise<rmp_msgs::MotorStatus>(motorStatusTopic, 1);
00169     m_BatteryPublisher = m_NodeHandle.advertise<rmp_msgs::Battery>(batteryTopic, 1);
00170     m_FaultStatusPublisher = m_NodeHandle.advertise<rmp_msgs::FaultStatus>(faultStatusTopic, 1);
00171     m_VelocityCommandSubscriber = m_NodeHandle.subscribe<geometry_msgs::TwistStamped>(velocityCommandTopic, 1, &Rmp440LE::ProcessVelocityCommand, this);
00172     m_DeadmanSubscriber = m_NodeHandle.subscribe<rmp_msgs::BoolStamped>(deadmanTopic, 1, &Rmp440LE::ProcessDeadman, this);
00173     m_AudioCommandSubscriber = m_NodeHandle.subscribe<rmp_msgs::AudioCommand>(audioCommandTopic, 1, &Rmp440LE::ProcessAudioCommand, this);
00174     
00175     if (updateFrequency < UPDATE_FREQUENCY_MIN)
00176     {
00177       updateFrequency = UPDATE_FREQUENCY_MIN;
00178     }
00179     else if (updateFrequency > UPDATE_FREQUENCY_MAX)
00180     {
00181       updateFrequency = UPDATE_FREQUENCY_MAX;
00182     }
00183     
00184     ros::Rate rate(updateFrequency);
00185 
00186     InitializeMessages();
00187 
00188     ros::Time lastUpdate = ros::Time::now();
00189     ros::Duration maxUpdatePeriod(MAX_UPDATE_PERIOD);
00190     bool forceUpdate = false;
00191     
00192     // Processing loop
00193     while (ros::ok())
00194     {
00195       ros::spinOnce();
00196 
00197       if ((ros::Time::now() - lastUpdate) > maxUpdatePeriod)
00198       {
00199         forceUpdate = true;
00200       }
00201 
00202       if (m_Rmp440LEInterface.Update(forceUpdate))
00203       {
00204         UpdateStatus();
00205         lastUpdate = ros::Time::now();
00206         forceUpdate = false;
00207       }
00208 
00209       rate.sleep();
00210     }
00211   } 
00212   catch (std::exception& rException) 
00213   {
00214     ROS_ERROR_STREAM("Exception caught: " << rException.what() << ". Will return.");
00215     return;
00216   }
00217 }
00218 
00219 void Rmp440LE::InitializeMessages()
00220 {
00221   std::string baseFrame, odometryFrame, inertialFrame, pseFrame;
00222 
00223   m_NodeHandle.param("base_frame", baseFrame, std::string("/rmp440le/base_footprint"));
00224   m_NodeHandle.param("odometry_frame", odometryFrame, std::string("/rmp440le/odom"));
00225   m_NodeHandle.param("inertial_frame", inertialFrame, std::string("/rmp440le/inertial"));
00226   m_NodeHandle.param("pse_frame", pseFrame, std::string("/rmp440le/pse"));
00227   
00228   m_OdometryMsg.header.frame_id = odometryFrame;
00229   m_OdometryMsg.child_frame_id = baseFrame;
00230   m_OdometryMsg.pose.pose = geometry_msgs::Pose();
00231   m_OdometryMsg.pose.pose.orientation = tf::createQuaternionMsgFromYaw(0.0);
00232   m_OdometryMsg.pose.covariance = {{ UNKNOWN_COV, 0, 0, 0, 0, 0,
00233                                      0, UNKNOWN_COV, 0, 0, 0, 0,
00234                                      0, 0, UNKNOWN_COV, 0, 0, 0,
00235                                      0, 0, 0, UNKNOWN_COV, 0, 0,
00236                                      0, 0, 0, 0, UNKNOWN_COV, 0,
00237                                      0, 0, 0, 0, 0, UNKNOWN_COV }};
00238 
00239   m_JointStateMsg.name.resize(WHEEL_COUNT);
00240   m_JointStateMsg.position.resize(WHEEL_COUNT, 0.0);
00241   m_JointStateMsg.velocity.resize(WHEEL_COUNT, 0.0);
00242   m_JointStateMsg.effort.resize(0);
00243   m_JointStateMsg.name[LEFT_FRONT_WHEEL_IDX] = LEFT_FRONT_WHEEL_JOINT_NAME;
00244   m_JointStateMsg.name[RIGHT_FRONT_WHEEL_IDX] = RIGHT_FRONT_WHEEL_JOINT_NAME;
00245   m_JointStateMsg.name[LEFT_REAR_WHEEL_IDX] = LEFT_REAR_WHEEL_JOINT_NAME;
00246   m_JointStateMsg.name[RIGHT_REAR_WHEEL_IDX] = RIGHT_REAR_WHEEL_JOINT_NAME;
00247 
00248 
00249   m_InertialMsg.header.frame_id = inertialFrame;
00250 
00251   boost::array<double, 9> covariance = {{ UNKNOWN_COV, 0, 0,
00252                                           0, UNKNOWN_COV, 0,
00253                                           0, 0, UNKNOWN_COV }};
00254 
00255   m_InertialMsg.orientation_covariance = covariance;
00256   m_InertialMsg.angular_velocity_covariance = covariance;
00257   m_InertialMsg.linear_acceleration_covariance = covariance;
00258 
00259   m_PseMsg = m_InertialMsg;
00260   m_PseMsg.header.frame_id = pseFrame;
00261 }
00262 
00263 void Rmp440LE::ProcessVelocityCommand(const geometry_msgs::TwistStamped::ConstPtr& rpVelocityCommand)
00264 {
00265   if (!IsDeadmanValid())
00266   {
00267     return;
00268   }
00269   
00270   if (m_Rmp440LEInterface.GetUserDefinedFeedback<uint32_t>(segway::OPERATIONAL_STATE) != segway::TRACTOR_MODE)
00271   {
00272     ROS_WARN_STREAM("Velocity command won't be processed. The rmp is in " << m_Rmp440LEInterface.GetUserDefinedFeedback<uint32_t>(segway::OPERATIONAL_STATE) << " mode and should be in " << segway::TRACTOR_MODE << " (TRACTOR)");
00273 
00274     return;
00275   }
00276   
00277   float maximumVelocity = m_Rmp440LEInterface.GetMaximumVelocity();
00278   float maximumTurnRate = m_Rmp440LEInterface.GetMaximumTurnRate();
00279 
00280   if ((maximumVelocity <= 0.0) || (maximumTurnRate <= 0))
00281   {
00282     std::stringstream stringStream;
00283     stringStream << "Invalid max velocity/turn rate: " << maximumVelocity << "/" << maximumTurnRate;
00284     
00285     throw std::logic_error(stringStream.str());
00286   }
00287   
00288   float normalizedVelocity = static_cast<float>(rpVelocityCommand->twist.linear.x) / maximumVelocity;
00289   // Segway defines yaw as negative z
00290   float normalizedYawRate = -1.0 * static_cast<float>(rpVelocityCommand->twist.angular.z) / maximumTurnRate;
00291   
00292   if ((normalizedVelocity > fabs(1.0)) || (normalizedYawRate > fabs(1.0)))
00293   {
00294     ROS_WARN_STREAM("Velocity command out of range: " << rpVelocityCommand->twist.linear.x << ", " << rpVelocityCommand->twist.angular.z << " should be within: " << maximumVelocity << " [m/s], " << maximumTurnRate << " [rad/s]");
00295     
00296     return;
00297   }
00298   
00299   m_Rmp440LEInterface.SetVelocity(normalizedVelocity, normalizedYawRate);
00300 }
00301 
00302 void Rmp440LE::ProcessDeadman(const rmp_msgs::BoolStamped::ConstPtr& rpDeadmanMsg)
00303 {
00304   m_DeadmanMsg = *rpDeadmanMsg;
00305 }
00306 
00307 void Rmp440LE::ProcessAudioCommand(const rmp_msgs::AudioCommand::ConstPtr& rpAudioCommand)
00308 {
00309   uint32_t command = rpAudioCommand->command;
00310       
00311   if ((command < segway::MOTOR_AUDIO_PLAY_NO_SONG) || (command > segway::MOTOR_AUDIO_SIMULATE_MOTOR_NOISE))
00312   {
00313     ROS_WARN_STREAM("Invalid audio command received: " << command << " should be between " << segway::MOTOR_AUDIO_PLAY_NO_SONG << " and " << segway::MOTOR_AUDIO_SIMULATE_MOTOR_NOISE << ". Won't be processed.");
00314 
00315     return;
00316   }
00317   
00318   m_Rmp440LEInterface.SetConfiguration(segway::RmpConfigurationCommandSet::SET_AUDIO_COMMAND, command);
00319 }
00320 
00321 void Rmp440LE::UpdateStatus()
00322 {
00323   UpdateImu();
00324   UpdateOdometry();
00325   UpdateBattery();
00326   UpdateMotorStatus();
00327   UpdateFaultStatus();
00328 }
00329 
00330 void Rmp440LE::UpdateImu()
00331 {
00332   // Pse Data
00333   uint32_t pseDataIsValid = m_Rmp440LEInterface.GetUserDefinedFeedback<uint32_t>(segway::PSE_DATA_IS_VALID);
00334   if (pseDataIsValid >= segway::PSE_VALID)
00335   {
00336     float pitch = DEG_TO_RAD * m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::PSE_PITCH_DEG);
00337     float roll = DEG_TO_RAD * m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::PSE_ROLL_DEG);
00338 
00339     m_PseMsg.orientation = tf::createQuaternionMsgFromRollPitchYaw(roll, pitch, 0.0);
00340     m_PseMsg.angular_velocity.x = DEG_TO_RAD * m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::PSE_PITCH_RATE_DPS);
00341     m_PseMsg.angular_velocity.y = DEG_TO_RAD * m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::PSE_ROLL_RATE_DPS);
00342     m_PseMsg.angular_velocity.z  = DEG_TO_RAD * m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::PSE_YAW_RATE_DPS);
00343     m_PseMsg.header.stamp = ros::Time::now();
00344 
00345     m_PsePublisher.publish(m_PseMsg);
00346   }
00347 
00348   // Inertial data
00349   m_InertialMsg.linear_acceleration.x = G_TO_M_S2 * m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::INERTIAL_X_ACC_G);
00350   m_InertialMsg.linear_acceleration.y = G_TO_M_S2 * m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::INERTIAL_Y_ACC_G);
00351   m_InertialMsg.linear_acceleration.z = 0.0;
00352   m_InertialMsg.angular_velocity.x = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::INERTIAL_X_RATE_RPS);
00353   m_InertialMsg.angular_velocity.y = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::INERTIAL_Y_RATE_RPS);
00354   m_InertialMsg.angular_velocity.z = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::INERTIAL_Z_RATE_RPS);
00355   m_InertialMsg.header.stamp = ros::Time::now();
00356 
00357   m_InertialPublisher.publish(m_InertialMsg);
00358 }
00359 
00360 void Rmp440LE::UpdateOdometry()  
00361 {
00362   double linearDisplacement = static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LINEAR_POS_M));
00363   double leftFrontDisplacement = static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LEFT_FRONT_POS_M));
00364   double leftRearDisplacement = static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LEFT_REAR_POS_M));
00365   double rightFrontDisplacement = static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::RIGHT_FRONT_POS_M));
00366   double rightRearDisplacement = static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::RIGHT_REAR_POS_M));
00367 
00368   if (m_OdometryInitialized)
00369   {
00370     double deltaLinearDisplacement = linearDisplacement - m_WheelsDisplacement.m_Linear;
00371     double deltaLeftSideDisplacement = ((leftFrontDisplacement - m_WheelsDisplacement.m_LeftFront) + (leftRearDisplacement - m_WheelsDisplacement.m_LeftRear)) / 2.0;
00372     double deltaRightSideDisplacement = ((rightFrontDisplacement - m_WheelsDisplacement.m_RightFront) + (rightRearDisplacement - m_WheelsDisplacement.m_RightRear)) / 2.0;
00373 
00374     double wheelTrackWidth = static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::FRAM_WHEEL_TRACK_WIDTH_M));
00375     double deltaHeading = (deltaRightSideDisplacement - deltaLeftSideDisplacement) / wheelTrackWidth;
00376 
00377     double previousHeading = tf::getYaw(m_OdometryMsg.pose.pose.orientation);
00378     double averageHeading = previousHeading + deltaHeading / 2.0;
00379 
00380     m_OdometryMsg.pose.pose.position.x += deltaLinearDisplacement * cos(averageHeading);
00381     m_OdometryMsg.pose.pose.position.y += deltaLinearDisplacement * sin(averageHeading);
00382     m_OdometryMsg.pose.pose.orientation = tf::createQuaternionMsgFromYaw(previousHeading + deltaHeading);
00383     m_OdometryMsg.twist.twist.linear.x = static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LINEAR_VEL_MPS));
00384     m_OdometryMsg.twist.twist.angular.z = -1.0 * static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::DIFFERENTIAL_WHEEL_VEL_RPS));
00385     m_OdometryMsg.header.stamp = ros::Time::now();
00386 
00387     m_OdometryPublisher.publish(m_OdometryMsg);
00388   }
00389   else
00390   {
00391     m_OdometryInitialized = true;
00392   }
00393 
00394   // Update
00395   m_WheelsDisplacement.m_Linear = linearDisplacement;
00396   m_WheelsDisplacement.m_LeftFront = leftFrontDisplacement;
00397   m_WheelsDisplacement.m_LeftRear = leftRearDisplacement;
00398   m_WheelsDisplacement.m_RightFront = rightFrontDisplacement;
00399   m_WheelsDisplacement.m_RightRear = rightRearDisplacement;
00400 
00401   double inverseRadius = 2.0 / static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::FRAM_TIRE_DIAMETER_M));
00402   
00403   m_JointStateMsg.position[LEFT_FRONT_WHEEL_IDX] = inverseRadius * leftFrontDisplacement;
00404   m_JointStateMsg.position[RIGHT_FRONT_WHEEL_IDX] = inverseRadius * rightFrontDisplacement;
00405   m_JointStateMsg.position[LEFT_REAR_WHEEL_IDX] = inverseRadius * leftRearDisplacement;
00406   m_JointStateMsg.position[RIGHT_REAR_WHEEL_IDX] = inverseRadius * rightRearDisplacement;
00407   m_JointStateMsg.velocity[LEFT_FRONT_WHEEL_IDX] = inverseRadius * static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LEFT_FRONT_VEL_MPS));
00408   m_JointStateMsg.velocity[RIGHT_FRONT_WHEEL_IDX] = inverseRadius * static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::RIGHT_FRONT_VEL_MPS));
00409   m_JointStateMsg.velocity[LEFT_REAR_WHEEL_IDX] = inverseRadius * static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LEFT_REAR_VEL_MPS));
00410   m_JointStateMsg.velocity[RIGHT_REAR_WHEEL_IDX] = inverseRadius * static_cast<double>(m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::RIGHT_REAR_VEL_MPS));
00411   m_JointStateMsg.header.stamp = ros::Time::now();
00412 
00413   m_JointStatesPublisher.publish(m_JointStateMsg);
00414 }
00415 
00416 void Rmp440LE::UpdateBattery()
00417 {
00418   rmp_msgs::Battery batteryMsg;
00419   // Soc
00420   batteryMsg.charge_state[rmp_msgs::Battery::BATT_FRONT_1_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::FRONT_BASE_BATT_1_SOC);
00421   batteryMsg.charge_state[rmp_msgs::Battery::BATT_FRONT_2_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::FRONT_BASE_BATT_2_SOC);
00422   batteryMsg.charge_state[rmp_msgs::Battery::BATT_REAR_1_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::REAR_BASE_BATT_1_SOC);
00423   batteryMsg.charge_state[rmp_msgs::Battery::BATT_REAR_2_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::REAR_BASE_BATT_2_SOC);
00424   batteryMsg.charge_state[rmp_msgs::Battery::BATT_AUX_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::AUX_BATT_SOC);
00425   // Temperature
00426   batteryMsg.temperature[rmp_msgs::Battery::BATT_FRONT_1_IDX] =  m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::FRONT_BASE_BATT_1_TEMP_DEGC);
00427   batteryMsg.temperature[rmp_msgs::Battery::BATT_FRONT_2_IDX] =  m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::FRONT_BASE_BATT_2_TEMP_DEGC);
00428   batteryMsg.temperature[rmp_msgs::Battery::BATT_REAR_1_IDX] =  m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::REAR_BASE_BATT_1_TEMP_DEGC);
00429   batteryMsg.temperature[rmp_msgs::Battery::BATT_REAR_2_IDX] =  m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::REAR_BASE_BATT_2_TEMP_DEGC);
00430   batteryMsg.temperature[rmp_msgs::Battery::BATT_AUX_IDX] =  m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::AUX_BATT_TEMP_DEGC);
00431   // Other fields...
00432   batteryMsg.min_propulsion_charge_state = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MIN_PROPULSION_BATT_SOC);
00433   batteryMsg.aux_battery_voltage = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::AUX_BATT_VOLTAGE_V);
00434   batteryMsg.aux_battery_current = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::AUX_BATT_CURRENT_A);
00435   batteryMsg.abb_system_status = m_Rmp440LEInterface.GetUserDefinedFeedback<uint32_t>(segway::ABB_SYSTEM_STATUS);
00436   batteryMsg.aux_battery_status = m_Rmp440LEInterface.GetUserDefinedFeedback<uint32_t>(segway::AUX_BATT_STATUS);
00437   batteryMsg.header.stamp = ros::Time::now();
00438   
00439   m_BatteryPublisher.publish(batteryMsg);
00440 }
00441 
00442 void Rmp440LE::UpdateMotorStatus()
00443 {
00444   rmp_msgs::MotorStatus motorStatus;
00445   // Current 
00446   motorStatus.current[rmp_msgs::MotorStatus::RIGHT_FRONT_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::RIGHT_FRONT_CURRENT_A0PK);
00447   motorStatus.current[rmp_msgs::MotorStatus::LEFT_FRONT_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LEFT_FRONT_CURRENT_A0PK);
00448   motorStatus.current[rmp_msgs::MotorStatus::RIGHT_REAR_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::RIGHT_REAR_CURRENT_A0PK);
00449   motorStatus.current[rmp_msgs::MotorStatus::LEFT_REAR_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LEFT_REAR_CURRENT_A0PK);
00450   // Current limit
00451   motorStatus.current_limit[rmp_msgs::MotorStatus::RIGHT_FRONT_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::RIGHT_FRONT_CURRENT_LIMIT_A0PK);
00452   motorStatus.current_limit[rmp_msgs::MotorStatus::LEFT_FRONT_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LEFT_FRONT_CURRENT_LIMIT_A0PK);
00453   motorStatus.current_limit[rmp_msgs::MotorStatus::RIGHT_REAR_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::RIGHT_REAR_CURRENT_LIMIT_A0PK);
00454   motorStatus.current_limit[rmp_msgs::MotorStatus::LEFT_REAR_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::LEFT_REAR_CURRENT_LIMIT_A0PK);
00455   // Mcu inst power
00456   motorStatus.mcu_inst_power[rmp_msgs::MotorStatus::RIGHT_FRONT_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MCU_0_INST_POWER_W);
00457   motorStatus.mcu_inst_power[rmp_msgs::MotorStatus::LEFT_FRONT_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MCU_1_INST_POWER_W);
00458   motorStatus.mcu_inst_power[rmp_msgs::MotorStatus::RIGHT_REAR_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MCU_2_INST_POWER_W);
00459   motorStatus.mcu_inst_power[rmp_msgs::MotorStatus::LEFT_REAR_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MCU_3_INST_POWER_W);
00460   // Mcu total energy
00461   motorStatus.mcu_total_energy[rmp_msgs::MotorStatus::RIGHT_FRONT_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MCU_0_TOTAL_ENERGY_WH);
00462   motorStatus.mcu_total_energy[rmp_msgs::MotorStatus::LEFT_FRONT_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MCU_1_TOTAL_ENERGY_WH);
00463   motorStatus.mcu_total_energy[rmp_msgs::MotorStatus::RIGHT_REAR_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MCU_2_TOTAL_ENERGY_WH);
00464   motorStatus.mcu_total_energy[rmp_msgs::MotorStatus::LEFT_REAR_IDX] = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MCU_3_TOTAL_ENERGY_WH);
00465   // Other fields...
00466   motorStatus.max_current = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MAX_MOTOR_CURRENT_A0PK);
00467   motorStatus.min_current_limit = m_Rmp440LEInterface.GetUserDefinedFeedback<float>(segway::MIN_MOTOR_CURRENT_LIMIT_A0PK);
00468   motorStatus.header.stamp = ros::Time::now();
00469 
00470   m_MotorStatusPublisher.publish(motorStatus);
00471 }
00472 
00473 void Rmp440LE::UpdateFaultStatus()
00474 {
00475   rmp_msgs::FaultStatus faultStatus;
00476   m_Rmp440LEInterface.GetFaultStatusDescription(faultStatus.fault_list);
00477   faultStatus.header.stamp = ros::Time::now();
00478 
00479   m_FaultStatusPublisher.publish(faultStatus);
00480 }
00481 
00482 bool Rmp440LE::IsDeadmanValid()
00483 {
00484   ros::Duration duration = ros::Time::now() - m_DeadmanMsg.header.stamp;
00485   
00486   if ( m_DeadmanMsg.data &&
00487        (duration < ros::Duration(DEADMAN_VALIDITY_PERIOD)) )
00488   {
00489     return true;
00490   }
00491 
00492   return false;
00493 }


rmp_base
Author(s):
autogenerated on Wed Aug 26 2015 16:24:39