00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <math.h>
00023
00024
00025 #include <ros/ros.h>
00026
00027
00028 #include <diagnostic_msgs/DiagnosticStatus.h>
00029 #include <diagnostic_updater/diagnostic_updater.h>
00030 #include <geometry_msgs/Twist.h>
00031 #include <nav_msgs/Odometry.h>
00032 #include <tf/transform_broadcaster.h>
00033 #include <cob_msgs/EmergencyStopState.h>
00034 #include <control_msgs/JointTrajectoryControllerState.h>
00035
00036
00037 #include <cob_undercarriage_ctrl/UndercarriageCtrlGeom.h>
00038 #include <cob_utilities/IniFile.h>
00039
00040
00041
00042
00043 class NodeClass
00044 {
00045
00046 public:
00047
00048 ros::NodeHandle n;
00049
00050
00051 ros::Publisher topic_pub_joint_state_cmd_;
00052 ros::Publisher topic_pub_controller_joint_command_;
00053 ros::Publisher topic_pub_odometry_;
00054 tf::TransformBroadcaster tf_broadcast_odometry_;
00055
00056
00057 ros::Subscriber topic_sub_CMD_pltf_twist_;
00058 ros::Subscriber topic_sub_EM_stop_state_;
00059 ros::Subscriber topic_sub_drive_diagnostic_;
00060
00061
00062
00063 ros::Subscriber topic_sub_joint_controller_states_;
00064
00065
00066 diagnostic_updater::Updater updater_;
00067
00068
00069 ros::Timer timer_ctrl_step_;
00070
00071
00072 UndercarriageCtrlGeom * ucar_ctrl_;
00073 std::string sIniDirectory;
00074 bool is_initialized_bool_;
00075 bool broadcast_tf_;
00076 int drive_chain_diagnostic_;
00077 ros::Time last_time_;
00078 ros::Time joint_state_odom_stamp_;
00079 double sample_time_, timeout_;
00080 double x_rob_m_, y_rob_m_, theta_rob_rad_;
00081 int iwatchdog_;
00082 double vel_x_rob_last_, vel_y_rob_last_, vel_theta_rob_last_;
00083 double max_vel_trans_, max_vel_rot_;
00084
00085 int m_iNumJoints;
00086
00087 diagnostic_msgs::DiagnosticStatus diagnostic_status_lookup_;
00088
00089
00090 NodeClass()
00091 {
00092
00093 is_initialized_bool_ = false;
00094 broadcast_tf_ = true;
00095 iwatchdog_ = 0;
00096 last_time_ = ros::Time::now();
00097 sample_time_ = 0.020;
00098 x_rob_m_ = 0.0;
00099 y_rob_m_ = 0.0;
00100 theta_rob_rad_ = 0.0;
00101 vel_x_rob_last_ = 0.0;
00102 vel_y_rob_last_ = 0.0;
00103 vel_theta_rob_last_ = 0.0;
00104
00105 drive_chain_diagnostic_ = diagnostic_status_lookup_.OK;
00106
00107
00108
00109 if (n.hasParam("timeout"))
00110 {
00111 n.getParam("timeout", timeout_);
00112 ROS_INFO("Timeout loaded from Parameter-Server is: %fs", timeout_);
00113 }
00114 else
00115 {
00116 ROS_WARN("No parameter timeout on Parameter-Server. Using default: 1.0s");
00117 timeout_ = 1.0;
00118 }
00119 if ( timeout_ < sample_time_ )
00120 {
00121 ROS_WARN("Specified timeout < sample_time. Setting timeout to sample_time = %fs", sample_time_);
00122 timeout_ = sample_time_;
00123 }
00124
00125
00126 if (n.hasParam("IniDirectory"))
00127 {
00128 n.getParam("IniDirectory", sIniDirectory);
00129 ROS_INFO("IniDirectory loaded from Parameter-Server is: %s", sIniDirectory.c_str());
00130 }
00131 else
00132 {
00133 sIniDirectory = "Platform/IniFiles/";
00134 ROS_WARN("IniDirectory not found on Parameter-Server, using default value: %s", sIniDirectory.c_str());
00135 }
00136
00137 if (n.hasParam("max_trans_velocity"))
00138 {
00139 n.getParam("max_trans_velocity", max_vel_trans_);
00140 ROS_INFO("Max translational velocity loaded from Parameter-Server is: %fs", max_vel_trans_);
00141 }
00142 else
00143 {
00144 ROS_WARN("No parameter max_trans_velocity on Parameter-Server. Using default: 1.1 m/s");
00145 max_vel_trans_ = 1.1;
00146 }
00147 if (n.hasParam("max_rot_velocity"))
00148 {
00149 n.getParam("max_rot_velocity", max_vel_rot_);
00150 ROS_INFO("Max rotational velocity loaded from Parameter-Server is: %fs", max_vel_rot_);
00151 }
00152 else
00153 {
00154 ROS_WARN("No parameter max_rot_velocity on Parameter-Server. Using default: 1.8 rad/s");
00155 max_vel_rot_ = 1.8;
00156 }
00157 if (n.hasParam("broadcast_tf"))
00158 {
00159 n.getParam("broadcast_tf", broadcast_tf_);
00160 }
00161
00162 IniFile iniFile;
00163 iniFile.SetFileName(sIniDirectory + "Platform.ini", "PltfHardwareCoB3.h");
00164 iniFile.GetKeyInt("Config", "NumberOfMotors", &m_iNumJoints, true);
00165
00166 ucar_ctrl_ = new UndercarriageCtrlGeom(sIniDirectory);
00167
00168
00169
00170
00171
00172 topic_pub_controller_joint_command_ = n.advertise<control_msgs::JointTrajectoryControllerState> ("joint_command", 1);
00173
00174 topic_pub_odometry_ = n.advertise<nav_msgs::Odometry>("odometry", 1);
00175
00176
00177 topic_sub_CMD_pltf_twist_ = n.subscribe("command", 1, &NodeClass::topicCallbackTwistCmd, this);
00178 topic_sub_EM_stop_state_ = n.subscribe("/emergency_stop_state", 1, &NodeClass::topicCallbackEMStop, this);
00179 topic_sub_drive_diagnostic_ = n.subscribe("diagnostic", 1, &NodeClass::topicCallbackDiagnostic, this);
00180
00181
00182
00183
00184 topic_sub_joint_controller_states_ = n.subscribe("state", 1, &NodeClass::topicCallbackJointControllerStates, this);
00185
00186
00187 updater_.setHardwareID(ros::this_node::getName());
00188 updater_.add("initialization", this, &NodeClass::diag_init);
00189
00190
00191 timer_ctrl_step_ = n.createTimer(ros::Duration(sample_time_), &NodeClass::timerCallbackCtrlStep, this);
00192
00193 }
00194
00195
00196 ~NodeClass()
00197 {
00198 }
00199
00200 void diag_init(diagnostic_updater::DiagnosticStatusWrapper &stat)
00201 {
00202 if(is_initialized_bool_)
00203 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "");
00204 else
00205 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "");
00206 stat.add("Initialized", is_initialized_bool_);
00207 }
00208
00209
00210 void topicCallbackTwistCmd(const geometry_msgs::Twist::ConstPtr& msg)
00211 {
00212 double vx_cmd_mms, vy_cmd_mms, w_cmd_rads;
00213
00214
00215 if(isnan(msg->linear.x) || isnan(msg->linear.y) || isnan(msg->angular.z)) {
00216 iwatchdog_ = 0;
00217 ROS_FATAL("Received NaN-value in Twist message. Stopping the robot.");
00218
00219 ucar_ctrl_->SetDesiredPltfVelocity(0.0, 0.0, 0.0, 0.0);
00220 ROS_DEBUG("Forced platform velocity commands to zero");
00221 return;
00222 }
00223
00224 if( (fabs(msg->linear.x) > max_vel_trans_) || (fabs(msg->linear.y) > max_vel_trans_) || (fabs(msg->angular.z) > max_vel_rot_))
00225 {
00226 if(fabs(msg->linear.x) > max_vel_trans_)
00227 {
00228 ROS_DEBUG_STREAM("Recevied cmdVelX: " << msg->linear.x <<
00229 ", which is bigger than the maximal allowed translational velocity: " << max_vel_trans_ << " so stop the robot");
00230 }
00231 if(fabs(msg->linear.y) > max_vel_trans_)
00232 {
00233 ROS_DEBUG_STREAM("Recevied cmdVelY: " << msg->linear.x <<
00234 ", which is bigger than the maximal allowed translational velocity: " << max_vel_trans_ << " so stop the robot");
00235 }
00236
00237 if(fabs(msg->angular.z) > max_vel_rot_)
00238 {
00239 ROS_DEBUG_STREAM("Recevied cmdVelTh: " << msg->angular.z <<
00240 ", which is bigger than the maximal allowed rotational velocity: " << max_vel_rot_ << " so stop the robot");
00241 }
00242 vx_cmd_mms = 0.0;
00243 vy_cmd_mms = 0.0;
00244 w_cmd_rads = 0.0;
00245 }
00246 else
00247 {
00248
00249
00250 vx_cmd_mms = msg->linear.x*1000.0;
00251 vy_cmd_mms = msg->linear.y*1000.0;
00252 w_cmd_rads = msg->angular.z;
00253 }
00254
00255 iwatchdog_ = 0;
00256
00257
00258 if (is_initialized_bool_ && drive_chain_diagnostic_==diagnostic_status_lookup_.OK)
00259 {
00260 ROS_DEBUG("received new velocity command [cmdVelX=%3.5f,cmdVelY=%3.5f,cmdVelTh=%3.5f]",
00261 msg->linear.x, msg->linear.y, msg->angular.z);
00262
00263
00264 ucar_ctrl_->SetDesiredPltfVelocity(vx_cmd_mms, vy_cmd_mms, w_cmd_rads, 0.0);
00265
00266 }
00267 else
00268 {
00269
00270 ucar_ctrl_->SetDesiredPltfVelocity( 0.0, 0.0, 0.0, 0.0);
00271
00272 ROS_DEBUG("Forced platform-velocity cmds to zero");
00273 }
00274
00275 }
00276
00277
00278 void topicCallbackEMStop(const cob_msgs::EmergencyStopState::ConstPtr& msg)
00279 {
00280 int EM_state;
00281 EM_state = msg->emergency_state;
00282
00283 if (EM_state == msg->EMFREE)
00284 {
00285
00286 if (is_initialized_bool_)
00287 {
00288 ucar_ctrl_->setEMStopActive(false);
00289 ROS_DEBUG("Undercarriage Controller EM-Stop released");
00290
00291
00292 }
00293 }
00294 else
00295 {
00296 ROS_DEBUG("Undercarriage Controller stopped due to EM-Stop");
00297
00298
00299 ucar_ctrl_->SetDesiredPltfVelocity( 0.0, 0.0, 0.0, 0.0);
00300
00301 ROS_DEBUG("Forced platform-velocity cmds to zero");
00302
00303
00304 ucar_ctrl_->setEMStopActive(true);
00305 }
00306 }
00307
00308
00309 void topicCallbackDiagnostic(const diagnostic_msgs::DiagnosticStatus::ConstPtr& msg)
00310 {
00311 control_msgs::JointTrajectoryControllerState joint_state_cmd;
00312
00313
00314 joint_state_cmd.header.stamp = ros::Time::now();
00315
00316
00317
00318
00319 joint_state_cmd.desired.positions.resize(m_iNumJoints);
00320 joint_state_cmd.desired.velocities.resize(m_iNumJoints);
00321
00322 joint_state_cmd.joint_names.push_back("fl_caster_r_wheel_joint");
00323 joint_state_cmd.joint_names.push_back("fl_caster_rotation_joint");
00324 joint_state_cmd.joint_names.push_back("bl_caster_r_wheel_joint");
00325 joint_state_cmd.joint_names.push_back("bl_caster_rotation_joint");
00326 joint_state_cmd.joint_names.push_back("br_caster_r_wheel_joint");
00327 joint_state_cmd.joint_names.push_back("br_caster_rotation_joint");
00328 joint_state_cmd.joint_names.push_back("fr_caster_r_wheel_joint");
00329 joint_state_cmd.joint_names.push_back("fr_caster_rotation_joint");
00330 joint_state_cmd.joint_names.resize(m_iNumJoints);
00331
00332
00333 for(int i=0; i<m_iNumJoints; i++)
00334 {
00335 joint_state_cmd.desired.positions[i] = 0.0;
00336 joint_state_cmd.desired.velocities[i] = 0.0;
00337
00338 }
00339
00340
00341 drive_chain_diagnostic_ = msg->level;
00342
00343
00344 if (is_initialized_bool_)
00345 {
00346
00347 if (drive_chain_diagnostic_ != diagnostic_status_lookup_.OK)
00348 {
00349
00350 ROS_DEBUG("drive chain not availlable: halt Controller");
00351
00352
00353 ucar_ctrl_->setEMStopActive(true);
00354
00355
00356 ucar_ctrl_->SetDesiredPltfVelocity( 0.0, 0.0, 0.0, 0.0);
00357
00358 ROS_DEBUG("Forced platform-velocity cmds to zero");
00359
00360
00361 if (drive_chain_diagnostic_ != diagnostic_status_lookup_.WARN)
00362 {
00363
00364
00365 }
00366 }
00367 }
00368
00369 else
00370 {
00371
00372 if(drive_chain_diagnostic_ != diagnostic_status_lookup_.WARN)
00373 {
00374
00375 topic_pub_controller_joint_command_.publish(joint_state_cmd);
00376 }
00377 }
00378 }
00379
00380 void topicCallbackJointControllerStates(const control_msgs::JointTrajectoryControllerState::ConstPtr& msg) {
00381 int num_joints;
00382 int iter_k, iter_j;
00383 std::vector<double> drive_joint_ang_rad, drive_joint_vel_rads, drive_joint_effort_NM;
00384 std::vector<double> steer_joint_ang_rad, steer_joint_vel_rads, steer_joint_effort_NM;
00385
00386 joint_state_odom_stamp_ = msg->header.stamp;
00387
00388
00389 num_joints = msg->joint_names.size();
00390
00391 drive_joint_ang_rad.assign(m_iNumJoints, 0.0);
00392 drive_joint_vel_rads.assign(m_iNumJoints, 0.0);
00393 drive_joint_effort_NM.assign(m_iNumJoints, 0.0);
00394
00395 steer_joint_ang_rad.assign(m_iNumJoints, 0.0);
00396 steer_joint_vel_rads.assign(m_iNumJoints, 0.0);
00397 steer_joint_effort_NM.assign(m_iNumJoints, 0.0);
00398
00399
00400 iter_k = 0;
00401 iter_j = 0;
00402
00403 for(int i = 0; i < num_joints; i++)
00404 {
00405
00406
00407 if(msg->joint_names[i] == "fl_caster_r_wheel_joint")
00408 {
00409 drive_joint_ang_rad[0] = msg->actual.positions[i];
00410 drive_joint_vel_rads[0] = msg->actual.velocities[i];
00411
00412 }
00413 if(msg->joint_names[i] == "bl_caster_r_wheel_joint")
00414 {
00415 drive_joint_ang_rad[1] = msg->actual.positions[i];
00416 drive_joint_vel_rads[1] = msg->actual.velocities[i];
00417
00418 }
00419 if(msg->joint_names[i] == "br_caster_r_wheel_joint")
00420 {
00421 drive_joint_ang_rad[2] = msg->actual.positions[i];
00422 drive_joint_vel_rads[2] = msg->actual.velocities[i];
00423
00424 }
00425 if(msg->joint_names[i] == "fr_caster_r_wheel_joint")
00426 {
00427 drive_joint_ang_rad[3] = msg->actual.positions[i];
00428 drive_joint_vel_rads[3] = msg->actual.velocities[i];
00429
00430 }
00431 if(msg->joint_names[i] == "fl_caster_rotation_joint")
00432 {
00433 steer_joint_ang_rad[0] = msg->actual.positions[i];
00434 steer_joint_vel_rads[0] = msg->actual.velocities[i];
00435
00436 }
00437 if(msg->joint_names[i] == "bl_caster_rotation_joint")
00438 {
00439 steer_joint_ang_rad[1] = msg->actual.positions[i];
00440 steer_joint_vel_rads[1] = msg->actual.velocities[i];
00441
00442 }
00443 if(msg->joint_names[i] == "br_caster_rotation_joint")
00444 {
00445 steer_joint_ang_rad[2] = msg->actual.positions[i];
00446 steer_joint_vel_rads[2] = msg->actual.velocities[i];
00447
00448 }
00449 if(msg->joint_names[i] == "fr_caster_rotation_joint")
00450 {
00451 steer_joint_ang_rad[3] = msg->actual.positions[i];
00452 steer_joint_vel_rads[3] = msg->actual.velocities[i];
00453
00454 }
00455 }
00456
00457
00458 ucar_ctrl_->SetActualWheelValues(drive_joint_vel_rads, steer_joint_vel_rads,
00459 drive_joint_ang_rad, steer_joint_ang_rad);
00460
00461
00462
00463 UpdateOdometry();
00464
00465 }
00466
00467 void timerCallbackCtrlStep(const ros::TimerEvent& e) {
00468 CalcCtrlStep();
00469 }
00470
00471
00472
00473 bool InitCtrl();
00474
00475 void CalcCtrlStep();
00476
00477
00478 void UpdateOdometry();
00479 };
00480
00481
00482
00483 int main(int argc, char** argv)
00484 {
00485
00486 ros::init(argc, argv, "undercarriage_ctrl");
00487
00488
00489 NodeClass nodeClass;
00490
00491
00492 nodeClass.ucar_ctrl_->InitUndercarriageCtrl();
00493 nodeClass.is_initialized_bool_ = true;
00494
00495 if( nodeClass.is_initialized_bool_ ) {
00496 nodeClass.last_time_ = ros::Time::now();
00497 ROS_INFO("Undercarriage control successfully initialized.");
00498 } else {
00499 ROS_FATAL("Undercarriage control initialization failed!");
00500 throw std::runtime_error("Undercarriage control initialization failed, check ini-Files!");
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 ros::spin();
00510
00511 return 0;
00512 }
00513
00514
00515
00516
00517
00518 void NodeClass::CalcCtrlStep()
00519 {
00520 double vx_cmd_ms, vy_cmd_ms, w_cmd_rads, dummy;
00521 std::vector<double> drive_jointvel_cmds_rads, steer_jointvel_cmds_rads, steer_jointang_cmds_rad;
00522 control_msgs::JointTrajectoryControllerState joint_state_cmd;
00523 int j, k;
00524 iwatchdog_ += 1;
00525
00526
00527 if (is_initialized_bool_)
00528 {
00529
00530
00531
00532
00533
00534
00535
00536 ucar_ctrl_->GetNewCtrlStateSteerDriveSetValues(drive_jointvel_cmds_rads, steer_jointvel_cmds_rads, steer_jointang_cmds_rad, vx_cmd_ms, vy_cmd_ms, w_cmd_rads, dummy);
00537
00538
00539
00540 if(drive_chain_diagnostic_ != diagnostic_status_lookup_.OK)
00541 {
00542 steer_jointang_cmds_rad.assign(m_iNumJoints, 0.0);
00543 steer_jointvel_cmds_rads.assign(m_iNumJoints, 0.0);
00544 }
00545
00546
00547 vx_cmd_ms = vx_cmd_ms/1000.0;
00548 vy_cmd_ms = vy_cmd_ms/1000.0;
00549
00550
00551
00552 joint_state_cmd.header.stamp = ros::Time::now();
00553
00554
00555
00556
00557 joint_state_cmd.desired.positions.resize(m_iNumJoints);
00558 joint_state_cmd.desired.velocities.resize(m_iNumJoints);
00559
00560 joint_state_cmd.joint_names.push_back("fl_caster_r_wheel_joint");
00561 joint_state_cmd.joint_names.push_back("fl_caster_rotation_joint");
00562 joint_state_cmd.joint_names.push_back("bl_caster_r_wheel_joint");
00563 joint_state_cmd.joint_names.push_back("bl_caster_rotation_joint");
00564 joint_state_cmd.joint_names.push_back("br_caster_r_wheel_joint");
00565 joint_state_cmd.joint_names.push_back("br_caster_rotation_joint");
00566 joint_state_cmd.joint_names.push_back("fr_caster_r_wheel_joint");
00567 joint_state_cmd.joint_names.push_back("fr_caster_rotation_joint");
00568 joint_state_cmd.joint_names.resize(m_iNumJoints);
00569
00570
00571 j = 0;
00572 k = 0;
00573 for(int i = 0; i<m_iNumJoints; i++)
00574 {
00575 if(iwatchdog_ < (int) std::floor(timeout_/sample_time_) )
00576 {
00577
00578 if( i == 1 || i == 3 || i == 5 || i == 7)
00579 {
00580 joint_state_cmd.desired.positions[i] = steer_jointang_cmds_rad[j];
00581 joint_state_cmd.desired.velocities[i] = steer_jointvel_cmds_rads[j];
00582
00583 j = j + 1;
00584 }
00585 else
00586 {
00587 joint_state_cmd.desired.positions[i] = 0.0;
00588 joint_state_cmd.desired.velocities[i] = drive_jointvel_cmds_rads[k];
00589
00590 k = k + 1;
00591 }
00592 }
00593 else
00594 {
00595 joint_state_cmd.desired.positions[i] = 0.0;
00596 joint_state_cmd.desired.velocities[i] = 0.0;
00597
00598 }
00599 }
00600
00601
00602 topic_pub_controller_joint_command_.publish(joint_state_cmd);
00603 }
00604
00605 }
00606
00607
00608
00609 void NodeClass::UpdateOdometry()
00610 {
00611 double vel_x_rob_ms, vel_y_rob_ms, vel_rob_ms, rot_rob_rads, delta_x_rob_m, delta_y_rob_m, delta_theta_rob_rad;
00612 double dummy1, dummy2;
00613 double dt;
00614 ros::Time current_time;
00615
00616
00617
00618 if (is_initialized_bool_)
00619 {
00620
00621
00622
00623
00624 ucar_ctrl_->GetActualPltfVelocity(delta_x_rob_m, delta_y_rob_m, delta_theta_rob_rad, dummy1,
00625 vel_x_rob_ms, vel_y_rob_ms, rot_rob_rads, dummy2);
00626
00627
00628 vel_x_rob_ms = vel_x_rob_ms/1000.0;
00629 vel_y_rob_ms = vel_y_rob_ms/1000.0;
00630 delta_x_rob_m = delta_x_rob_m/1000.0;
00631 delta_y_rob_m = delta_y_rob_m/1000.0;
00632
00633 ROS_DEBUG("Odmonetry delta is: x=%f, y=%f, th=%f", delta_x_rob_m, delta_y_rob_m, rot_rob_rads);
00634 }
00635 else
00636 {
00637
00638 vel_x_rob_ms = 0.0;
00639 vel_y_rob_ms = 0.0;
00640 delta_x_rob_m = 0.0;
00641 delta_y_rob_m = 0.0;
00642 }
00643
00644
00645
00646 current_time = ros::Time::now();
00647 dt = current_time.toSec() - last_time_.toSec();
00648 last_time_ = current_time;
00649 vel_rob_ms = sqrt(vel_x_rob_ms*vel_x_rob_ms + vel_y_rob_ms*vel_y_rob_ms);
00650
00651
00652 x_rob_m_ = x_rob_m_ + ((vel_x_rob_ms+vel_x_rob_last_)/2.0 * cos(theta_rob_rad_) - (vel_y_rob_ms+vel_y_rob_last_)/2.0 * sin(theta_rob_rad_)) * dt;
00653 y_rob_m_ = y_rob_m_ + ((vel_x_rob_ms+vel_x_rob_last_)/2.0 * sin(theta_rob_rad_) + (vel_y_rob_ms+vel_y_rob_last_)/2.0 * cos(theta_rob_rad_)) * dt;
00654 theta_rob_rad_ = theta_rob_rad_ + rot_rob_rads * dt;
00655
00656
00657 vel_x_rob_last_ = vel_x_rob_ms;
00658 vel_y_rob_last_ = vel_y_rob_ms;
00659 vel_theta_rob_last_ = rot_rob_rads;
00660
00661
00662
00663
00664 geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(theta_rob_rad_);
00665
00666 if (broadcast_tf_ == true)
00667 {
00668
00669 geometry_msgs::TransformStamped odom_tf;
00670
00671 odom_tf.header.stamp = joint_state_odom_stamp_;
00672 odom_tf.header.frame_id = "/odom_combined";
00673 odom_tf.child_frame_id = "/base_footprint";
00674
00675 odom_tf.transform.translation.x = x_rob_m_;
00676 odom_tf.transform.translation.y = y_rob_m_;
00677 odom_tf.transform.translation.z = 0.0;
00678 odom_tf.transform.rotation = odom_quat;
00679
00680
00681 tf_broadcast_odometry_.sendTransform(odom_tf);
00682 }
00683
00684
00685 nav_msgs::Odometry odom_top;
00686
00687 odom_top.header.stamp = joint_state_odom_stamp_;
00688 odom_top.header.frame_id = "/odom_combined";
00689 odom_top.child_frame_id = "/base_footprint";
00690
00691 odom_top.pose.pose.position.x = x_rob_m_;
00692 odom_top.pose.pose.position.y = y_rob_m_;
00693 odom_top.pose.pose.position.z = 0.0;
00694 odom_top.pose.pose.orientation = odom_quat;
00695 for(int i = 0; i < 6; i++)
00696 odom_top.pose.covariance[i*6+i] = 0.1;
00697
00698
00699 odom_top.twist.twist.linear.x = vel_x_rob_ms;
00700 odom_top.twist.twist.linear.y = vel_y_rob_ms;
00701 odom_top.twist.twist.linear.z = 0.0;
00702 odom_top.twist.twist.angular.x = 0.0;
00703 odom_top.twist.twist.angular.y = 0.0;
00704 odom_top.twist.twist.angular.z = rot_rob_rads;
00705 for(int i = 0; i < 6; i++)
00706 odom_top.twist.covariance[6*i+i] = 0.1;
00707
00708
00709 topic_pub_odometry_.publish(odom_top);
00710 }
00711
00712
00713
00714