00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
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
00052 static const int PORT_NUMBER_MAX = 65536;
00053 static const double UPDATE_FREQUENCY_MIN = 0.5;
00054 static const double UPDATE_FREQUENCY_MAX = 100.0;
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;
00058 static const double MAX_UPDATE_PERIOD = 0.05;
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }