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