SchunkServer.h
Go to the documentation of this file.
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         void init(RobotArm* arm, std::map<std::string, unsigned int>& joints_name_to_number_map) {
00053 
00054                 arm_ = arm;
00055                 joints_name_to_number_map_ = joints_name_to_number_map;
00056 
00057                 state_publisher_ = nh_.advertise<control_msgs::JointTrajectoryControllerState>("trajectory_state", 5);
00058 
00059                 std::map<std::string, unsigned int>::iterator it;
00060                 for (it = joints_name_to_number_map_.begin(); it != joints_name_to_number_map_.end(); ++it) {
00061                         state_msg_.joint_names.push_back(it->first);
00062                 }
00063                 int num_of_joints = joints_name_to_number_map_.size();
00064                 state_msg_.desired.positions.resize(num_of_joints);
00065                 state_msg_.desired.velocities.resize(num_of_joints);
00066                 state_msg_.desired.accelerations.resize(num_of_joints);
00067                 state_msg_.actual.positions.resize(num_of_joints);
00068                 state_msg_.actual.velocities.resize(num_of_joints);
00069                 state_msg_.error.positions.resize(num_of_joints);
00070                 state_msg_.error.velocities.resize(num_of_joints);
00071 
00072 
00073                 nh_.param<std::string>("follow_joint_trajectory_action_name", action_name_, "follow_joint_trajectory");
00074                 as_ = new ActionServerType(nh_, action_name_,
00075                                 boost::bind(&TrajectoryExecuter::trajectoryActionCallback, this, _1), false);
00076                 as_->start();
00077         }
00078         ~TrajectoryExecuter() {
00079 
00080                 delete as_;
00081         }
00082 
00083         void main() {
00084                 while (true) {
00085                         {
00086                                 boost::unique_lock<boost::mutex> lock(mut_);
00087                                 waiting_ = true;
00088                                 bool gotit = false;
00089                                 while (!run_){
00090                                         if(!nh_.ok()) {
00091                                                 return;
00092                                         }
00093                                         try {
00094                                                 boost::this_thread::interruption_point();
00095                                                 gotit = cond_.timed_wait(lock, boost::posix_time::milliseconds(100));
00096                                         }
00097                                         catch(const boost::thread_interrupted&) {
00098                                                 ROS_INFO("Trajectory thread was interrupted and returns, stopping the arm.");
00099                                                 arm_->normalStopAll();
00100                                                 return;
00101                                         }
00102                                         if (! gotit) {
00103                                                 //Let's make people happy by publishing a state message
00104                                                 for (unsigned int joint_i = 0; joint_i<joints_name_to_number_map_.size(); ++joint_i) {
00105                                                         //fill in the message
00106                                                         state_msg_.desired = state_msg_.actual;
00107                                                         state_msg_.actual.positions[joint_i] = arm_->getPosition(joint_i);
00108                                                         state_msg_.actual.velocities[joint_i] = 0;
00109                                                         state_msg_.actual.time_from_start = ros::Duration(0);
00110                                                 }
00111 
00112                                                 //finally publish the state message
00113                                                 state_msg_.header.stamp = ros::Time::now();
00114                                                 state_publisher_.publish(state_msg_);
00115                                         }
00116 
00117                                 }
00118                         }
00119                         //I hope the mutex is unlocked now
00120                         {
00121                                 boost::unique_lock<boost::mutex> lock(mut_);
00122                                 waiting_ = false;
00123                         }
00124 
00125                         ROS_INFO("Trajectory thread is starting its job");
00126                         followTrajectory();
00127                         arm_->normalStopAll();
00128 
00129                         {
00130                                 //Self deactivate
00131                                 boost::unique_lock<boost::mutex> lock(mut_);
00132                                 run_ = false;
00133                         }
00134                         ROS_INFO("Trajectory thread has finished its job");
00135                 }
00136         }
00137 
00138         void start(const trajectory_msgs::JointTrajectory& newtraj) {
00139                 {
00140                         boost::unique_lock<boost::mutex> lock(mut_);
00141                         if (run_) {
00142                                 ROS_WARN("You need to stop a trajectory before issuing a new command. Ignoring the new command");
00143                                 return;
00144                         }
00145 
00146                         traj_ = newtraj;
00147                         run_ = true;
00148                 }
00149                 ROS_INFO("Waking up the thread");
00150                 cond_.notify_one();
00151         }
00152 
00153         void stop() {
00154                 boost::unique_lock<boost::mutex> lock(mut_);
00155                 run_ = false;
00156         }
00157 
00158         bool isRunning() {
00159                 boost::unique_lock<boost::mutex> lock(mut_);
00160                 return run_;
00161         }
00162 
00163         bool isWaiting() {
00164                 boost::unique_lock<boost::mutex> lock(mut_);
00165                 return waiting_;
00166         }
00167 
00168 
00169         void trajectoryActionCallback(const control_msgs::FollowJointTrajectoryGoalConstPtr& goal)
00170         {
00171                 bool success = true;
00172                 ros::Time trajStartTime = ros::Time::now();
00173                 const trajectory_msgs::JointTrajectory& traj = goal->trajectory;
00174 
00175                 // init feedback message
00176                 feedback_.joint_names = traj.joint_names;
00177                 int num_of_joints = traj.joint_names.size();
00178                 feedback_.desired.positions.resize(num_of_joints);
00179                 feedback_.desired.velocities.resize(num_of_joints);
00180                 feedback_.desired.accelerations.resize(num_of_joints);
00181                 feedback_.actual.positions.resize(num_of_joints);
00182                 feedback_.actual.velocities.resize(num_of_joints);
00183                 feedback_.actual.accelerations.resize(num_of_joints);
00184                 feedback_.error.positions.resize(num_of_joints);
00185                 feedback_.error.velocities.resize(num_of_joints);
00186                 feedback_.error.accelerations.resize(num_of_joints);
00187 
00188                 // for each trajectory step...
00189                 unsigned int steps = traj.points.size();
00190                 for (unsigned int step_i = 0; step_i < steps; ++step_i) {
00191 
00192                         // check that preempt has not been requested by the client
00193                         if (as_->isPreemptRequested() || !ros::ok()) {
00194                                 ROS_INFO("%s: Preempted", action_name_.c_str());
00195                                 // set the action state to preempted
00196                                 as_->setPreempted();
00197                                 success = false;
00198                                 arm_->normalStopAll();
00199                                 break;
00200                         }
00201 
00202 
00203                         // get the step target
00204                         const trajectory_msgs::JointTrajectoryPoint& trajStep = traj.points[step_i];
00205                         feedback_.desired = trajStep;
00206 
00207                         ROS_INFO_STREAM("Trajectory thread executing step "<<step_i<<"+1/"<<steps<<" until "<<trajStep.time_from_start<<" s / "<<(trajStartTime+trajStep.time_from_start));
00208 
00209                         // for each joint in step...
00210                         for (unsigned int joint_i = 0; joint_i < traj.joint_names.size(); ++joint_i) {
00211 
00212                                 int id = joints_name_to_number_map_[traj.joint_names[joint_i]];
00213 
00214                                 float acceleration = trajStep.accelerations[joint_i];
00215                                 float velocity = trajStep.velocities[joint_i];
00216                                 float position = trajStep.positions[joint_i];
00217 
00218 //                              ROS_INFO_STREAM("Moving module "<<id<<" with "<</*setiosflags(ios::fixed)<<*/ velocity<<" rad/s and "<<acceleration<<" rad/s*s to "<<position<<" rad");
00219 
00220 
00222 #define SIGN_TOLERANT_MAX(value, def)   ( (value)==0 ? 0 : \
00223                                                                                         ( \
00224                                                                                                 (value)>0 ? \
00225                                                                                                         std::max((value),  (def)) : \
00226                                                                                                         std::min((value), -(def)) \
00227                                                                                         ) \
00228                                                                                 )
00229 
00230 #define SIGN_TOLERANT_CUT(value, lim)   ( (value)==0 ? 0 : \
00231                                                                                         ( \
00232                                                                                                 (value)>0 ? \
00233                                                                                                         ( (value) >  (lim) ? (value) : (0) ) : \
00234                                                                                                         ( (value) < -(lim) ? (value) : (0) ) \
00235                                                                                         ) \
00236                                                                                 )
00237 
00238 //                              velocity = SIGN_TOLERANT_CUT(velocity, TOO_SLOW);
00239 //                              velocity = SIGN_TOLERANT_MAX(velocity, SLOWEST_REASONABLE_JOINT_SPEED);
00240 //                              acceleration = SIGN_TOLERANT_MAX(acceleration, 0.43f);
00241                                 acceleration = 0.21;
00242 
00243                                 if(step_i == steps-1) {
00244                                         velocity = SLOWEST_REASONABLE_JOINT_SPEED;
00245                                 }
00246 
00247 //                              if(std::abs(velocity) < TOO_SLOW) {
00248 //                                      ROS_INFO_STREAM("Skipping module "<<id<<" due to too low velocity");
00249 //                              }
00250 //                              else {
00251                                 ROS_INFO_STREAM("Moving module "<<id<<" with "<</*setiosflags(ios::fixed)<<*/ velocity<<" rad/s and "<<acceleration<<" rad/s*s to "<<position<<" rad");
00252 
00253 #if SCHUNK_NOT_AMTEC != 0
00254                                 // TODO schunk option of trajectory action callback
00255 //                              arm_->moveVelocity(id, velocity);
00256 #else
00257                                 arm_->setAcceleration(id, acceleration);
00258                                 arm_->setVelocity(id, velocity);
00259                                 arm_->movePosition(id, position);
00260 //                              arm_->moveVelocity(id, velocity);       TODO choose this if the velocity and time are calculated precisely
00261 
00262 //                              if(step_i == steps-1) {
00263 //                                      ROS_INFO("LAST STEP, moving to position instead of with velocity.");
00264 //                                      arm_->movePosition(id, position);
00265 //                              }
00266 //                              else {
00268 //                                      arm_->moveVelocity(id, velocity);
00269 //                              }
00270 #endif
00271 //                              }
00272 
00273                                 // fill the joint individual feedback part
00274                                 feedback_.actual.positions[id] = arm_->getPosition(id);
00275                                 feedback_.actual.velocities[id] = arm_->getVelocity(id);        // Note: not supported in SchunkProtocol
00276 //                              feedback_.actual.accelerations[id] = arm_->manipulator_.getModules().at(id).status_acc / max_acceleration?; TODO cannot know acceleration status
00277                         }
00278 
00279                         // publish the feedback
00280                         feedback_.header.stamp = ros::Time::now();
00281                         feedback_.actual.time_from_start = ros::Time::now() - trajStartTime;
00282                         as_->publishFeedback(feedback_);
00283 
00284                         // sleep until step time has passed
00285                         ros::Time::sleepUntil(trajStartTime + trajStep.time_from_start);
00286                 }//for each trajectory step...
00287 
00288                 if(success) {
00289                         ROS_INFO("Trajectory done, waiting for joints to stop...");
00290                         bool all_joints_stopped;
00291                         do {
00292                                 ros::WallDuration(0.06).sleep();
00293                                 all_joints_stopped = true;
00294                                 for (unsigned int joint_i = 0; joint_i < traj.joint_names.size(); ++joint_i) {
00295                                         uint8_t moving, brake, foo;
00296                                         float foofl;
00297                                         arm_->getModuleStatus(joint_i, foo, moving, foo, foo, foo, brake, foo, foo, foo, foofl);
00298 //                                      if(moving) {
00299                                         if(!brake) {
00300                                                 all_joints_stopped = false;
00301                                                 break;
00302                                         }
00303 //                                      if(arm_->manipulator_.getModules().at(joint_i).status_vel == 0)
00304 //                                              all_joints_stopped = false;
00305                                 }
00306                         } while (!all_joints_stopped);
00307 
00308                         result_.error_code = control_msgs::FollowJointTrajectoryResult::SUCCESSFUL;
00309                         ROS_INFO("%s: Succeeded", action_name_.c_str());
00310                         // set the action state to succeeded
00311                         as_->setSucceeded(result_);
00312                 }
00313         }
00314 
00315 
00316         // from action tutorial
00317 protected:
00318         ros::NodeHandle nh_;
00319         typedef actionlib::SimpleActionServer<control_msgs::FollowJointTrajectoryAction> ActionServerType;
00320         ActionServerType* as_;
00321         std::string action_name_;
00322         // create messages that are used to published feedback/result
00323         control_msgs::FollowJointTrajectoryFeedback feedback_;
00324         control_msgs::FollowJointTrajectoryResult result_;
00325 
00326 
00327 private:
00328         /* At this time only velocity values are followed. */
00329         void followTrajectory() {
00330                 //I am not entirely sure that this code actually looks like real-time
00331                 ros::Time trajStartTime = ros::Time::now();
00332                 for (unsigned int step = 0; step < traj_.points.size(); ++step) {
00333                         trajectory_msgs::JointTrajectoryPoint& point = traj_.points[step];
00334 
00335                         ROS_INFO_STREAM("Trajectory thread executing step "<<step);
00336                         //now apply speed to each joint
00337                         for (unsigned int joint_i = 0; joint_i < traj_.joint_names.size(); ++joint_i) {
00338 
00339                                 unsigned int id = joints_name_to_number_map_[traj_.joint_names[joint_i]];
00340                                 float velocity = point.velocities[joint_i];
00341 
00342                                 ROS_INFO_STREAM("Moving module "<<id<<" with "<<velocity<<" rad/s = "<<RAD_TO_DEG(velocity)<<" deg/s");
00343                                 arm_->moveVelocity(id, velocity);
00344 
00345                                 //fill in the message
00346                                 state_msg_.desired = state_msg_.actual;
00347                                 state_msg_.actual.positions[joint_i] = arm_->getPosition(joint_i);
00348                                 state_msg_.actual.velocities[joint_i] = arm_->getVelocity(joint_i);     // Note: not supported on SchunkProtocol
00349                                 state_msg_.actual.time_from_start = point.time_from_start;
00350                         }
00351 
00352                         //finally publish the state message
00353                         state_msg_.header.stamp = ros::Time::now();
00354                         state_publisher_.publish(state_msg_);
00355 
00356 
00357                         //wait for the right time and check if it has to die
00358                         while (ros::Time::now() < trajStartTime + point.time_from_start) {
00359                                 ; // <- Now things are really dirty
00360                                 { //This is tricky... a block as the only body of a loop!
00361                                         boost::unique_lock<boost::mutex> lock(mut_);
00362                                         if (!run_) {
00363                                                 ROS_INFO("Trajectory thread has been commanded to stop");
00364                                                 return;
00365                                         }
00366                                 }
00367                         }
00368                 }
00369         }
00370 
00371         RobotArm* arm_;
00372         std::map<std::string, unsigned int> joints_name_to_number_map_;
00373         trajectory_msgs::JointTrajectory traj_;
00374         bool run_;
00375         bool waiting_;
00376         boost::condition_variable cond_;
00377         boost::mutex mut_;
00378         control_msgs::JointTrajectoryControllerState state_msg_;
00379         ros::Publisher state_publisher_;
00380 };
00381 
00382 
00383 
00384 class SchunkServer : private boost::noncopyable {
00385 public:
00386         SchunkServer(ros::NodeHandle &nh) :
00387                 node_handle_(nh),
00388                 arm_(NULL),
00389                 trajectory_executer_(nh)
00390         {
00391                 init();
00392         }
00393 
00394         ~SchunkServer() {
00395                 trajectory_executer_.stop();
00396                 trajectory_executer_thread_.interrupt();
00397                 trajectory_executer_thread_.join();
00398                 if(arm_ != NULL)
00399                         delete arm_;
00400         }
00401 
00402 private:
00403         void renewRobotArm() {
00404                 // delete old instance if existent
00405                 if(arm_ != NULL)
00406                         delete arm_;
00407 
00408                 std::string robot_arm_class;
00409                 ros::NodeHandle nh_private("~");
00410                 if(!nh_private.getParam("robot_arm_class", robot_arm_class)) {
00411                         ROS_WARN_STREAM("Parameter robot arm class not set, defaulting to AmtecProtocolArm.");
00412                         robot_arm_class = "AmtecProtocolArm";
00413                 }
00414 
00415                 // TODO implement real class loader
00416                 if(robot_arm_class == "AmtecProtocolArm")
00417                         arm_ = new AmtecProtocolArm();
00418                 else if(robot_arm_class == "SchunkProtocolArm")
00419                         arm_ = new SchunkProtocolArm();
00420                 else if(robot_arm_class == "LWA3ArmUASHH")
00421                         arm_ = new LWA3ArmUASHH();
00422                 else if(robot_arm_class == "PowerCubeArmUUISRC")
00423                         arm_ = new PowerCubeArmUUISRC();
00424                 else {
00425                         ROS_FATAL_STREAM("Cannot load unknown robot arm class: "<<robot_arm_class);
00426                         exit(1);
00427                 }
00428         }
00429 
00430         void init() {
00431                 // Initialise the arm model parser and find out what non-fixed joints are present
00432                 arm_model_.initParam("robot_description");
00433                 std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator mapElement;
00434                 for (mapElement = arm_model_.joints_.begin(); mapElement != arm_model_.joints_.end(); ++mapElement) {
00435                         boost::shared_ptr<urdf::Joint> joint = mapElement->second;
00436                         ROS_DEBUG_STREAM("Joint: Name="<<joint->name<<" MimicPtr="<<joint->mimic);
00437                         if (joint->type != urdf::Joint::FIXED &&
00438                                         joint->mimic == 0)      // ignore virtual joints mimicking a physical one
00439                                 joints_list_.push_back(joint);
00440                 }
00441                 ROS_INFO("URDF specifies %d non-fixed non-mimicking joints.", joints_list_.size());
00442 
00443                 // Initialise the arm
00444                 renewRobotArm();
00445                 arm_->init();
00446 
00447                 // Check if reinitialisation is needed
00448                 while(arm_->getModulesCount() != joints_list_.size()) {
00449                         ROS_WARN("Reinitialising robot arm... found %d joints but need %d", arm_->getModulesCount(), joints_list_.size());
00450                         renewRobotArm();
00451                         ros::WallDuration(1).sleep(); // let arm start up
00452                         arm_->init();
00453                 }
00454 
00455                 // Check that the required modules are present.
00456                 ROS_WARN("Didn't check that the modules in the description match modules in reality.");
00457 
00458                 // Set up the joint state publisher with the joint names
00459                 // This assumes that the joints are ordered on the robot in the same order as the URDF!!!
00460                 current_JointState_.name.resize(joints_list_.size());
00461                 current_JointState_.position.resize(joints_list_.size());
00462                 current_JointState_.velocity.resize(joints_list_.size());
00463                 for (unsigned int i = 0; i < joints_list_.size(); ++i) {
00464                         current_JointState_.name[i] = joints_list_[i]->name;
00465                         joints_name_to_number_map_[joints_list_[i]->name] = i;
00466                         ROS_INFO("%d is mapping to %s", i, joints_list_[i]->name.c_str());
00467                 }
00468                 current_JointState_publisher_ = node_handle_.advertise<sensor_msgs::JointState>("/joint_states", 1);
00469 
00470                 // Set up the schunk status publisher
00471                 current_SchunkStatus_publisher_ = node_handle_.advertise<metralabs_msgs::SchunkStatus>("status", 1);
00472                 for (uint i = 0; i < joints_list_.size(); ++i) {
00473                         metralabs_msgs::SchunkJointStatus status;
00474                         status.jointName = joints_list_[i]->name;
00475                         current_SchunkStatus_.joints.push_back(status);
00476                 }
00477 
00478                 trajectory_executer_.init(arm_, joints_name_to_number_map_);
00479 
00480                 ROS_INFO("Starting the trajectory executer thread");
00481                 trajectory_executer_thread_ = boost::thread(boost::bind(&TrajectoryExecuter::main, &trajectory_executer_));
00482 
00483 
00484                 /*
00485                  * /schunk/position/joint_state -> publishes joint state for kinematics modules
00486                  * /schunk/target_pc/joint_state <- for received position control commands
00487                  * /schunk/target_vc/joint_state  <- for receiving velocity control commands
00488                  * /schunk/status -> to publish all the statuses
00489                  */
00490 
00491                 ROS_INFO("Subscribing schunk topics...");
00492 
00493                 // those topics which must be received multiple times (for each joint) got a 10 for their message buffer
00494                 emergency_subscriber_ = node_handle_.subscribe("emergency", 1, &SchunkServer::cb_emergency, this);
00495                 stop_subscriber_ = node_handle_.subscribe("stop", 1, &SchunkServer::cb_stop, this);
00496                 ack_subscriber_ = node_handle_.subscribe("ack", 10, &SchunkServer::cb_ack, this);
00497                 ack_all_subscriber_ = node_handle_.subscribe("ack_all", 1, &SchunkServer::cb_ackAll, this);
00498                 ref_subscriber_ = node_handle_.subscribe("ref", 10, &SchunkServer::cb_ref, this);
00499                 ref_all_subscriber_ = node_handle_.subscribe("ref_all", 1, &SchunkServer::cb_refAll, this);
00500 
00501                 set_velocity_subscriber_ = node_handle_.subscribe("set_velocity", 10, &SchunkServer::cb_setVelocity, this);
00502                 set_acceleration_subscriber_ = node_handle_.subscribe("set_acceleration", 10, &SchunkServer::cb_setAcceleration, this);
00503                 set_current_subscriber_ = node_handle_.subscribe("set_current", 10, &SchunkServer::cb_setCurrent, this);
00504                 set_currents_max_all_subscriber_ = node_handle_.subscribe("set_current_max_all", 1, &SchunkServer::cb_setCurrentsMaxAll, this);
00505 
00506                 move_position_subscriber_ = node_handle_.subscribe("move_position", 10, &SchunkServer::cb_movePosition, this);
00507                 move_velocity_subscriber_ = node_handle_.subscribe("move_velocity", 10, &SchunkServer::cb_moveVelocity, this);
00508                 move_all_position_subscriber_ = node_handle_.subscribe("move_all_position", 1, &SchunkServer::cb_moveAllPosition, this);
00509                 move_all_velocity_subscriber_ = node_handle_.subscribe("move_all_velocity", 1, &SchunkServer::cb_moveAllVelocity, this);
00510                 trajectory_command_subscriber_ = node_handle_.subscribe("trajectory_command", 1, &SchunkServer::cb_commandTrajectory, this);
00511 
00512                 boost::thread(&SchunkServer::publishingLoop, this, ros::Rate(30));
00513 
00514                 ROS_INFO("SchunkServer Ready");
00515 
00516         }
00517 
00518         void cb_emergency(const std_msgs::Empty::ConstPtr& dummy)       {
00519                 ROS_INFO("emergency");
00520                 arm_->emergencyStopAll();
00521         }
00522 
00523         void cb_stop(const std_msgs::Empty::ConstPtr& dummy)    {
00524                 ROS_INFO("stop");
00525                 arm_->normalStopAll();
00526         }
00527 
00528         void cb_ack(const std_msgs::Int8::ConstPtr& id)         {
00529                 ROS_INFO("cb_ack: [%d]", id->data);
00530                 arm_->ackJoint(id->data);
00531         }
00532 
00533         void cb_ackAll(const std_msgs::Empty::ConstPtr& dummy)  {
00534                 ROS_INFO("cb_ackAll");
00535                 arm_->ackAll();
00536         }
00537 
00538         void cb_ref(const std_msgs::Int8::ConstPtr& id) {
00539                 ROS_INFO("cb_ref: [%d]", id->data);
00540                 arm_->refJoint(id->data);
00541         }
00542 
00543         void cb_refAll(const std_msgs::Empty::ConstPtr& dummy)  {
00544                 ROS_INFO("cb_refAll");
00545                 arm_->refAll();
00546         }
00547 
00548 
00549         void cb_setVelocity(const metralabs_msgs::IDAndFloat::ConstPtr& data)   {
00550                 ROS_INFO("cb_setVelocity: [%d, %f]", data->id, data->value);
00551                 arm_->setVelocity(data->id, data->value);
00552         }
00553 
00554         void cb_setAcceleration(const metralabs_msgs::IDAndFloat::ConstPtr& data)       {
00555                 ROS_INFO("cb_setAcceleration: [%d, %f]", data->id, data->value);
00556                 arm_->setAcceleration(data->id, data->value);
00557         }
00558 
00559         void cb_setCurrent(const metralabs_msgs::IDAndFloat::ConstPtr& data)    {
00560                 ROS_INFO("cb_setCurrent: [%d, %f]", data->id, data->value);
00561                 arm_->setCurrent(data->id, data->value);
00562         }
00563 
00564         void cb_setCurrentsMaxAll(const std_msgs::Empty::ConstPtr& dummy)       {
00565                 ROS_INFO("cb_setCurrentsMaxAll");
00566                 arm_->setCurrentsToMax();
00567         }
00568 
00569 
00570         void cb_movePosition(const metralabs_msgs::IDAndFloat::ConstPtr& data)  {
00571                 ROS_INFO("cb_movePosition: [%d, %f]", data->id, data->value);
00572                 arm_->movePosition(data->id, data->value);
00573         }
00574 
00575         void cb_moveVelocity(const metralabs_msgs::IDAndFloat::ConstPtr& data)  {
00576                 ROS_INFO("cb_moveVelocity: [%d, %f]", data->id, data->value);
00577                 if (data->value == 0.0)
00578                         arm_->normalStopJoint(data->id);
00579                 else
00580                         arm_->moveVelocity(data->id, data->value);
00581         }
00582 
00583         void cb_moveAllPosition(const sensor_msgs::JointState::ConstPtr& data) {
00584                 // The "names" member says how many joints, the other members may be empty.
00585                 // Not all the joints have to be specified in the message
00586                 // and not all types must be filled
00587                 for (uint i = 0; i < data.get()->name.size(); ++i) {
00588                         string joint_name = data.get()->name[i];
00589                         int joint_number = joints_name_to_number_map_[joint_name];
00590                         ROS_INFO_STREAM("cb_PositionControl: joint "<<joint_name<<" (#"<<joint_number<<")");
00591 
00592                         arm_->setCurrentsToMax();
00593                         if (data.get()->position.size()!=0) {
00594                                 double pos = data.get()->position[i];
00595                                 ROS_INFO_STREAM(" to position "<<pos);
00596                                 arm_->movePosition(joint_number, pos);
00597                         }
00598                         if (data.get()->velocity.size()!=0) {
00599                                 double vel = data.get()->velocity[i];
00600                                 ROS_INFO_STREAM(" with velocity "<<vel);
00601                                 arm_->setVelocity(joint_number, vel);
00602                         }
00603                         if (data.get()->effort.size()!=0) {
00604                                 double eff = data.get()->effort[i];
00605                                 ROS_INFO_STREAM(" with effort "<<eff);
00606                                 arm_->setCurrent(joint_number, eff);
00607                         }
00608                 }
00609         }
00610 
00611         void cb_moveAllVelocity(const sensor_msgs::JointState::ConstPtr& data) {
00612                 // The "names" member says how many joints, the other members may be empty.
00613                 // Not all the joints have to be specified in the message
00614                 // and not all types must be filled
00615                 for (uint i = 0; i < data.get()->name.size(); ++i) {
00616                         string joint_name = data.get()->name[i];
00617                         int joint_number = joints_name_to_number_map_[joint_name];
00618                         ROS_INFO_STREAM("cb_VelocityControl: joint "<<joint_name<<" (#"<<joint_number<<")");
00619 
00620 //                      m_powerCube.setCurrentsToMax();
00621 
00622                         if (data.get()->velocity.size() != 0) {
00623                                 double vel = data.get()->velocity[i];
00624                                 ROS_INFO_STREAM(" with velocity "<<vel);
00625                                 if (vel == 0.0)
00626                                         arm_->normalStopJoint(joint_number);
00627                                 else
00628                                         arm_->moveVelocity(joint_number, vel);
00629                         }
00630                         if (data.get()->effort.size()!=0) {
00631                                 double eff = data.get()->effort[i];
00632                                 ROS_INFO_STREAM(" with effort "<<eff);
00633                                 arm_->setCurrent(joint_number, eff);
00634                         }
00635                 }
00636         }
00637 
00638         void cb_commandTrajectory(const trajectory_msgs::JointTrajectory traj) {
00639                 ROS_INFO("Schunk Server: received a new trajectory");
00640                 trajectory_executer_.stop();
00641                 while (! trajectory_executer_.isWaiting() ) {
00642                         ROS_INFO("Waiting for the controller to be ready..");
00643                 }
00644                 trajectory_executer_.start(traj);
00645         }
00646 
00647 private:
00648         void publishingLoop(ros::Rate loop_rate) {
00649                 while (node_handle_.ok()) {
00650                         publishCurrentJointState();
00651                         publishCurrentSchunkStatus();
00652                         // This will adjust as needed per iteration
00653                         loop_rate.sleep();
00654                 }
00655         }
00656 
00657         void publishCurrentJointState() {
00658                 current_JointState_.header.stamp = ros::Time::now();
00659                 for (unsigned int i = 0; i < current_JointState_.name.size(); ++i) {
00660                         current_JointState_.position[i] = arm_->getPosition(i);
00661                         current_JointState_.velocity[i] = arm_->getVelocity(i);
00662                 }
00663                 current_JointState_publisher_.publish(current_JointState_);
00664         }
00665 
00666         void publishCurrentSchunkStatus() {
00667                 std::vector<metralabs_msgs::SchunkJointStatus>::iterator it;
00668                 uint module_number;
00669                 for (it = current_SchunkStatus_.joints.begin(); it != current_SchunkStatus_.joints.end(); ++it) {
00670                         module_number = joints_name_to_number_map_[it->jointName];
00671                         arm_->getModuleStatus(module_number, it->referenced, it->moving, it->progMode, it->warning,
00672                                         it->error, it->brake, it->moveEnd, it->posReached, it->errorCode, it->current);
00673                 }
00674                 current_SchunkStatus_publisher_.publish(current_SchunkStatus_);
00675         }
00676 
00677 
00678 private:
00679         ros::NodeHandle node_handle_;
00680         RobotArm* arm_;
00681         urdf::Model arm_model_; // A parsing of the model description
00682         std::vector<boost::shared_ptr<urdf::Joint> > joints_list_;
00683         std::map<std::string, unsigned int> joints_name_to_number_map_;
00684 
00685         sensor_msgs::JointState current_JointState_;
00686         metralabs_msgs::SchunkStatus current_SchunkStatus_;
00687         ros::Publisher current_JointState_publisher_;
00688         ros::Publisher current_SchunkStatus_publisher_;
00689 
00690         TrajectoryExecuter trajectory_executer_;
00691         boost::thread trajectory_executer_thread_;
00692 
00693         ros::Subscriber emergency_subscriber_;
00694         ros::Subscriber stop_subscriber_;
00695         ros::Subscriber first_ref_subscriber_;
00696         ros::Subscriber ack_subscriber_;
00697         ros::Subscriber ack_all_subscriber_;
00698         ros::Subscriber ref_subscriber_;
00699         ros::Subscriber ref_all_subscriber_;
00700 
00701         ros::Subscriber set_velocity_subscriber_;
00702         ros::Subscriber set_acceleration_subscriber_;
00703         ros::Subscriber set_current_subscriber_;
00704         ros::Subscriber set_currents_max_all_subscriber_;
00705 
00706         ros::Subscriber move_position_subscriber_;
00707         ros::Subscriber move_velocity_subscriber_;
00708         ros::Subscriber move_all_position_subscriber_;
00709         ros::Subscriber move_all_velocity_subscriber_;
00710         ros::Subscriber trajectory_command_subscriber_;
00711 };
00712 
00713 
00714 #endif /* SCHUNKSERVER_H_ */


metralabs_ros
Author(s): Yianni Gatsoulis and Chris Burbridge and Lorenzo Riano and Felix Kolbe
autogenerated on Tue Jan 7 2014 11:38:56