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 #include <algorithm>
00037 #include <boost/thread/mutex.hpp>
00038
00039 #include <ros/ros.h>
00040 #include <actionlib/client/simple_action_client.h>
00041
00042 #include <control_msgs/FollowJointTrajectoryAction.h>
00043 #include <control_msgs/GripperCommandAction.h>
00044 #include <geometry_msgs/TwistStamped.h>
00045 #include <nav_msgs/Odometry.h>
00046 #include <sensor_msgs/JointState.h>
00047 #include <sensor_msgs/Joy.h>
00048 #include <topic_tools/MuxSelect.h>
00049
00050 double integrate(double desired, double present, double max_rate, double dt)
00051 {
00052 if (desired > present)
00053 return std::min(desired, present + max_rate * dt);
00054 else
00055 return std::max(desired, present - max_rate * dt);
00056 }
00057
00058
00059 class TeleopComponent
00060 {
00061 public:
00062 TeleopComponent() : active_(false) {}
00063 virtual ~TeleopComponent() {}
00064
00065
00066
00067 virtual bool update(const sensor_msgs::Joy::ConstPtr& joy,
00068 const sensor_msgs::JointState::ConstPtr& state) = 0;
00069
00070
00071 virtual void publish(const ros::Duration& dt) = 0;
00072
00073
00074 virtual bool start()
00075 {
00076 active_ = true;
00077 return active_;
00078 }
00079
00080
00081 virtual bool stop()
00082 {
00083 active_ = false;
00084 return active_;
00085 }
00086
00087 protected:
00088 bool active_;
00089 };
00090
00091
00092 class BaseTeleop : public TeleopComponent
00093 {
00094 public:
00095 BaseTeleop(const std::string& name, ros::NodeHandle& nh)
00096 {
00097 ros::NodeHandle pnh(nh, name);
00098
00099
00100 pnh.param("button_deadman", deadman_, 10);
00101 pnh.param("axis_x", axis_x_, 3);
00102 pnh.param("axis_w", axis_w_, 0);
00103
00104
00105 pnh.param("max_vel_x", max_vel_x_, 1.0);
00106 pnh.param("min_vel_x", min_vel_x_, -0.5);
00107 pnh.param("max_vel_w", max_vel_w_, 3.0);
00108 pnh.param("max_acc_x", max_acc_x_, 1.0);
00109 pnh.param("max_acc_w", max_acc_w_, 3.0);
00110
00111
00112 pnh.param("max_windup_time", max_windup_time, 0.25);
00113
00114
00115 pnh.param("use_mux", use_mux_, true);
00116 if (use_mux_)
00117 {
00118 mux_ = nh.serviceClient<topic_tools::MuxSelect>("/cmd_vel_mux/select");
00119 }
00120
00121 cmd_vel_pub_ = nh.advertise<geometry_msgs::Twist>("/teleop/cmd_vel", 1);
00122 odom_sub_ = nh.subscribe("/odom", 1, &BaseTeleop::odomCallback, this);
00123 }
00124
00125 virtual bool update(const sensor_msgs::Joy::ConstPtr& joy,
00126 const sensor_msgs::JointState::ConstPtr& state)
00127 {
00128 bool deadman_pressed = joy->buttons[deadman_];
00129
00130 if (!deadman_pressed)
00131 {
00132 stop();
00133 return false;
00134 }
00135
00136 start();
00137
00138 if (joy->axes[axis_x_] > 0.0)
00139 desired_.linear.x = joy->axes[axis_x_] * max_vel_x_;
00140 else
00141 desired_.linear.x = joy->axes[axis_x_] * -min_vel_x_;
00142 desired_.angular.z = joy->axes[axis_w_] * max_vel_w_;
00143
00144
00145 return true;
00146 }
00147
00148 virtual void publish(const ros::Duration& dt)
00149 {
00150 if (active_)
00151 {
00152 {
00153 boost::mutex::scoped_lock lock(odom_mutex_);
00154
00155
00156
00157
00158 if (last_.linear.x >= 0)
00159 last_.linear.x = std::min(last_.linear.x, odom_.twist.twist.linear.x + max_acc_x_ * max_windup_time);
00160 else
00161 last_.linear.x = std::max(last_.linear.x, odom_.twist.twist.linear.x - max_acc_x_ * max_windup_time);
00162 if (last_.angular.z >= 0)
00163 last_.angular.z = std::min(last_.angular.z, odom_.twist.twist.angular.z + max_acc_w_ * max_windup_time);
00164 else
00165 last_.angular.z = std::max(last_.angular.z, odom_.twist.twist.angular.z - max_acc_w_ * max_windup_time);
00166 }
00167
00168 last_.linear.x = integrate(desired_.linear.x, last_.linear.x, max_acc_x_, dt.toSec());
00169 last_.angular.z = integrate(desired_.angular.z, last_.angular.z, max_acc_w_, dt.toSec());
00170 cmd_vel_pub_.publish(last_);
00171 }
00172 }
00173
00174 virtual bool start()
00175 {
00176 if (!active_ && use_mux_)
00177 {
00178
00179 topic_tools::MuxSelect req;
00180 req.request.topic = cmd_vel_pub_.getTopic();
00181 if (mux_.call(req))
00182 {
00183 prev_mux_topic_ = req.response.prev_topic;
00184 }
00185 else
00186 {
00187 ROS_ERROR("Unable to switch mux");
00188 }
00189 }
00190 active_ = true;
00191 return active_;
00192 }
00193
00194 virtual bool stop()
00195 {
00196
00197 last_ = desired_ = geometry_msgs::Twist();
00198 cmd_vel_pub_.publish(last_);
00199
00200 if (active_ && use_mux_)
00201 {
00202 topic_tools::MuxSelect req;
00203 req.request.topic = prev_mux_topic_;
00204 if (!mux_.call(req))
00205 {
00206 ROS_ERROR("Unable to switch mux");
00207 return active_;
00208 }
00209 }
00210 active_ = false;
00211 return active_;
00212 }
00213
00214 private:
00215 void odomCallback(const nav_msgs::OdometryConstPtr& odom)
00216 {
00217
00218 boost::mutex::scoped_lock lock(odom_mutex_);
00219 odom_ = *odom;
00220 }
00221
00222
00223 int deadman_, axis_x_, axis_w_;
00224
00225
00226 double max_vel_x_, min_vel_x_, max_vel_w_;
00227 double max_acc_x_, max_acc_w_;
00228
00229
00230 bool use_mux_;
00231 std::string prev_mux_topic_;
00232 ros::ServiceClient mux_;
00233
00234
00235 ros::Publisher cmd_vel_pub_;
00236 ros::Subscriber odom_sub_;
00237
00238
00239 boost::mutex odom_mutex_;
00240 nav_msgs::Odometry odom_;
00241
00242 double max_windup_time;
00243
00244 geometry_msgs::Twist desired_;
00245 geometry_msgs::Twist last_;
00246 };
00247
00248
00249
00250 class FollowTeleop : public TeleopComponent
00251 {
00252 typedef actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction> client_t;
00253
00254 public:
00255 FollowTeleop(const std::string& name, ros::NodeHandle& nh)
00256 {
00257 ros::NodeHandle pnh(nh, name);
00258
00259
00260 pnh.param("button_deadman", deadman_, 10);
00261 pnh.param("button_increase", inc_button_, 12);
00262 pnh.param("button_decrease", dec_button_, 14);
00263
00264
00265 pnh.param("min_position", min_position_, 0.0);
00266 pnh.param("max_position", max_position_, 0.4);
00267 pnh.param("max_velocity", max_velocity_, 0.075);
00268 pnh.param("max_accel", max_acceleration_, 0.25);
00269
00270
00271 pnh.param("inhibit", inhibit_, false);
00272
00273
00274 pnh.param<std::string>("joint_name", joint_name_, "torso_lift_joint");
00275 std::string action_name;
00276 pnh.param<std::string>("action_name", action_name, "torso_controller/follow_joint_trajectory");
00277
00278 client_.reset(new client_t(action_name, true));
00279 if (!client_->waitForServer(ros::Duration(2.0)))
00280 {
00281 ROS_ERROR("%s may not be connected.", action_name.c_str());
00282 }
00283 }
00284
00285
00286 virtual bool update(const sensor_msgs::Joy::ConstPtr& joy,
00287 const sensor_msgs::JointState::ConstPtr& state)
00288 {
00289 bool deadman_pressed = joy->buttons[deadman_];
00290
00291 if (!deadman_pressed)
00292 {
00293 stop();
00294
00295 for (size_t i = 0; i < state->name.size(); i++)
00296 {
00297 if (state->name[i] == joint_name_)
00298 {
00299 actual_position_ = state->position[i];
00300 break;
00301 }
00302 }
00303 return false;
00304 }
00305
00306 if (joy->buttons[inc_button_])
00307 {
00308 desired_velocity_ = max_velocity_;
00309 start();
00310 }
00311 else if (joy->buttons[dec_button_])
00312 {
00313 desired_velocity_ = -max_velocity_;
00314 start();
00315 }
00316 else
00317 {
00318 desired_velocity_ = 0.0;
00319 }
00320
00321 return inhibit_;
00322 }
00323
00324
00325 virtual void publish(const ros::Duration& dt)
00326 {
00327 if (active_)
00328 {
00329
00330 double step = 0.25;
00331 double vel = integrate(desired_velocity_, last_velocity_, max_acceleration_, step);
00332 double travel = step * (vel + last_velocity_) / 2.0;
00333 double pos = std::max(min_position_, std::min(max_position_, actual_position_ + travel));
00334
00335 control_msgs::FollowJointTrajectoryGoal goal;
00336 goal.trajectory.joint_names.push_back(joint_name_);
00337 trajectory_msgs::JointTrajectoryPoint p;
00338 p.positions.push_back(pos);
00339 p.velocities.push_back(vel);
00340 p.time_from_start = ros::Duration(step);
00341 goal.trajectory.points.push_back(p);
00342 goal.goal_time_tolerance = ros::Duration(0.0);
00343 client_->sendGoal(goal);
00344
00345 vel = integrate(desired_velocity_, last_velocity_, max_acceleration_, dt.toSec());
00346 travel = dt.toSec() * (vel + last_velocity_) / 2.0;
00347 actual_position_ = std::max(min_position_, std::min(max_position_, actual_position_ + travel));
00348 last_velocity_ = vel;
00349 }
00350 }
00351
00352 virtual bool stop()
00353 {
00354 active_ = false;
00355 last_velocity_ = 0.0;
00356 return active_;
00357 }
00358
00359 private:
00360 int deadman_, inc_button_, dec_button_;
00361 double min_position_, max_position_, max_velocity_, max_acceleration_;
00362 bool inhibit_;
00363 std::string joint_name_;
00364 double actual_position_;
00365 double desired_velocity_, last_velocity_;
00366 boost::shared_ptr<client_t> client_;
00367 };
00368
00369
00370 class GripperTeleop : public TeleopComponent
00371 {
00372 typedef actionlib::SimpleActionClient<control_msgs::GripperCommandAction> client_t;
00373
00374 public:
00375 GripperTeleop(const std::string& name, ros::NodeHandle& nh) :
00376 req_close_(false),
00377 req_open_(false)
00378 {
00379 ros::NodeHandle pnh(nh, name);
00380
00381
00382 pnh.param("button_deadman", deadman_, 10);
00383 pnh.param("button_open", open_button_, 0);
00384 pnh.param("button_close", close_button_, 3);
00385
00386
00387 pnh.param("closed_position", min_position_, 0.0);
00388 pnh.param("open_position", max_position_, 0.115);
00389 pnh.param("max_effort", max_effort_, 100.0);
00390
00391 std::string action_name = "gripper_controller/gripper_action";
00392 client_.reset(new client_t(action_name, true));
00393 if (!client_->waitForServer(ros::Duration(2.0)))
00394 {
00395 ROS_ERROR("%s may not be connected.", action_name.c_str());
00396 }
00397 }
00398
00399
00400
00401 virtual bool update(const sensor_msgs::Joy::ConstPtr& joy,
00402 const sensor_msgs::JointState::ConstPtr& state)
00403 {
00404 bool deadman_pressed = joy->buttons[deadman_];
00405
00406 if (deadman_pressed)
00407 {
00408 if (joy->buttons[open_button_])
00409 req_open_ = true;
00410 else if (joy->buttons[close_button_])
00411 req_close_ = true;
00412 }
00413
00414 return false;
00415 }
00416
00417
00418 virtual void publish(const ros::Duration& dt)
00419 {
00420 if (req_open_)
00421 {
00422 control_msgs::GripperCommandGoal goal;
00423 goal.command.position = max_position_;
00424 goal.command.max_effort = max_effort_;
00425 client_->sendGoal(goal);
00426 req_open_ = false;
00427 }
00428 else if (req_close_)
00429 {
00430 control_msgs::GripperCommandGoal goal;
00431 goal.command.position = min_position_;
00432 goal.command.max_effort = max_effort_;
00433 client_->sendGoal(goal);
00434 req_close_ = false;
00435 }
00436 }
00437
00438 private:
00439 int deadman_, open_button_, close_button_;
00440 double min_position_, max_position_, max_effort_;
00441 bool req_close_, req_open_;
00442 boost::shared_ptr<client_t> client_;
00443 };
00444
00445
00446
00447 class HeadTeleop : public TeleopComponent
00448 {
00449 typedef actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction> client_t;
00450
00451 public:
00452 HeadTeleop(const std::string& name, ros::NodeHandle& nh) :
00453 last_pan_(0.0),
00454 last_tilt_(0.0)
00455 {
00456 ros::NodeHandle pnh(nh, name);
00457
00458
00459 pnh.param("button_deadman", deadman_, 8);
00460 pnh.param("axis_pan", axis_pan_, 0);
00461 pnh.param("axis_tilt", axis_tilt_, 3);
00462
00463
00464 pnh.param("max_vel_pan", max_vel_pan_, 1.5);
00465 pnh.param("max_vel_tilt", max_vel_tilt_, 1.5);
00466 pnh.param("max_acc_pan", max_acc_pan_, 3.0);
00467 pnh.param("max_acc_tilt", max_acc_tilt_, 3.0);
00468 pnh.param("min_pos_pan", min_pos_pan_, -1.57);
00469 pnh.param("max_pos_pan", max_pos_pan_, 1.57);
00470 pnh.param("min_pos_tilt", min_pos_tilt_, -0.76);
00471 pnh.param("max_pos_tilt", max_pos_tilt_, 1.45);
00472
00473
00474 head_pan_joint_ = "head_pan_joint";
00475 head_tilt_joint_ = "head_tilt_joint";
00476
00477 std::string action_name = "head_controller/follow_joint_trajectory";
00478 client_.reset(new client_t(action_name, true));
00479 if (!client_->waitForServer(ros::Duration(2.0)))
00480 {
00481 ROS_ERROR("%s may not be connected.", action_name.c_str());
00482 }
00483 }
00484
00485
00486 virtual bool update(const sensor_msgs::Joy::ConstPtr& joy,
00487 const sensor_msgs::JointState::ConstPtr& state)
00488 {
00489 bool deadman_pressed = joy->buttons[deadman_];
00490
00491 if (!deadman_pressed)
00492 {
00493 stop();
00494
00495 for (size_t i = 0; i < state->name.size(); i++)
00496 {
00497 if (state->name[i] == head_pan_joint_)
00498 actual_pos_pan_ = state->position[i];
00499 if (state->name[i] == head_tilt_joint_)
00500 actual_pos_tilt_ = state->position[i];
00501 }
00502 return false;
00503 }
00504
00505 desired_pan_ = joy->axes[axis_pan_] * max_vel_pan_;
00506 desired_tilt_ = joy->axes[axis_tilt_] * max_vel_tilt_;
00507 start();
00508
00509 return true;
00510 }
00511
00512
00513 virtual void publish(const ros::Duration& dt)
00514 {
00515 if (active_)
00516 {
00517
00518 double step = 0.125;
00519 double pan_vel = integrate(desired_pan_, last_pan_, max_acc_pan_, step);
00520 double pan_travel = step * (pan_vel + last_pan_) / 2.0;
00521 double pan = std::max(min_pos_pan_, std::min(max_pos_pan_, actual_pos_pan_ + pan_travel));
00522 double tilt_vel = integrate(desired_tilt_, last_tilt_, max_acc_tilt_, step);
00523 double tilt_travel = step * (tilt_vel + last_tilt_) / 2.0;
00524 double tilt = std::max(min_pos_tilt_, std::min(max_pos_tilt_, actual_pos_tilt_ + tilt_travel));
00525
00526 control_msgs::FollowJointTrajectoryGoal goal;
00527 goal.trajectory.joint_names.push_back(head_pan_joint_);
00528 goal.trajectory.joint_names.push_back(head_tilt_joint_);
00529 trajectory_msgs::JointTrajectoryPoint p;
00530 p.positions.push_back(pan);
00531 p.positions.push_back(tilt);
00532 p.velocities.push_back(pan_vel);
00533 p.velocities.push_back(tilt_vel);
00534 p.time_from_start = ros::Duration(step);
00535 goal.trajectory.points.push_back(p);
00536 goal.goal_time_tolerance = ros::Duration(0.0);
00537 client_->sendGoal(goal);
00538
00539 pan_vel = integrate(desired_pan_, last_pan_, max_acc_pan_, dt.toSec());
00540 pan_travel = dt.toSec() * (pan_vel + last_pan_) / 2.0;
00541 actual_pos_pan_ = std::max(min_pos_pan_, std::min(max_pos_pan_, actual_pos_pan_ + pan_travel));
00542 last_pan_ = pan_vel;
00543 tilt_vel = integrate(desired_tilt_, last_tilt_, max_acc_tilt_, dt.toSec());
00544 tilt_travel = dt.toSec() * (tilt_vel + last_tilt_) / 2.0;
00545 actual_pos_tilt_ = std::max(min_pos_tilt_, std::min(max_pos_tilt_, actual_pos_tilt_ + tilt_travel));
00546 last_tilt_ = tilt_vel;
00547 }
00548 }
00549
00550 virtual bool stop()
00551 {
00552 active_ = false;
00553 last_pan_ = last_tilt_ = 0.0;
00554 return active_;
00555 }
00556
00557 private:
00558 int deadman_, axis_pan_, axis_tilt_;
00559 double max_vel_pan_, max_vel_tilt_;
00560 double max_acc_pan_, max_acc_tilt_;
00561 double min_pos_pan_, max_pos_pan_, min_pos_tilt_, max_pos_tilt_;
00562 std::string head_pan_joint_, head_tilt_joint_;
00563 double actual_pos_pan_, actual_pos_tilt_;
00564 double desired_pan_, desired_tilt_;
00565 double last_pan_, last_tilt_;
00566 boost::shared_ptr<client_t> client_;
00567 };
00568
00569 class ArmTeleop : public TeleopComponent
00570 {
00571 public:
00572 ArmTeleop(const std::string& name, ros::NodeHandle& nh)
00573 {
00574 ros::NodeHandle pnh(nh, name);
00575
00576 pnh.param("axis_x", axis_x_, 3);
00577 pnh.param("axis_y", axis_y_, 2);
00578 pnh.param("axis_z", axis_z_, 1);
00579 pnh.param("axis_roll", axis_roll_, 2);
00580 pnh.param("axis_pitch", axis_pitch_, 3);
00581 pnh.param("axis_yaw", axis_yaw_, 0);
00582
00583 pnh.param("button_arm_linear", button_linear_, 9);
00584 pnh.param("button_arm_angular", button_angular_, 11);
00585
00586
00587 pnh.param("max_vel_x", max_vel_x_, 1.0);
00588 pnh.param("max_vel_y", max_vel_y_, 1.0);
00589 pnh.param("max_vel_z", max_vel_z_, 1.0);
00590 pnh.param("max_acc_x", max_acc_x_, 10.0);
00591 pnh.param("max_acc_y", max_acc_y_, 10.0);
00592 pnh.param("max_acc_z", max_acc_z_, 10.0);
00593
00594 pnh.param("max_vel_roll", max_vel_roll_, 2.0);
00595 pnh.param("max_vel_pitch", max_vel_pitch_, 2.0);
00596 pnh.param("max_vel_yaw", max_vel_yaw_, 2.0);
00597 pnh.param("max_acc_roll", max_acc_roll_, 10.0);
00598 pnh.param("max_acc_pitch", max_acc_pitch_, 10.0);
00599 pnh.param("max_acc_yaw", max_acc_yaw_, 10.0);
00600
00601 cmd_pub_ = nh.advertise<geometry_msgs::TwistStamped>("/arm_controller/cartesian_twist/command", 10);
00602 }
00603
00604 virtual bool update(const sensor_msgs::Joy::ConstPtr& joy,
00605 const sensor_msgs::JointState::ConstPtr& state)
00606 {
00607 bool button_linear_pressed = joy->buttons[button_linear_];
00608 bool button_angular_pressed = joy->buttons[button_angular_];
00609
00610 if (!(button_linear_pressed || button_angular_pressed) &&
00611 (ros::Time::now() - last_update_ > ros::Duration(0.5)))
00612 {
00613 stop();
00614 return false;
00615 }
00616
00617 start();
00618
00619 if (button_linear_pressed)
00620 {
00621 desired_.twist.linear.x = joy->axes[axis_x_] * max_vel_x_;
00622 desired_.twist.linear.y = joy->axes[axis_y_] * max_vel_y_;
00623 desired_.twist.linear.z = joy->axes[axis_z_] * max_vel_z_;
00624 desired_.twist.angular.x = 0.0;
00625 desired_.twist.angular.y = 0.0;
00626 desired_.twist.angular.z = 0.0;
00627 last_update_ = ros::Time::now();
00628 }
00629 else if (button_angular_pressed)
00630 {
00631 desired_.twist.linear.x = 0.0;
00632 desired_.twist.linear.y = 0.0;
00633 desired_.twist.linear.z = 0.0;
00634 desired_.twist.angular.x = joy->axes[axis_roll_] * max_vel_roll_;
00635 desired_.twist.angular.y = joy->axes[axis_pitch_] * max_vel_pitch_;
00636 desired_.twist.angular.z = joy->axes[axis_yaw_] * max_vel_yaw_;
00637 last_update_ = ros::Time::now();
00638 }
00639 else
00640 {
00641 desired_.twist.linear.x = 0.0;
00642 desired_.twist.linear.y = 0.0;
00643 desired_.twist.linear.z = 0.0;
00644 desired_.twist.angular.x = 0.0;
00645 desired_.twist.angular.y = 0.0;
00646 desired_.twist.angular.z = 0.0;
00647 }
00648
00649 return true;
00650 }
00651
00652 virtual void publish(const ros::Duration& dt)
00653 {
00654 if (active_)
00655 {
00656
00657 last_.twist.linear.x = integrate(desired_.twist.linear.x, last_.twist.linear.x, max_acc_x_, dt.toSec());
00658 last_.twist.linear.y = integrate(desired_.twist.linear.y, last_.twist.linear.y, max_acc_y_, dt.toSec());
00659 last_.twist.linear.z = integrate(desired_.twist.linear.z, last_.twist.linear.z, max_acc_z_, dt.toSec());
00660
00661 last_.twist.angular.x = integrate(desired_.twist.angular.x, last_.twist.angular.x, max_acc_roll_, dt.toSec());
00662 last_.twist.angular.y = integrate(desired_.twist.angular.y, last_.twist.angular.y, max_acc_pitch_, dt.toSec());
00663 last_.twist.angular.z = integrate(desired_.twist.angular.z, last_.twist.angular.z, max_acc_yaw_, dt.toSec());
00664
00665 last_.header.frame_id = "base_link";
00666
00667 cmd_pub_.publish(last_);
00668 }
00669 }
00670
00671 virtual bool start()
00672 {
00673 active_ = true;
00674 return active_;
00675 }
00676
00677
00678 virtual bool stop()
00679 {
00680
00681 if (active_)
00682 {
00683 last_ = desired_ = geometry_msgs::TwistStamped();
00684 cmd_pub_.publish(last_);
00685 }
00686
00687 active_ = false;
00688 return active_;
00689 }
00690
00691 private:
00692
00693
00694 int axis_x_, axis_y_, axis_z_, axis_roll_, axis_pitch_, axis_yaw_;
00695 int button_linear_, button_angular_;
00696
00697
00698 double max_vel_x_, max_vel_y_, max_vel_z_;
00699 double max_vel_roll_, max_vel_pitch_, max_vel_yaw_;
00700 double max_acc_x_, max_acc_y_, max_acc_z_;
00701 double max_acc_roll_, max_acc_pitch_, max_acc_yaw_;
00702
00703
00704 ros::Publisher cmd_pub_;
00705
00706 geometry_msgs::TwistStamped desired_;
00707 geometry_msgs::TwistStamped last_;
00708 ros::Time last_update_;
00709 };
00710
00711
00712 class Teleop
00713 {
00714 typedef boost::shared_ptr<TeleopComponent> TeleopComponentPtr;
00715
00716 public:
00717 void init(ros::NodeHandle& nh)
00718 {
00719 bool is_fetch;
00720 nh.param("is_fetch", is_fetch, true);
00721
00722
00723
00724 TeleopComponentPtr c;
00725 if (is_fetch)
00726 {
00727
00728 c.reset(new FollowTeleop("torso", nh));
00729 components_.push_back(c);
00730
00731
00732 c.reset(new GripperTeleop("gripper", nh));
00733 components_.push_back(c);
00734
00735
00736 c.reset(new HeadTeleop("head", nh));
00737 components_.push_back(c);
00738
00739 c.reset(new ArmTeleop("arm", nh));
00740 components_.push_back(c);
00741 }
00742
00743
00744 c.reset(new BaseTeleop("base", nh));
00745 components_.push_back(c);
00746
00747 state_msg_.reset(new sensor_msgs::JointState());
00748 joy_sub_ = nh.subscribe("/joy", 1, &Teleop::joyCallback, this);
00749 state_sub_ = nh.subscribe("/joint_states", 10, &Teleop::stateCallback, this);
00750 }
00751
00752 void publish(const ros::Duration& dt)
00753 {
00754 if (ros::Time::now() - last_update_ > ros::Duration(0.25))
00755 {
00756
00757 for (size_t c = 0; c < components_.size(); c++)
00758 {
00759 components_[c]->stop();
00760 }
00761 }
00762 else
00763 {
00764 for (size_t c = 0; c < components_.size(); c++)
00765 {
00766 components_[c]->publish(dt);
00767 }
00768 }
00769 }
00770
00771 private:
00772 void joyCallback(const sensor_msgs::Joy::ConstPtr& msg)
00773 {
00774
00775 boost::mutex::scoped_lock lock(state_mutex_);
00776
00777 bool ok = true;
00778 for (size_t c = 0; c < components_.size(); c++)
00779 {
00780 if (ok)
00781 {
00782 ok &= !components_[c]->update(msg, state_msg_);
00783 }
00784 else
00785 {
00786
00787 components_[c]->stop();
00788 }
00789 }
00790 last_update_ = ros::Time::now();
00791 }
00792
00793 void stateCallback(const sensor_msgs::JointStateConstPtr& msg)
00794 {
00795
00796 boost::mutex::scoped_lock lock(state_mutex_);
00797
00798
00799 for (size_t msg_j = 0; msg_j < msg->name.size(); msg_j++)
00800 {
00801 size_t state_j;
00802 for (state_j = 0; state_j < state_msg_->name.size(); state_j++)
00803 {
00804 if (state_msg_->name[state_j] == msg->name[msg_j])
00805 {
00806 state_msg_->position[state_j] = msg->position[msg_j];
00807 state_msg_->velocity[state_j] = msg->velocity[msg_j];
00808 break;
00809 }
00810 }
00811 if (state_j == state_msg_->name.size())
00812 {
00813
00814 state_msg_->name.push_back(msg->name[msg_j]);
00815 state_msg_->position.push_back(msg->position[msg_j]);
00816 state_msg_->velocity.push_back(msg->velocity[msg_j]);
00817 }
00818 }
00819 }
00820
00821 std::vector<TeleopComponentPtr> components_;
00822 ros::Time last_update_;
00823 boost::mutex state_mutex_;
00824 sensor_msgs::JointStatePtr state_msg_;
00825 ros::Subscriber joy_sub_, state_sub_;
00826 };
00827
00828 int main(int argc, char** argv)
00829 {
00830 ros::init(argc, argv, "teleop");
00831 ros::NodeHandle n("~");
00832
00833 Teleop teleop;
00834 teleop.init(n);
00835
00836 ros::Rate r(30.0);
00837 while (ros::ok())
00838 {
00839 ros::spinOnce();
00840 teleop.publish(ros::Duration(1/30.0));
00841 r.sleep();
00842 }
00843
00844 return 0;
00845 }