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