00001 #ifndef SCHUNKSERVER_H_
00002 #define SCHUNKSERVER_H_
00003
00004 #include <boost/thread.hpp>
00005 #include <boost/noncopyable.hpp>
00006
00007 #include <ros/ros.h>
00008 #include <actionlib/server/simple_action_server.h>
00009
00010 #include <urdf/model.h>
00011 #include <tf/transform_broadcaster.h>
00012
00013 #include <std_msgs/Int8.h>
00014
00015 #include <metralabs_msgs/IDAndFloat.h>
00016 #include <metralabs_msgs/SchunkStatus.h>
00017
00018 #include <sensor_msgs/JointState.h>
00019
00020 #include <trajectory_msgs/JointTrajectory.h>
00021 #include <control_msgs/JointTrajectoryControllerState.h>
00022 #include <control_msgs/FollowJointTrajectoryAction.h>
00023
00024 #include "RobotArm.h"
00025 #include "AmtecProtocolArm.h"
00026 #include "SchunkProtocolArm.h"
00027 #include "LWA3ArmUASHH.h"
00028 #include "PowerCubeArmUUISRC.h"
00029
00030 using namespace std;
00031
00032
00033 #define DEG_TO_RAD(d) ((d)*M_PI/180.0)
00034 #define RAD_TO_DEG(r) ((r)*180.0/M_PI)
00035
00036 #define SLOWEST_REASONABLE_JOINT_SPEED 0.015f // the slowest reasonable speed for our joints (IMHO)
00037 #define TOO_SLOW 0.002f //
00038
00039
00040
00041 class TrajectoryExecuter : private boost::noncopyable {
00042 public:
00043 TrajectoryExecuter(ros::NodeHandle& nh) :
00044 nh_(nh),
00045 as_(NULL),
00046 arm_(NULL)
00047 {
00048 run_ = false;
00049 waiting_ = false;
00050
00051
00052 ROS_ASSERT(isnanf(0 / (float)0));
00053 ROS_ASSERT(isnanf(-0 / (float)0));
00054 }
00055
00056 void init(RobotArm* arm, std::map<std::string, RobotArm::IDType>& joints_name_to_number_map) {
00057
00058 arm_ = arm;
00059 joints_name_to_number_map_ = joints_name_to_number_map;
00060
00061 state_publisher_ = nh_.advertise<control_msgs::JointTrajectoryControllerState>("trajectory_state", 5);
00062
00063 std::map<std::string, RobotArm::IDType>::iterator it;
00064 for (it = joints_name_to_number_map_.begin(); it != joints_name_to_number_map_.end(); ++it) {
00065 state_msg_.joint_names.push_back(it->first);
00066 }
00067 int num_of_joints = joints_name_to_number_map_.size();
00068 state_msg_.desired.positions.resize(num_of_joints);
00069 state_msg_.desired.velocities.resize(num_of_joints);
00070 state_msg_.desired.accelerations.resize(num_of_joints);
00071 state_msg_.actual.positions.resize(num_of_joints);
00072 state_msg_.actual.velocities.resize(num_of_joints);
00073 state_msg_.error.positions.resize(num_of_joints);
00074 state_msg_.error.velocities.resize(num_of_joints);
00075
00076
00077 nh_.param<std::string>("follow_joint_trajectory_action_name", action_name_, "follow_joint_trajectory");
00078 as_ = new ActionServerType(nh_, action_name_,
00079 boost::bind(&TrajectoryExecuter::trajectoryActionCallback, this, _1), false);
00080 as_->start();
00081 }
00082
00083 ~TrajectoryExecuter() {
00084 delete as_;
00085 }
00086
00087 void main() {
00088 while (true) {
00089 {
00090 boost::unique_lock<boost::mutex> lock(mut_);
00091 waiting_ = true;
00092 bool gotit = false;
00093 while (!run_){
00094 if(!nh_.ok()) {
00095 return;
00096 }
00097 try {
00098 boost::this_thread::interruption_point();
00099 gotit = cond_.timed_wait(lock, boost::posix_time::milliseconds(100));
00100 }
00101 catch(const boost::thread_interrupted&) {
00102 ROS_INFO("Trajectory thread was interrupted and returns, stopping the arm.");
00103 arm_->normalStopAll();
00104 return;
00105 }
00106 if (! gotit) {
00107
00108 for (unsigned int joint_i = 0; joint_i<joints_name_to_number_map_.size(); ++joint_i) {
00109
00110 state_msg_.desired = state_msg_.actual;
00111 state_msg_.actual.positions[joint_i] = arm_->getPosition(joint_i);
00112 state_msg_.actual.velocities[joint_i] = 0;
00113 state_msg_.actual.time_from_start = ros::Duration(0);
00114 }
00115
00116
00117 state_msg_.header.stamp = ros::Time::now();
00118 state_publisher_.publish(state_msg_);
00119 }
00120
00121 }
00122 }
00123
00124 {
00125 boost::unique_lock<boost::mutex> lock(mut_);
00126 waiting_ = false;
00127 }
00128
00129 ROS_INFO("Trajectory thread is starting its job");
00130 followTrajectory();
00131 arm_->normalStopAll();
00132
00133 {
00134
00135 boost::unique_lock<boost::mutex> lock(mut_);
00136 run_ = false;
00137 }
00138 ROS_INFO("Trajectory thread has finished its job");
00139 }
00140 }
00141
00142 void start(const trajectory_msgs::JointTrajectory& newtraj) {
00143 {
00144 boost::unique_lock<boost::mutex> lock(mut_);
00145 if (run_) {
00146 ROS_WARN("You need to stop a trajectory before issuing a new command. Ignoring the new command");
00147 return;
00148 }
00149
00150 traj_ = newtraj;
00151 run_ = true;
00152 }
00153 ROS_INFO("Waking up the thread");
00154 cond_.notify_one();
00155 }
00156
00157 void stop() {
00158 boost::unique_lock<boost::mutex> lock(mut_);
00159 run_ = false;
00160 }
00161
00162 bool isRunning() {
00163 boost::unique_lock<boost::mutex> lock(mut_);
00164 return run_;
00165 }
00166
00167 bool isWaiting() {
00168 boost::unique_lock<boost::mutex> lock(mut_);
00169 return waiting_;
00170 }
00171
00172
00173
00174 void trajectoryActionCallback(const control_msgs::FollowJointTrajectoryGoalConstPtr& goal)
00175 {
00176 const trajectory_msgs::JointTrajectory& traj = goal->trajectory;
00177 const unsigned int num_of_joints = traj.joint_names.size();
00178
00179
00180
00181
00182 RobotArm::IDType msg_index_to_model_index[num_of_joints];
00183
00184 for (unsigned int joint_i = 0; joint_i < num_of_joints; ++joint_i) {
00185 RobotArm::IDType id = joints_name_to_number_map_[traj.joint_names[joint_i]];
00186 msg_index_to_model_index[joint_i] = id;
00187 ROS_INFO_STREAM("TrajectoryAction callback: mapping joint: msg id "<<joint_i<<" to model id "<<id);
00188 }
00189
00190
00191
00192 for (unsigned int joint_i = 0; joint_i < num_of_joints; ++joint_i) {
00193 RobotArm::IDType id = msg_index_to_model_index[joint_i];
00194
00195
00196 uint8_t moving, error, brake, foo;
00197 float foofl;
00198 arm_->getModuleStatus(id, foo, moving, foo, foo, error, brake, foo, foo, foo, foofl);
00199 if(moving || error) {
00200 arm_->normalStopAll();
00201 ROS_ERROR("Arm in error state or moving, rejecting trajectory action.");
00202 as_->setAborted();
00203 return;
00204 }
00205
00206
00207 float MAX_ALLOWED_DEVIANCE = 0.05;
00208 float first_step_position = traj.points[0].positions[joint_i];
00209 float current_position = arm_->getPosition(id);
00210 float actual_difference = first_step_position-current_position;
00211 if (abs(actual_difference) > MAX_ALLOWED_DEVIANCE) {
00212 arm_->normalStopAll();
00213 ROS_ERROR_STREAM("Arm pose and first trajectory step differ to much, "
00214 << "rejecting trajectory action. Joint ID: " << id <<
00215 " difference: " << actual_difference << " allowed: " << MAX_ALLOWED_DEVIANCE);
00216 as_->setAborted();
00217 return;
00218 }
00219
00220 }
00221 ROS_INFO("Arm in valid state, starting trajectory..");
00222
00223
00224
00225 feedback_.joint_names = traj.joint_names;
00226 feedback_.desired.positions.resize(num_of_joints);
00227 feedback_.desired.velocities.resize(num_of_joints);
00228 feedback_.desired.accelerations.resize(num_of_joints);
00229 feedback_.actual.positions.resize(num_of_joints);
00230 feedback_.actual.velocities.resize(num_of_joints);
00231 feedback_.actual.accelerations.resize(num_of_joints);
00232 feedback_.error.positions.resize(num_of_joints);
00233 feedback_.error.velocities.resize(num_of_joints);
00234 feedback_.error.accelerations.resize(num_of_joints);
00235
00236 const ros::Time traj_start_time = ros::Time::now();
00237
00239
00240 unsigned int steps = traj.points.size();
00241 for (unsigned int step_i = 0; step_i < steps; ++step_i) {
00242
00243
00244 if (as_->isPreemptRequested() || !ros::ok()) {
00245 arm_->normalStopAll();
00246 ROS_INFO("%s: Preempted", action_name_.c_str());
00247 as_->setPreempted();
00248 return;
00249 }
00250
00251
00252 for (unsigned int joint_i = 0; joint_i < num_of_joints; ++joint_i) {
00253 RobotArm::IDType id = msg_index_to_model_index[joint_i];
00254 uint8_t error, foo;
00255 float foofl;
00256 arm_->getModuleStatus(id, foo, foo, foo, foo, error, foo, foo, foo, foo, foofl);
00257 if(error) {
00258 arm_->normalStopAll();
00259 ROS_ERROR("Arm in error state, aborting trajectory action.");
00260 as_->setAborted();
00261 return;
00262 }
00263 }
00264
00265
00266 const trajectory_msgs::JointTrajectoryPoint& traj_step = traj.points[step_i];
00267 feedback_.desired = traj_step;
00268
00269 ROS_INFO_STREAM("Trajectory thread executing step "<<step_i<<"+1/"<<steps<<" until "<<traj_step.time_from_start<<" s");
00270
00272
00273 for (unsigned int joint_i = 0; joint_i < num_of_joints; ++joint_i) {
00274
00275 RobotArm::IDType id = msg_index_to_model_index[joint_i];
00276 float acceleration = traj_step.accelerations[joint_i];
00277 float velocity = traj_step.velocities[joint_i];
00278 float position = traj_step.positions[joint_i];
00279
00280
00281
00282 if (isnanf(acceleration) || isnanf(velocity) || isnanf(position)) {
00283 arm_->normalStopAll();
00284 ROS_ERROR("Received NAN in trajectory step! Aborting trajectory action.");
00285 ROS_ERROR_STREAM(traj);
00286 as_->setAborted();
00287 return;
00288 }
00289
00290 if(step_i == steps-1) {
00291
00292 velocity = 0.05;
00293 arm_->setVelocity(id, velocity);
00294 arm_->movePosition(id, position);
00295 }
00296 else if(abs(velocity) < TOO_SLOW) {
00297
00298
00299 ROS_INFO_STREAM("Velocity for module "<<id<<" to close to zero to move with velocity, therefore moving to position with fix velocity.");
00300 velocity = 0.05;
00301 arm_->setVelocity(id, velocity);
00302 arm_->movePosition(id, position);
00303 }
00304 else {
00305 arm_->moveVelocity(id, velocity);
00306 }
00307 }
00308
00309
00310 for (unsigned int joint_i = 0; joint_i < num_of_joints; ++joint_i) {
00311
00312 RobotArm::IDType id = msg_index_to_model_index[joint_i];
00313 feedback_.actual.positions[joint_i] = arm_->getPosition(id);
00314 feedback_.actual.velocities[joint_i] = arm_->getVelocity(id);
00315 }
00316
00317
00318 feedback_.header.stamp = ros::Time::now();
00319 feedback_.actual.time_from_start = feedback_.header.stamp - traj_start_time;
00320 as_->publishFeedback(feedback_);
00321
00322
00323 ros::Time step_end_time = traj_start_time + traj_step.time_from_start;
00324 if(step_end_time <= ros::Time::now())
00325 ROS_WARN("Trajectory follower to slow, has to sleep a negative duration!");
00326 else
00327 ros::Time::sleepUntil(step_end_time);
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 }
00365
00366
00367 ROS_INFO("Trajectory done, waiting for joints to stop...");
00368 bool all_joints_stopped;
00369 do {
00370 ros::WallDuration(0.06).sleep();
00371 all_joints_stopped = true;
00372 for (unsigned int joint_i = 0; joint_i < num_of_joints; ++joint_i) {
00373 RobotArm::IDType id = msg_index_to_model_index[joint_i];
00374 uint8_t moving, brake, foo;
00375 float foofl;
00376 arm_->getModuleStatus(id, foo, moving, foo, foo, foo, brake, foo, foo, foo, foofl);
00377 if(moving) {
00378 all_joints_stopped = false;
00379 break;
00380 }
00381 }
00382 } while (!all_joints_stopped);
00383
00384 result_.error_code = control_msgs::FollowJointTrajectoryResult::SUCCESSFUL;
00385 ROS_INFO("%s: Succeeded", action_name_.c_str());
00386
00387 as_->setSucceeded(result_);
00388 }
00389
00390
00391
00392 protected:
00393 ros::NodeHandle nh_;
00394 typedef actionlib::SimpleActionServer<control_msgs::FollowJointTrajectoryAction> ActionServerType;
00395 ActionServerType* as_;
00396 std::string action_name_;
00397
00398 control_msgs::FollowJointTrajectoryFeedback feedback_;
00399 control_msgs::FollowJointTrajectoryResult result_;
00400
00401
00402 private:
00403
00404 void followTrajectory() {
00405
00406 ros::Time trajStartTime = ros::Time::now();
00407 for (unsigned int step = 0; step < traj_.points.size(); ++step) {
00408 trajectory_msgs::JointTrajectoryPoint& point = traj_.points[step];
00409
00410 ROS_INFO_STREAM("Trajectory thread executing step "<<step);
00411
00412 for (unsigned int joint_i = 0; joint_i < traj_.joint_names.size(); ++joint_i) {
00413
00414 RobotArm::IDType id = joints_name_to_number_map_[traj_.joint_names[joint_i]];
00415 float velocity = point.velocities[joint_i];
00416
00417 ROS_INFO_STREAM("Moving module "<<id<<" with "<<velocity<<" rad/s = "<<RAD_TO_DEG(velocity)<<" deg/s");
00418 arm_->moveVelocity(id, velocity);
00419
00420
00421 state_msg_.desired = state_msg_.actual;
00422 state_msg_.actual.positions[joint_i] = arm_->getPosition(joint_i);
00423 state_msg_.actual.velocities[joint_i] = arm_->getVelocity(joint_i);
00424 state_msg_.actual.time_from_start = point.time_from_start;
00425 }
00426
00427
00428 state_msg_.header.stamp = ros::Time::now();
00429 state_publisher_.publish(state_msg_);
00430
00431
00432
00433 while (ros::Time::now() < trajStartTime + point.time_from_start) {
00434 ;
00435 {
00436 boost::unique_lock<boost::mutex> lock(mut_);
00437 if (!run_) {
00438 ROS_INFO("Trajectory thread has been commanded to stop");
00439 return;
00440 }
00441 }
00442 }
00443 }
00444 }
00445
00446 RobotArm* arm_;
00447 std::map<std::string, RobotArm::IDType> joints_name_to_number_map_;
00448 trajectory_msgs::JointTrajectory traj_;
00449 bool run_;
00450 bool waiting_;
00451 boost::condition_variable cond_;
00452 boost::mutex mut_;
00453 control_msgs::JointTrajectoryControllerState state_msg_;
00454 ros::Publisher state_publisher_;
00455 };
00456
00457
00458
00459 class SchunkServer : private boost::noncopyable {
00460 public:
00461 SchunkServer(ros::NodeHandle &nh) :
00462 node_handle_(nh),
00463 arm_(NULL),
00464 trajectory_executer_(nh)
00465 {
00466 init();
00467 }
00468
00469 ~SchunkServer() {
00470 trajectory_executer_.stop();
00471 trajectory_executer_thread_.interrupt();
00472 trajectory_executer_thread_.join();
00473 if(arm_ != NULL)
00474 delete arm_;
00475 }
00476
00477 private:
00478 void renewRobotArm() {
00479
00480 if(arm_ != NULL)
00481 delete arm_;
00482
00483 std::string robot_arm_class;
00484 ros::NodeHandle nh_private("~");
00485 if(!nh_private.getParam("robot_arm_class", robot_arm_class)) {
00486 ROS_WARN_STREAM("Parameter robot arm class not set, defaulting to AmtecProtocolArm.");
00487 robot_arm_class = "AmtecProtocolArm";
00488 }
00489
00490
00491 if(robot_arm_class == "AmtecProtocolArm")
00492 arm_ = new AmtecProtocolArm();
00493 else if(robot_arm_class == "SchunkProtocolArm")
00494 arm_ = new SchunkProtocolArm();
00495 else if(robot_arm_class == "LWA3ArmUASHH")
00496 arm_ = new LWA3ArmUASHH();
00497 else if(robot_arm_class == "PowerCubeArmUUISRC")
00498 arm_ = new PowerCubeArmUUISRC();
00499 else {
00500 ROS_FATAL_STREAM("Cannot load unknown robot arm class: "<<robot_arm_class);
00501 exit(1);
00502 }
00503 }
00504
00505 void init() {
00506
00507 arm_model_.initParam("robot_description");
00508 std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator mapElement;
00509 for (mapElement = arm_model_.joints_.begin(); mapElement != arm_model_.joints_.end(); ++mapElement) {
00510 boost::shared_ptr<urdf::Joint> joint = mapElement->second;
00511 ROS_DEBUG_STREAM("Joint: Name="<<joint->name<<" MimicPtr="<<joint->mimic);
00512 if (joint->type != urdf::Joint::FIXED &&
00513 joint->mimic == 0)
00514 joints_list_.push_back(joint);
00515 }
00516 ROS_INFO("URDF specifies %d non-fixed non-mimicking joints.", joints_list_.size());
00517
00518
00519 renewRobotArm();
00520 arm_->init();
00521
00522
00523 while(arm_->getModulesCount() != joints_list_.size()) {
00524 ROS_WARN("Reinitialising robot arm... found %d joints but need %d", arm_->getModulesCount(), joints_list_.size());
00525 renewRobotArm();
00526 ros::WallDuration(1).sleep();
00527 arm_->init();
00528 }
00529
00530
00531 ROS_WARN("Didn't check that the modules in the description match modules in reality.");
00532
00533
00534
00535 current_JointState_.name.resize(joints_list_.size());
00536 current_JointState_.position.resize(joints_list_.size());
00537 current_JointState_.velocity.resize(joints_list_.size());
00538 for (unsigned int i = 0; i < joints_list_.size(); ++i) {
00539 current_JointState_.name[i] = joints_list_[i]->name;
00540 joints_name_to_number_map_[joints_list_[i]->name] = i;
00541 ROS_INFO("%d is mapping to %s", i, joints_list_[i]->name.c_str());
00542 }
00543 current_JointState_publisher_ = node_handle_.advertise<sensor_msgs::JointState>("/joint_states", 1);
00544
00545
00546 current_SchunkStatus_publisher_ = node_handle_.advertise<metralabs_msgs::SchunkStatus>("status", 1);
00547 for (uint i = 0; i < joints_list_.size(); ++i) {
00548 metralabs_msgs::SchunkJointStatus status;
00549 status.jointName = joints_list_[i]->name;
00550 current_SchunkStatus_.joints.push_back(status);
00551 }
00552
00553 trajectory_executer_.init(arm_, joints_name_to_number_map_);
00554
00555 ROS_INFO("Starting the trajectory executer thread");
00556 trajectory_executer_thread_ = boost::thread(boost::bind(&TrajectoryExecuter::main, &trajectory_executer_));
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 ROS_INFO("Subscribing schunk topics...");
00567
00568
00569 emergency_subscriber_ = node_handle_.subscribe("emergency", 1, &SchunkServer::cb_emergency, this);
00570 stop_subscriber_ = node_handle_.subscribe("stop", 1, &SchunkServer::cb_stop, this);
00571 ack_subscriber_ = node_handle_.subscribe("ack", 10, &SchunkServer::cb_ack, this);
00572 ack_all_subscriber_ = node_handle_.subscribe("ack_all", 1, &SchunkServer::cb_ackAll, this);
00573 ref_subscriber_ = node_handle_.subscribe("ref", 10, &SchunkServer::cb_ref, this);
00574 ref_all_subscriber_ = node_handle_.subscribe("ref_all", 1, &SchunkServer::cb_refAll, this);
00575
00576 set_velocity_subscriber_ = node_handle_.subscribe("set_velocity", 10, &SchunkServer::cb_setVelocity, this);
00577 set_acceleration_subscriber_ = node_handle_.subscribe("set_acceleration", 10, &SchunkServer::cb_setAcceleration, this);
00578 set_current_subscriber_ = node_handle_.subscribe("set_current", 10, &SchunkServer::cb_setCurrent, this);
00579 set_currents_max_all_subscriber_ = node_handle_.subscribe("set_current_max_all", 1, &SchunkServer::cb_setCurrentsMaxAll, this);
00580
00581 move_position_subscriber_ = node_handle_.subscribe("move_position", 10, &SchunkServer::cb_movePosition, this);
00582 move_velocity_subscriber_ = node_handle_.subscribe("move_velocity", 10, &SchunkServer::cb_moveVelocity, this);
00583 move_all_position_subscriber_ = node_handle_.subscribe("move_all_position", 1, &SchunkServer::cb_moveAllPosition, this);
00584 move_all_velocity_subscriber_ = node_handle_.subscribe("move_all_velocity", 1, &SchunkServer::cb_moveAllVelocity, this);
00585 trajectory_command_subscriber_ = node_handle_.subscribe("trajectory_command", 1, &SchunkServer::cb_commandTrajectory, this);
00586
00587 boost::thread(&SchunkServer::publishingLoop, this, ros::Rate(30));
00588
00589 ROS_INFO("SchunkServer Ready");
00590
00591 }
00592
00593 void cb_emergency(const std_msgs::Empty::ConstPtr& dummy) {
00594 ROS_INFO("emergency");
00595 arm_->emergencyStopAll();
00596 }
00597
00598 void cb_stop(const std_msgs::Empty::ConstPtr& dummy) {
00599 ROS_INFO("stop");
00600 arm_->normalStopAll();
00601 }
00602
00603 void cb_ack(const std_msgs::Int8::ConstPtr& id) {
00604 ROS_INFO("cb_ack: [%d]", id->data);
00605 arm_->ackJoint(id->data);
00606 }
00607
00608 void cb_ackAll(const std_msgs::Empty::ConstPtr& dummy) {
00609 ROS_INFO("cb_ackAll");
00610 arm_->ackAll();
00611 }
00612
00613 void cb_ref(const std_msgs::Int8::ConstPtr& id) {
00614 ROS_INFO("cb_ref: [%d]", id->data);
00615 arm_->refJoint(id->data);
00616 }
00617
00618 void cb_refAll(const std_msgs::Empty::ConstPtr& dummy) {
00619 ROS_INFO("cb_refAll");
00620 arm_->refAll();
00621 }
00622
00623
00624 void cb_setVelocity(const metralabs_msgs::IDAndFloat::ConstPtr& data) {
00625 ROS_INFO("cb_setVelocity: [%d, %f]", data->id, data->value);
00626 arm_->setVelocity(data->id, data->value);
00627 }
00628
00629 void cb_setAcceleration(const metralabs_msgs::IDAndFloat::ConstPtr& data) {
00630 ROS_INFO("cb_setAcceleration: [%d, %f]", data->id, data->value);
00631 arm_->setAcceleration(data->id, data->value);
00632 }
00633
00634 void cb_setCurrent(const metralabs_msgs::IDAndFloat::ConstPtr& data) {
00635 ROS_INFO("cb_setCurrent: [%d, %f]", data->id, data->value);
00636 arm_->setCurrent(data->id, data->value);
00637 }
00638
00639 void cb_setCurrentsMaxAll(const std_msgs::Empty::ConstPtr& dummy) {
00640 ROS_INFO("cb_setCurrentsMaxAll");
00641 arm_->setCurrentsToMax();
00642 }
00643
00644
00645 void cb_movePosition(const metralabs_msgs::IDAndFloat::ConstPtr& data) {
00646 ROS_INFO("cb_movePosition: [%d, %f]", data->id, data->value);
00647 arm_->movePosition(data->id, data->value);
00648 }
00649
00650 void cb_moveVelocity(const metralabs_msgs::IDAndFloat::ConstPtr& data) {
00651 ROS_INFO("cb_moveVelocity: [%d, %f]", data->id, data->value);
00652 if (data->value == 0.0)
00653 arm_->normalStopJoint(data->id);
00654 else
00655 arm_->moveVelocity(data->id, data->value);
00656 }
00657
00658 void cb_moveAllPosition(const sensor_msgs::JointState::ConstPtr& data) {
00659
00660
00661
00662 for (uint i = 0; i < data.get()->name.size(); ++i) {
00663 string joint_name = data.get()->name[i];
00664 RobotArm::IDType joint_number = joints_name_to_number_map_[joint_name];
00665 ROS_INFO_STREAM("cb_PositionControl: joint "<<joint_name<<" (#"<<joint_number<<")");
00666
00667 arm_->setCurrentsToMax();
00668 if (data.get()->position.size()!=0) {
00669 double pos = data.get()->position[i];
00670 ROS_INFO_STREAM(" to position "<<pos);
00671 arm_->movePosition(joint_number, pos);
00672 }
00673 if (data.get()->velocity.size()!=0) {
00674 double vel = data.get()->velocity[i];
00675 ROS_INFO_STREAM(" with velocity "<<vel);
00676 arm_->setVelocity(joint_number, vel);
00677 }
00678 if (data.get()->effort.size()!=0) {
00679 double eff = data.get()->effort[i];
00680 ROS_INFO_STREAM(" with effort "<<eff);
00681 arm_->setCurrent(joint_number, eff);
00682 }
00683 }
00684 }
00685
00686 void cb_moveAllVelocity(const sensor_msgs::JointState::ConstPtr& data) {
00687
00688
00689
00690 for (uint i = 0; i < data.get()->name.size(); ++i) {
00691 string joint_name = data.get()->name[i];
00692 RobotArm::IDType joint_number = joints_name_to_number_map_[joint_name];
00693 ROS_INFO_STREAM("cb_VelocityControl: joint "<<joint_name<<" (#"<<joint_number<<")");
00694
00695
00696
00697 if (data.get()->velocity.size() != 0) {
00698 double vel = data.get()->velocity[i];
00699 ROS_INFO_STREAM(" with velocity "<<vel);
00700 if (vel == 0.0)
00701 arm_->normalStopJoint(joint_number);
00702 else
00703 arm_->moveVelocity(joint_number, vel);
00704 }
00705 if (data.get()->effort.size()!=0) {
00706 double eff = data.get()->effort[i];
00707 ROS_INFO_STREAM(" with effort "<<eff);
00708 arm_->setCurrent(joint_number, eff);
00709 }
00710 }
00711 }
00712
00713 void cb_commandTrajectory(const trajectory_msgs::JointTrajectory traj) {
00714 ROS_INFO("Schunk Server: received a new trajectory");
00715 trajectory_executer_.stop();
00716 while (! trajectory_executer_.isWaiting() ) {
00717 ROS_INFO("Waiting for the controller to be ready..");
00718 }
00719 trajectory_executer_.start(traj);
00720 }
00721
00722 private:
00723 void publishingLoop(ros::Rate loop_rate) {
00724
00725 while (node_handle_.ok()) {
00726 publishCurrentJointState();
00727 publishCurrentSchunkStatus();
00728
00729 loop_rate.sleep();
00730 }
00731 }
00732
00733 void publishCurrentJointState() {
00734 current_JointState_.header.stamp = ros::Time::now();
00735 for (unsigned int i = 0; i < current_JointState_.name.size(); ++i) {
00736 current_JointState_.position[i] = arm_->getPosition(i);
00737 current_JointState_.velocity[i] = arm_->getVelocity(i);
00738 }
00739 current_JointState_publisher_.publish(current_JointState_);
00740 }
00741
00742 void publishCurrentSchunkStatus() {
00743 std::vector<metralabs_msgs::SchunkJointStatus>::iterator it;
00744 for (it = current_SchunkStatus_.joints.begin(); it != current_SchunkStatus_.joints.end(); ++it) {
00745 RobotArm::IDType module_number = joints_name_to_number_map_[it->jointName];
00746 arm_->getModuleStatus(module_number, it->referenced, it->moving, it->progMode, it->warning,
00747 it->error, it->brake, it->moveEnd, it->posReached, it->errorCode, it->current);
00748 }
00749 current_SchunkStatus_publisher_.publish(current_SchunkStatus_);
00750 }
00751
00752
00753 private:
00754 ros::NodeHandle node_handle_;
00755 RobotArm* arm_;
00756 urdf::Model arm_model_;
00757 std::vector<boost::shared_ptr<urdf::Joint> > joints_list_;
00758 std::map<std::string, RobotArm::IDType> joints_name_to_number_map_;
00759
00760 sensor_msgs::JointState current_JointState_;
00761 metralabs_msgs::SchunkStatus current_SchunkStatus_;
00762 ros::Publisher current_JointState_publisher_;
00763 ros::Publisher current_SchunkStatus_publisher_;
00764
00765 TrajectoryExecuter trajectory_executer_;
00766 boost::thread trajectory_executer_thread_;
00767
00768 ros::Subscriber emergency_subscriber_;
00769 ros::Subscriber stop_subscriber_;
00770 ros::Subscriber first_ref_subscriber_;
00771 ros::Subscriber ack_subscriber_;
00772 ros::Subscriber ack_all_subscriber_;
00773 ros::Subscriber ref_subscriber_;
00774 ros::Subscriber ref_all_subscriber_;
00775
00776 ros::Subscriber set_velocity_subscriber_;
00777 ros::Subscriber set_acceleration_subscriber_;
00778 ros::Subscriber set_current_subscriber_;
00779 ros::Subscriber set_currents_max_all_subscriber_;
00780
00781 ros::Subscriber move_position_subscriber_;
00782 ros::Subscriber move_velocity_subscriber_;
00783 ros::Subscriber move_all_position_subscriber_;
00784 ros::Subscriber move_all_velocity_subscriber_;
00785 ros::Subscriber trajectory_command_subscriber_;
00786 };
00787
00788
00789 #endif