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 #include <ros/ros.h>
00036 #include <sensor_msgs/JointState.h>
00037 #include <sensor_msgs/Imu.h>
00038 #include <geometry_msgs/Twist.h>
00039 #include <std_msgs/Float64.h>
00040 #include <tf/transform_broadcaster.h>
00041 #include <nav_msgs/Odometry.h>
00042 #include <robotnik_msgs/set_mode.h>
00043 #include <robotnik_msgs/get_mode.h>
00044 #include <robotnik_msgs/set_odometry.h>
00045 #include <robotnik_msgs/ptz.h>
00046 #include <gazebo_msgs/ModelState.h>
00047
00048
00049 #include "diagnostic_msgs/DiagnosticStatus.h"
00050 #include "diagnostic_updater/diagnostic_updater.h"
00051 #include "diagnostic_updater/update_functions.h"
00052 #include "diagnostic_updater/DiagnosticStatusWrapper.h"
00053 #include "diagnostic_updater/publisher.h"
00054
00055
00056 #define PI 3.1415926535
00057 #define SUMMIT_XL_MIN_COMMAND_REC_FREQ 5.0
00058 #define SUMMIT_XL_MAX_COMMAND_REC_FREQ 150.0
00059
00060 #define SKID_STEERING 1
00061 #define MECANUM_STEERING 2
00062
00063 #define SUMMIT_XL_WHEEL_DIAMETER 0.25 // Default wheel diameter
00064 #define SUMMIT_XL_D_TRACKS_M 1.0 // default equivalent W distance (difference is due to slippage of skid steering)
00065 #define SUMMIT_XL_WHEELBASE 0.446 // default real L distance forward to rear axis
00066 #define SUMMIT_XL_TRACKWIDTH 0.408 // default real W distance from left wheels to right wheels
00067
00068 using namespace std;
00069
00070 class SummitXLControllerClass {
00071
00072 public:
00073
00074 ros::NodeHandle node_handle_;
00075 ros::NodeHandle private_node_handle_;
00076 double desired_freq_;
00077
00078
00079 diagnostic_updater::Updater diagnostic_;
00080 diagnostic_updater::FrequencyStatus freq_diag_;
00081 diagnostic_updater::HeaderlessTopicDiagnostic *subs_command_freq;
00082 ros::Time last_command_time_;
00083 diagnostic_updater::FunctionDiagnosticTask command_freq_;
00084
00085
00086 std::string robot_model_;
00087
00088
00089 ros::Publisher ref_vel_flw_;
00090 ros::Publisher ref_vel_frw_;
00091 ros::Publisher ref_vel_blw_;
00092 ros::Publisher ref_vel_brw_;
00093 ros::Publisher ref_pos_flw_;
00094 ros::Publisher ref_pos_frw_;
00095 ros::Publisher ref_pos_blw_;
00096 ros::Publisher ref_pos_brw_;
00097 ros::Publisher ref_pos_scissor_;
00098 ros::Publisher ref_pos_pan_;
00099 ros::Publisher ref_pos_tilt_;
00100
00101 ros::Publisher gazebo_set_model_;
00102
00103
00104 ros::Subscriber joint_state_sub_;
00105
00106
00107 ros::Subscriber cmd_sub_;
00108
00109
00110 ros::Subscriber ptz_sub_;
00111
00112
00113
00114
00115 ros::ServiceServer srv_SetOdometry_;
00116 ros::ServiceServer srv_SetMode_;
00117 ros::ServiceServer srv_GetMode_;
00118
00119
00120 std::string frw_vel_topic_;
00121 std::string flw_vel_topic_;
00122 std::string brw_vel_topic_;
00123 std::string blw_vel_topic_;
00124
00125
00126 std::string joint_front_right_wheel;
00127 std::string joint_front_left_wheel;
00128 std::string joint_back_left_wheel;
00129 std::string joint_back_right_wheel;
00130
00131
00132 std::string frw_pos_topic_;
00133 std::string flw_pos_topic_;
00134 std::string brw_pos_topic_;
00135 std::string blw_pos_topic_;
00136
00137
00138 std::string joint_front_right_steer;
00139 std::string joint_front_left_steer;
00140 std::string joint_back_left_steer;
00141 std::string joint_back_right_steer;
00142
00143
00144 std::string scissor_pos_topic_;
00145
00146
00147 std::string odom_topic_;
00148
00149
00150 std::string joint_camera_pan;
00151 std::string joint_camera_tilt;
00152
00153
00154 std::string pan_pos_topic_;
00155 std::string tilt_pos_topic_;
00156
00157
00158 std::string scissor_prismatic_joint;
00159
00160
00161 int kinematic_modes_;
00162 int active_kinematic_mode_;
00163
00164
00165 int frw_vel_, flw_vel_, blw_vel_, brw_vel_;
00166 int frw_pos_, flw_pos_, blw_pos_, brw_pos_;
00167 int scissor_pos_;
00168 int pan_pos_, tilt_pos_;
00169
00170
00171
00172 double linearSpeedXMps_;
00173 double linearSpeedYMps_;
00174 double angularSpeedRads_;
00175
00176
00177 double robot_pose_px_;
00178 double robot_pose_py_;
00179 double robot_pose_pa_;
00180 double robot_pose_vx_;
00181 double robot_pose_vy_;
00182
00183
00184 sensor_msgs::JointState joint_state_;
00185
00186
00187 geometry_msgs::Twist base_vel_msg_;
00188
00189
00190 double v_ref_x_;
00191 double v_ref_y_;
00192 double w_ref_;
00193 double v_ref_z_;
00194 double pos_ref_pan_;
00195 double pos_ref_tilt_;
00196
00197
00198 bool read_state_;
00199
00200
00201 double summit_xl_wheel_diameter_;
00202 double summit_xl_d_tracks_m_;
00203 double summit_xl_wheelbase_;
00204 double summit_xl_trackwidth_;
00205
00206
00207 double ang_vel_x_;
00208 double ang_vel_y_;
00209 double ang_vel_z_;
00210
00211 double lin_acc_x_;
00212 double lin_acc_y_;
00213 double lin_acc_z_;
00214
00215 double orientation_x_;
00216 double orientation_y_;
00217 double orientation_z_;
00218 double orientation_w_;
00219
00220
00221 bool publish_odom_tf_;
00222 bool publish_odom_msg_;
00223
00224 ros::Subscriber imu_sub_;
00225
00226
00227 ros::Publisher odom_pub_;
00228
00229
00230 tf::TransformBroadcaster odom_broadcaster;
00231
00232
00236 SummitXLControllerClass(ros::NodeHandle h) : diagnostic_(),
00237 node_handle_(h), private_node_handle_("~"),
00238 desired_freq_(100),
00239 freq_diag_(diagnostic_updater::FrequencyStatusParam(&desired_freq_, &desired_freq_, 0.05) ),
00240 command_freq_("Command frequency check", boost::bind(&SummitXLControllerClass::check_command_subscriber, this, _1))
00241 {
00242
00243
00244 ROS_INFO("summit_xl_robot_control_node - Init ");
00245
00246
00247
00248 kinematic_modes_ = 1;
00249
00250
00251 if (!private_node_handle_.getParam("model", robot_model_)) {
00252 ROS_ERROR("Robot model not defined.");
00253 exit(-1);
00254 }
00255 else ROS_INFO("Robot Model : %s", robot_model_.c_str());
00256
00257
00258 private_node_handle_.param<std::string>("frw_vel_topic", frw_vel_topic_, "joint_frw_velocity_controller/command");
00259 private_node_handle_.param<std::string>("flw_vel_topic", flw_vel_topic_, "joint_flw_velocity_controller/command");
00260 private_node_handle_.param<std::string>("blw_vel_topic", blw_vel_topic_, "joint_blw_velocity_controller/command");
00261 private_node_handle_.param<std::string>("brw_vel_topic", brw_vel_topic_, "joint_brw_velocity_controller/command");
00262
00263
00264 private_node_handle_.param<std::string>("joint_front_right_wheel", joint_front_right_wheel, "joint_front_right_wheel");
00265 private_node_handle_.param<std::string>("joint_front_left_wheel", joint_front_left_wheel, "joint_front_left_wheel");
00266 private_node_handle_.param<std::string>("joint_back_left_wheel", joint_back_left_wheel, "joint_back_left_wheel");
00267 private_node_handle_.param<std::string>("joint_back_right_wheel", joint_back_right_wheel, "joint_back_right_wheel");
00268
00269 if (!private_node_handle_.getParam("summit_xl_wheelbase", summit_xl_wheelbase_))
00270 summit_xl_wheelbase_ = SUMMIT_XL_WHEELBASE;
00271 if (!private_node_handle_.getParam("summit_xl_trackwidth", summit_xl_trackwidth_))
00272 summit_xl_trackwidth_ = SUMMIT_XL_TRACKWIDTH;
00273
00274
00275 if ((robot_model_=="summit_xl_omni") || (robot_model_=="x_wam")) {
00276 kinematic_modes_ = 2;
00277
00278
00279 if (robot_model_=="x_wam") {
00280 private_node_handle_.param<std::string>("scissor_pos_topic", scissor_pos_topic_, "joint_scissor_position_controller/command");
00281 private_node_handle_.param<std::string>("scissor_prismatic_joint", scissor_prismatic_joint, "scissor_prismatic_joint");
00282 }
00283 }
00284
00285
00286 private_node_handle_.param<std::string>("pan_pos_topic", pan_pos_topic_, "joint_pan_position_controller/command");
00287 private_node_handle_.param<std::string>("tilt_pos_topic", tilt_pos_topic_, "joint_tilt_position_controller/command");
00288 private_node_handle_.param<std::string>("joint_camera_pan", joint_camera_pan, "joint_camera_pan");
00289 private_node_handle_.param<std::string>("joint_camera_tilt", joint_camera_tilt, "joint_camera_tilt");
00290
00291
00292 node_handle_.param<std::string>("odom_topic", odom_topic_, "/odom");
00293
00294
00295 if (!private_node_handle_.getParam("summit_xl_wheel_diameter", summit_xl_wheel_diameter_))
00296 summit_xl_wheel_diameter_ = SUMMIT_XL_WHEEL_DIAMETER;
00297 if (!private_node_handle_.getParam("summit_xl_d_tracks_m", summit_xl_d_tracks_m_))
00298 summit_xl_d_tracks_m_ = SUMMIT_XL_D_TRACKS_M;
00299
00300 ROS_INFO("summit_xl_wheel_diameter_ = %5.2f", summit_xl_wheel_diameter_);
00301 ROS_INFO("summit_xl_d_tracks_m_ = %5.2f", summit_xl_d_tracks_m_);
00302
00303 private_node_handle_.param("publish_odom_tf", publish_odom_tf_, true);
00304 private_node_handle_.param("publish_odom_msg", publish_odom_msg_, true);
00305
00306 if (publish_odom_tf_) ROS_INFO("PUBLISHING odom->base_footprint tf");
00307 else ROS_INFO("NOT PUBLISHING odom->base_footprint tf");
00308
00309 if (publish_odom_msg_) ROS_INFO("PUBLISHING odom->base_footprint msg");
00310 else ROS_INFO("NOT PUBLISHING odom->base_footprint msg");
00311
00312
00313 linearSpeedXMps_ = 0.0;
00314 linearSpeedYMps_ = 0.0;
00315 angularSpeedRads_ = 0.0;
00316
00317
00318 robot_pose_px_ = 0.0;
00319 robot_pose_py_ = 0.0;
00320 robot_pose_pa_ = 0.0;
00321 robot_pose_vx_ = 0.0;
00322 robot_pose_vy_ = 0.0;
00323
00324
00325 v_ref_x_ = 0.0;
00326 v_ref_y_ = 0.0;
00327 w_ref_ = 0.0;
00328 v_ref_z_ = 0.0;
00329 pos_ref_pan_ = 0.0;
00330 pos_ref_tilt_= 0.0;
00331
00332
00333 ang_vel_x_ = 0.0; ang_vel_y_ = 0.0; ang_vel_z_ = 0.0;
00334 lin_acc_x_ = 0.0; lin_acc_y_ = 0.0; lin_acc_z_ = 0.0;
00335 orientation_x_ = 0.0; orientation_y_ = 0.0; orientation_z_ = 0.0; orientation_w_ = 1.0;
00336
00337
00338 active_kinematic_mode_ = SKID_STEERING;
00339
00340
00341 srv_SetMode_ = node_handle_.advertiseService("/summit_xl_controller/set_mode", &SummitXLControllerClass::srvCallback_SetMode, this);
00342 srv_GetMode_ = node_handle_.advertiseService("get_mode", &SummitXLControllerClass::srvCallback_GetMode, this);
00343 srv_SetOdometry_ = node_handle_.advertiseService("set_odometry", &SummitXLControllerClass::srvCallback_SetOdometry, this);
00344
00345
00346 joint_state_sub_ = node_handle_.subscribe<sensor_msgs::JointState>("/joint_states", 1, &SummitXLControllerClass::jointStateCallback, this);
00347
00348
00349 imu_sub_ = node_handle_.subscribe("/imu/data", 1, &SummitXLControllerClass::imuCallback, this);
00350
00351
00352
00353 ref_vel_frw_ = node_handle_.advertise<std_msgs::Float64>( frw_vel_topic_, 50);
00354 ref_vel_flw_ = node_handle_.advertise<std_msgs::Float64>( flw_vel_topic_, 50);
00355 ref_vel_blw_ = node_handle_.advertise<std_msgs::Float64>( blw_vel_topic_, 50);
00356 ref_vel_brw_ = node_handle_.advertise<std_msgs::Float64>( brw_vel_topic_, 50);
00357
00358
00359 if (robot_model_=="x_wam") {
00360 ref_pos_scissor_ = node_handle_.advertise<std_msgs::Float64>( scissor_pos_topic_, 50);
00361 }
00362
00363 ref_pos_pan_ = node_handle_.advertise<std_msgs::Float64>( pan_pos_topic_, 50);
00364 ref_pos_tilt_ = node_handle_.advertise<std_msgs::Float64>( tilt_pos_topic_, 50);
00365
00366
00367 cmd_sub_ = node_handle_.subscribe<geometry_msgs::Twist>("/summit_xl_control/cmd_vel", 1, &SummitXLControllerClass::commandCallback, this);
00368
00369
00370 ptz_sub_ = node_handle_.subscribe<robotnik_msgs::ptz>("/axis_camera/ptz_command", 1, &SummitXLControllerClass::command_ptzCallback, this);
00371
00372
00373 odom_pub_ = node_handle_.advertise<nav_msgs::Odometry>(odom_topic_, 1000);
00374
00375
00376 diagnostic_.setHardwareID("summit_xl_robot_control - simulation");
00377 diagnostic_.add( freq_diag_ );
00378 diagnostic_.add( command_freq_ );
00379
00380 gazebo_set_model_ = node_handle_.advertise<gazebo_msgs::ModelState>("/gazebo/set_model_state", 1);
00381
00382
00383
00384 double min_freq = SUMMIT_XL_MIN_COMMAND_REC_FREQ;
00385 double max_freq = SUMMIT_XL_MAX_COMMAND_REC_FREQ;
00386 subs_command_freq = new diagnostic_updater::HeaderlessTopicDiagnostic("/summit_xl_control/cmd_vel", diagnostic_,
00387 diagnostic_updater::FrequencyStatusParam(&min_freq, &max_freq, 0.1, 10));
00388 subs_command_freq->addTask(&command_freq_);
00389
00390
00391 read_state_ = false;
00392 }
00393
00395 int starting()
00396 {
00397
00398 ROS_INFO("SummitXLControllerClass::starting");
00399
00400
00401 if (read_state_) {
00402 vector<string> joint_names = joint_state_.name;
00403 frw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_front_right_wheel)) - joint_names.begin();
00404 flw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_front_left_wheel)) - joint_names.begin();
00405 blw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_back_left_wheel)) - joint_names.begin();
00406 brw_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_back_right_wheel)) - joint_names.begin();
00407 if (robot_model_=="x_wam") {
00408 scissor_pos_ = find (joint_names.begin(),joint_names.end(), string(scissor_prismatic_joint)) - joint_names.begin();
00409 }
00410
00411
00412
00413 return 0;
00414 }
00415 else return -1;
00416 }
00417
00418
00420 void UpdateControl()
00421 {
00422
00423 if (active_kinematic_mode_ == SKID_STEERING) {
00424 double v_left_mps, v_right_mps;
00425
00426
00427 v_left_mps = ((joint_state_.velocity[blw_vel_] + joint_state_.velocity[flw_vel_]) / 2.0) * (summit_xl_wheel_diameter_ / 2.0);
00428 v_right_mps = ((joint_state_.velocity[brw_vel_] + joint_state_.velocity[frw_vel_]) / 2.0) * (summit_xl_wheel_diameter_ / 2.0);
00429
00430
00431 linearSpeedXMps_ = (v_right_mps + v_left_mps) / 2.0;
00432 angularSpeedRads_ = (v_right_mps - v_left_mps) / summit_xl_d_tracks_m_;
00433
00434 std_msgs::Float64 frw_ref_msg;
00435 std_msgs::Float64 flw_ref_msg;
00436 std_msgs::Float64 blw_ref_msg;
00437 std_msgs::Float64 brw_ref_msg;
00438
00439 frw_ref_msg.data = (v_ref_x_ + w_ref_* summit_xl_d_tracks_m_/2.0) / (summit_xl_wheel_diameter_ / 2.0);
00440 brw_ref_msg.data = (v_ref_x_ + w_ref_* summit_xl_d_tracks_m_/2.0) / (summit_xl_wheel_diameter_ / 2.0);
00441 flw_ref_msg.data = (v_ref_x_ - w_ref_* summit_xl_d_tracks_m_/2.0) / (summit_xl_wheel_diameter_ / 2.0);
00442 blw_ref_msg.data = (v_ref_x_ - w_ref_* summit_xl_d_tracks_m_/2.0) / (summit_xl_wheel_diameter_ / 2.0);
00443
00444 ref_vel_frw_.publish( frw_ref_msg );
00445 ref_vel_flw_.publish( flw_ref_msg );
00446 ref_vel_blw_.publish( blw_ref_msg );
00447 ref_vel_brw_.publish( brw_ref_msg );
00448 }
00449
00450
00451
00452 if (active_kinematic_mode_ == MECANUM_STEERING) {
00453
00454
00455
00456 double v_frw_mps, v_flw_mps, v_blw_mps, v_brw_mps;
00457 v_frw_mps = joint_state_.velocity[frw_vel_] * (summit_xl_wheel_diameter_ / 2.0);
00458 v_flw_mps = joint_state_.velocity[flw_vel_] * (summit_xl_wheel_diameter_ / 2.0);
00459 v_blw_mps = joint_state_.velocity[blw_vel_] * (summit_xl_wheel_diameter_ / 2.0);
00460 v_brw_mps = joint_state_.velocity[brw_vel_] * (summit_xl_wheel_diameter_ / 2.0);
00461
00462 double vx = v_ref_x_;
00463 double vy = v_ref_y_;
00464 double w = w_ref_;
00465 double L = summit_xl_wheelbase_;
00466 double W = summit_xl_trackwidth_;
00467
00468 double lab = (SUMMIT_XL_WHEELBASE + SUMMIT_XL_TRACKWIDTH) / 2.0;
00469 double q1 = (v_ref_x_ + v_ref_y_ + lab * w_ref_) / (summit_xl_wheel_diameter_ / 2.0);
00470 double q2 = (v_ref_x_ - v_ref_y_ - lab * w_ref_) / (summit_xl_wheel_diameter_ / 2.0);
00471 double q3 = (v_ref_x_ + v_ref_y_ - lab * w_ref_) / (summit_xl_wheel_diameter_ / 2.0);
00472 double q4 = (v_ref_x_ - v_ref_y_ + lab * w_ref_) / (summit_xl_wheel_diameter_ / 2.0);
00473
00474
00475
00476
00477 double limit = 40.0;
00478
00479
00480 std_msgs::Float64 frw_ref_vel_msg;
00481 std_msgs::Float64 flw_ref_vel_msg;
00482 std_msgs::Float64 blw_ref_vel_msg;
00483 std_msgs::Float64 brw_ref_vel_msg;
00484
00485 frw_ref_vel_msg.data = saturation(q1, -limit, limit);
00486 flw_ref_vel_msg.data = saturation(q2, -limit, limit);
00487 blw_ref_vel_msg.data = saturation(q3, -limit, limit);
00488 brw_ref_vel_msg.data = saturation(q4, -limit, limit);
00489
00490 ref_vel_frw_.publish( frw_ref_vel_msg );
00491 ref_vel_flw_.publish( flw_ref_vel_msg );
00492 ref_vel_blw_.publish( blw_ref_vel_msg );
00493 ref_vel_brw_.publish( brw_ref_vel_msg );
00494 }
00495
00496
00497 if (robot_model_ == "x_wam") {
00498
00499 static double scissor_ref_pos = 0.0;
00500 scissor_ref_pos += (v_ref_z_ / desired_freq_);
00501 std_msgs::Float64 scissor_ref_pos_msg;
00502
00503 scissor_ref_pos_msg.data = saturation(scissor_ref_pos, 0.0, 0.5);
00504 ref_pos_scissor_.publish( scissor_ref_pos_msg );
00505 }
00506
00507
00508 std_msgs::Float64 pan_ref_pos_msg, tilt_ref_pos_msg;
00509 pan_ref_pos_msg.data = pos_ref_pan_;
00510 ref_pos_pan_.publish( pan_ref_pos_msg );
00511 tilt_ref_pos_msg.data = pos_ref_tilt_;
00512 ref_pos_tilt_.publish( tilt_ref_pos_msg );
00513 }
00514
00515
00516 void UpdateOdometry()
00517 {
00518
00519
00520 if (active_kinematic_mode_ == SKID_STEERING) {
00521
00522
00523 robot_pose_vx_ = linearSpeedXMps_ * cos(robot_pose_pa_);
00524 robot_pose_vy_ = linearSpeedXMps_ * sin(robot_pose_pa_);
00525 }
00526
00527
00528 if (active_kinematic_mode_ == MECANUM_STEERING) {
00529
00530
00531 double v1, v2, v3, v4;
00532 v1 = joint_state_.velocity[frw_vel_] * (summit_xl_wheel_diameter_ / 2.0);
00533 v2 = joint_state_.velocity[flw_vel_] * (summit_xl_wheel_diameter_ / 2.0);
00534 v3 = joint_state_.velocity[blw_vel_] * (summit_xl_wheel_diameter_ / 2.0);
00535 v4 = joint_state_.velocity[brw_vel_] * (summit_xl_wheel_diameter_ / 2.0);
00536
00537 double lab = (SUMMIT_XL_WHEELBASE + SUMMIT_XL_TRACKWIDTH) / 2.0;
00538
00539 double vx = (1 / 4.0) * (v1 + v2 + v3 + v4);
00540 double vy = (1 / 4.0) * (v1 - v2 + v3 - v4);
00541 double wr = (1 / (4.0 * lab)) * (v1 - v2 - v3 + v4);
00542
00543 robot_pose_vx_ = vx;
00544 robot_pose_vy_ = vy;
00545 }
00546
00547
00548 double fSamplePeriod = 1.0 / desired_freq_;
00549
00550
00551
00552 double roll, pitch, yaw;
00553 tf::Matrix3x3(tf::Quaternion(orientation_x_, orientation_y_, orientation_z_, orientation_w_)).getRPY(roll, pitch, yaw);
00554 robot_pose_pa_ = yaw;
00555 robot_pose_px_ += robot_pose_vx_ * fSamplePeriod;
00556 robot_pose_py_ += robot_pose_vy_ * fSamplePeriod;
00557
00558 }
00559
00560
00561 void PublishOdometry()
00562 {
00563 ros::Time current_time = ros::Time::now();
00564
00565
00566 geometry_msgs::TransformStamped odom_trans;
00567 odom_trans.header.stamp = current_time;
00568 odom_trans.header.frame_id = "odom";
00569 odom_trans.child_frame_id = "base_footprint";
00570
00571 odom_trans.transform.translation.x = robot_pose_px_;
00572 odom_trans.transform.translation.y = robot_pose_py_;
00573 odom_trans.transform.translation.z = 0.0;
00574 odom_trans.transform.rotation.x = orientation_x_;
00575 odom_trans.transform.rotation.y = orientation_y_;
00576 odom_trans.transform.rotation.z = orientation_z_;
00577 odom_trans.transform.rotation.w = orientation_w_;
00578
00579
00580
00581
00582 if (publish_odom_tf_) {
00583 odom_broadcaster.sendTransform(odom_trans);
00584 }
00585
00586
00587 nav_msgs::Odometry odom;
00588 odom.header.stamp = current_time;
00589 odom.header.frame_id = "odom";
00590
00591
00592
00593 odom.pose.pose.position.x = robot_pose_px_;
00594 odom.pose.pose.position.y = robot_pose_py_;
00595 odom.pose.pose.position.z = 0.0;
00596
00597 odom.pose.pose.orientation.x = orientation_x_;
00598 odom.pose.pose.orientation.y = orientation_y_;
00599 odom.pose.pose.orientation.z = orientation_z_;
00600 odom.pose.pose.orientation.w = orientation_w_;
00601
00602 for(int i = 0; i < 6; i++)
00603 odom.pose.covariance[i*6+i] = 0.001;
00604 odom.twist.covariance[35] = 0.03;
00605
00606
00607 odom.child_frame_id = "base_footprint";
00608
00609
00610
00611 if (active_kinematic_mode_ == SKID_STEERING) {
00612 odom.twist.twist.linear.x = linearSpeedXMps_;
00613 odom.twist.twist.linear.y = 0;
00614 }
00615 else if (active_kinematic_mode_ == MECANUM_STEERING) {
00616 odom.twist.twist.linear.x = robot_pose_vx_;
00617 odom.twist.twist.linear.y = robot_pose_vy_;
00618 }
00619
00620 odom.twist.twist.linear.z = 0.0;
00621
00622 odom.twist.twist.angular.x = ang_vel_x_;
00623 odom.twist.twist.angular.y = ang_vel_y_;
00624 odom.twist.twist.angular.z = ang_vel_z_;
00625
00626 for(int i = 0; i < 6; i++)
00627 odom.twist.covariance[6*i+i] = 0.001;
00628 odom.twist.covariance[35] = 0.03;
00629
00630
00631 if (publish_odom_msg_)
00632 odom_pub_.publish(odom);
00633
00634
00635
00636
00637
00638
00639 }
00640
00642 void stopping()
00643 {}
00644
00645
00646
00647
00648
00649
00650 void check_command_subscriber(diagnostic_updater::DiagnosticStatusWrapper &stat)
00651 {
00652 ros::Time current_time = ros::Time::now();
00653
00654 double diff = (current_time - last_command_time_).toSec();
00655
00656 if(diff > 1.0){
00657 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Topic is not receiving commands");
00658
00659
00660 }else{
00661 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Topic receiving commands");
00662 }
00663 }
00664
00665
00666
00667 void setCommand(const geometry_msgs::Twist &cmd_vel)
00668 {
00669 v_ref_x_ = saturation(cmd_vel.linear.x, -10.0, 10.0);
00670 v_ref_y_ = saturation(cmd_vel.linear.y, -10.0, 10.0);
00671 w_ref_ = saturation(cmd_vel.angular.z, -10.0, 10.0);
00672 v_ref_z_ = saturation(cmd_vel.linear.z, -10.0, 10.0);
00673 }
00674
00675
00676
00677 bool srvCallback_SetMode(robotnik_msgs::set_mode::Request& request, robotnik_msgs::set_mode::Response& response)
00678 {
00679
00680
00681
00682
00683
00684 ROS_INFO("SummitXLControllerClass::srvCallback_SetMode request.mode= %d", request.mode);
00685 if (request.mode == 1) {
00686 active_kinematic_mode_ = request.mode;
00687 return true;
00688 }
00689 if (request.mode == 2) {
00690 if (kinematic_modes_ == 2) {
00691 active_kinematic_mode_ = request.mode;
00692 return true;
00693 }
00694 else return false;
00695 }
00696 return false;
00697 }
00698
00699
00700 bool srvCallback_GetMode(robotnik_msgs::get_mode::Request& request, robotnik_msgs::get_mode::Response& response)
00701 {
00702 response.mode = active_kinematic_mode_;
00703 return true;
00704 }
00705
00706
00707
00708 bool srvCallback_SetOdometry(robotnik_msgs::set_odometry::Request &request, robotnik_msgs::set_odometry::Response &response )
00709 {
00710 ROS_INFO("summit_xl_odometry::set_odometry: request -> x = %f, y = %f, a = %f", request.x, request.y, request.orientation);
00711 robot_pose_px_ = request.x;
00712 robot_pose_py_ = request.y;
00713 robot_pose_pa_ = request.orientation;
00714
00715 response.ret = true;
00716 return true;
00717 }
00718
00719
00720
00721 void jointStateCallback(const sensor_msgs::JointStateConstPtr& msg)
00722 {
00723 joint_state_ = *msg;
00724 read_state_ = true;
00725 }
00726
00727
00728 void commandCallback(const geometry_msgs::TwistConstPtr& msg)
00729 {
00730
00731 last_command_time_ = ros::Time::now();
00732 subs_command_freq->tick();
00733
00734 base_vel_msg_ = *msg;
00735 this->setCommand(base_vel_msg_);
00736 }
00737
00738
00739 void command_ptzCallback(const robotnik_msgs::ptzConstPtr& msg)
00740 {
00741 pos_ref_pan_ += msg->pan / 180.0 * PI;
00742 pos_ref_tilt_ += msg->tilt / 180.0 * PI;
00743 }
00744
00745
00746 void imuCallback( const sensor_msgs::Imu& imu_msg){
00747
00748 orientation_x_ = imu_msg.orientation.x;
00749 orientation_y_ = imu_msg.orientation.y;
00750 orientation_z_ = imu_msg.orientation.z;
00751 orientation_w_ = imu_msg.orientation.w;
00752
00753 ang_vel_x_ = imu_msg.angular_velocity.x;
00754 ang_vel_y_ = imu_msg.angular_velocity.y;
00755 ang_vel_z_ = imu_msg.angular_velocity.z;
00756
00757 lin_acc_x_ = imu_msg.linear_acceleration.x;
00758 lin_acc_y_ = imu_msg.linear_acceleration.y;
00759 lin_acc_z_ = imu_msg.linear_acceleration.z;
00760 }
00761
00762 double saturation(double u, double min, double max)
00763 {
00764 if (u>max) u=max;
00765 if (u<min) u=min;
00766 return u;
00767 }
00768
00769 double radnorm( double value )
00770 {
00771 while (value > PI) value -= PI;
00772 while (value < -PI) value += PI;
00773 return value;
00774 }
00775
00776 double radnorm2( double value )
00777 {
00778 while (value > 2.0*PI) value -= 2.0*PI;
00779 while (value < -2.0*PI) value += 2.0*PI;
00780 return value;
00781 }
00782
00783 bool spin()
00784 {
00785 ROS_INFO("summit_xl_robot_control::spin()");
00786 ros::Rate r(desired_freq_);
00787
00788 while (!ros::isShuttingDown())
00789 {
00790 if (starting() == 0)
00791 {
00792 while(ros::ok() && node_handle_.ok()) {
00793 UpdateControl();
00794 UpdateOdometry();
00795 PublishOdometry();
00796 diagnostic_.update();
00797 ros::spinOnce();
00798 r.sleep();
00799 }
00800 ROS_INFO("END OF ros::ok() !!!");
00801 } else {
00802
00803
00804 usleep(1000000);
00805 ros::spinOnce();
00806 }
00807 }
00808
00809 ROS_INFO("summit_xl_robot_control::spin() - end");
00810 return true;
00811 }
00812
00813 };
00814
00815 int main(int argc, char** argv)
00816 {
00817 ros::init(argc, argv, "summit_xl_robot_control");
00818
00819 ros::NodeHandle n;
00820 SummitXLControllerClass sxlrc(n);
00821
00822
00823
00824 sxlrc.spin();
00825
00826 return (0);
00827
00828
00829 }
00830