00001
00002
00003
00004
00005 #ifndef ROBOTICAN_CONTROLLERS_GRIPPER_ACTION_CONTROLLER_IMPL_H
00006 #define ROBOTICAN_CONTROLLERS_GRIPPER_ACTION_CONTROLLER_IMPL_H
00007
00008
00009
00010 namespace gripper_action_controller
00011 {
00012 namespace internal
00013 {
00014 std::string getLeafNamespace(const ros::NodeHandle& nh)
00015 {
00016 const std::string complete_ns = nh.getNamespace();
00017 std::size_t id = complete_ns.find_last_of("/");
00018 return complete_ns.substr(id + 1);
00019 }
00020
00021 boost::shared_ptr<urdf::Model> getUrdf(const ros::NodeHandle& nh, const std::string& param_name)
00022 {
00023 boost::shared_ptr<urdf::Model> urdf(new urdf::Model);
00024
00025 std::string urdf_str;
00026
00027 if (nh.getParam(param_name, urdf_str))
00028 {
00029 if (!urdf->initString(urdf_str))
00030 {
00031 ROS_ERROR_STREAM("Failed to parse URDF contained in '" << param_name << "' parameter (namespace: " <<
00032 nh.getNamespace() << ").");
00033 return boost::shared_ptr<urdf::Model>();
00034 }
00035 }
00036
00037 else if (!urdf->initParam("robot_description"))
00038 {
00039 ROS_ERROR_STREAM("Failed to parse URDF contained in '" << param_name << "' parameter");
00040 return boost::shared_ptr<urdf::Model>();
00041 }
00042 return urdf;
00043 }
00044
00045 typedef boost::shared_ptr<const urdf::Joint> UrdfJointConstPtr;
00046 std::vector<UrdfJointConstPtr> getUrdfJoints(const urdf::Model& urdf, const std::vector<std::string>& joint_names)
00047 {
00048 std::vector<UrdfJointConstPtr> out;
00049 for (unsigned int i = 0; i < joint_names.size(); ++i)
00050 {
00051 UrdfJointConstPtr urdf_joint = urdf.getJoint(joint_names[i]);
00052 if (urdf_joint)
00053 {
00054 out.push_back(urdf_joint);
00055 }
00056 else
00057 {
00058 ROS_ERROR_STREAM("Could not find joint '" << joint_names[i] << "' in URDF model.");
00059 return std::vector<UrdfJointConstPtr>();
00060 }
00061 }
00062 return out;
00063 }
00064
00065 }
00066
00067 template <class HardwareInterface>
00068 inline void GripperActionControllerTwo<HardwareInterface>::
00069 starting(const ros::Time& time)
00070 {
00071 command_struct_rt_.position_ = pos2Gap(rightjoint_.getPosition());
00072 command_struct_rt_.max_effort_ = default_max_effort_;
00073 command_.initRT(command_struct_rt_);
00074
00075 _lastPosition = command_struct_rt_.position_;
00076
00077
00078
00079 left_hw_iface_adapter_.starting(ros::Time(0.0));
00080 right_hw_iface_adapter_.starting(ros::Time(0.0));
00081 last_movement_time_ = time;
00082 }
00083
00084 template <class HardwareInterface>
00085 inline void GripperActionControllerTwo<HardwareInterface>::
00086 stopping(const ros::Time& time)
00087 {
00088 preemptActiveGoal();
00089 }
00090
00091 template <class HardwareInterface>
00092 inline void GripperActionControllerTwo<HardwareInterface>::
00093 preemptActiveGoal()
00094 {
00095 RealtimeGoalHandlePtr current_active_goal(rt_active_goal_);
00096
00097
00098 if (current_active_goal)
00099 {
00100
00101 rt_active_goal_.reset();
00102 if(current_active_goal->gh_.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
00103 current_active_goal->gh_.setCanceled();
00104 }
00105 }
00106
00107 template <class HardwareInterface>
00108 GripperActionControllerTwo<HardwareInterface>::
00109 GripperActionControllerTwo()
00110 : verbose_(false)
00111 {}
00112
00113 template <class HardwareInterface>
00114 bool GripperActionControllerTwo<HardwareInterface>::init(HardwareInterface* hw,
00115 ros::NodeHandle& root_nh,
00116 ros::NodeHandle& controller_nh)
00117 {
00118 using namespace internal;
00119
00120
00121 controller_nh_ = controller_nh;
00122
00123
00124 name_ = getLeafNamespace(controller_nh_);
00125
00126
00127 double action_monitor_rate = 20.0;
00128 controller_nh_.getParam("action_monitor_rate", action_monitor_rate);
00129 action_monitor_period_ = ros::Duration(1.0 / action_monitor_rate);
00130 ROS_DEBUG_STREAM_NAMED(name_, "Action status changes will be monitored at " << action_monitor_rate << "Hz.");
00131
00132
00133 controller_nh_.getParam("leftJoint", leftJoint_name_);
00134 controller_nh_.getParam("rightJoint", rightJoint_name_);
00135 _gapPub = controller_nh_.advertise<control_msgs::GripperCommandResult>("current_gap", 10);
00136 if (leftJoint_name_.empty() || rightJoint_name_.empty())
00137 {
00138 ROS_ERROR_STREAM_NAMED(name_, "Could not find joint name on param server");
00139 return false;
00140 }
00141
00142
00143 boost::shared_ptr<urdf::Model> urdf = getUrdf(root_nh, "robot_description");
00144 if (!urdf)
00145 {
00146 return false;
00147 }
00148
00149 std::vector<std::string> joint_names;
00150 joint_names.push_back(leftJoint_name_);
00151 joint_names.push_back(rightJoint_name_);
00152 std::vector<UrdfJointConstPtr> urdf_joints = getUrdfJoints(*urdf, joint_names);
00153 if (urdf_joints.empty())
00154 {
00155 return false;
00156 }
00157
00158
00159
00160 try
00161 {
00162 leftjoint_ = hw->getHandle(leftJoint_name_);
00163 rightjoint_ = hw->getHandle(rightJoint_name_);
00164 }
00165 catch (...)
00166 {
00167 ROS_ERROR_STREAM_NAMED(name_, "Could not find joint '" << leftJoint_name_ << "' in '" <<
00168 this->getHardwareInterfaceType() << "'.");
00169 return false;
00170 }
00171
00172 ROS_DEBUG_STREAM_NAMED(name_, "Initialized controller '" << name_ << "' with:" <<
00173 "\n- Hardware interface type: '" << this->getHardwareInterfaceType() << "'" <<
00174 "\n");
00175
00176
00177 controller_nh_.param<double>("goal_tolerance", goal_tolerance_, 0.01);
00178 goal_tolerance_ = fabs(goal_tolerance_);
00179
00180 controller_nh_.param<double>("max_effort", default_max_effort_, 0.0);
00181 default_max_effort_ = fabs(default_max_effort_);
00182
00183 controller_nh_.param<double>("stall_velocity_threshold", stall_velocity_threshold_, 0.001);
00184 controller_nh_.param<double>("stall_timeout", stall_timeout_, 1.0);
00185
00186
00187 left_hw_iface_adapter_.init(leftjoint_, controller_nh_);
00188 right_hw_iface_adapter_.init(rightjoint_, controller_nh_);
00189
00190
00191 command_struct_.position_ = pos2Gap(rightjoint_.getPosition());
00192 command_struct_.max_effort_ = default_max_effort_;
00193
00194
00195 pre_alloc_result_.reset(new control_msgs::GripperCommandResult());
00196 pre_alloc_result_->position = command_struct_.position_;
00197 pre_alloc_result_->reached_goal = false;
00198 pre_alloc_result_->stalled = false;
00199
00200
00201 action_server_.reset(new ActionServer(controller_nh_, "gripper_cmd",
00202 boost::bind(&GripperActionControllerTwo::goalCB, this, _1),
00203 boost::bind(&GripperActionControllerTwo::cancelCB, this, _1),
00204 false));
00205
00206 action_server_->start();
00207 return true;
00208 }
00209
00210 template <class HardwareInterface>
00211 void GripperActionControllerTwo<HardwareInterface>::
00212 update(const ros::Time& time, const ros::Duration& period)
00213 {
00214 command_struct_rt_ = *(command_.readFromRT());
00215
00216 double current_position = pos2Gap(rightjoint_.getPosition());
00217
00218 double current_velocity = current_position - _lastPosition / period.toSec();
00219 double current_effort = (fabs(leftjoint_.getEffort())>fabs(rightjoint_.getEffort())) ? fabs(leftjoint_.getEffort()):fabs(rightjoint_.getEffort());
00220 double error_position = command_struct_rt_.position_ - current_position;
00221 double error_velocity = - current_velocity;
00222 _lastPosition = current_position;
00223 if (command_struct_rt_.max_effort_==0) current_effort=-1;
00224 checkForSuccess(time, error_position, current_position, current_velocity, current_effort,command_struct_rt_.max_effort_);
00225
00226
00227 double jointsPos = gap2Pos(command_struct_rt_.position_);
00228
00229 computed_command_ = left_hw_iface_adapter_.updateCommand(time, period,
00230 -jointsPos, 0.0, error_position, error_velocity, command_struct_rt_.max_effort_);
00231 computed_command_ = right_hw_iface_adapter_.updateCommand(time, period,
00232 jointsPos, 0.0, error_position, error_velocity, command_struct_rt_.max_effort_);
00233 }
00234
00235 template <class HardwareInterface>
00236 void GripperActionControllerTwo<HardwareInterface>::
00237 goalCB(GoalHandle gh)
00238 {
00239 ROS_INFO("Recieved new action goal");
00240
00241
00242 if (!this->isRunning())
00243 {
00244 ROS_ERROR_NAMED(name_, "Can't accept new action goals. Controller is not running.");
00245 control_msgs::GripperCommandResult result;
00246 gh.setRejected(result);
00247 return;
00248 }
00249
00250
00251 RealtimeGoalHandlePtr rt_goal(new RealtimeGoalHandle(gh));
00252
00253
00254 preemptActiveGoal();
00255 gh.setAccepted();
00256
00257
00258
00259 command_struct_.position_ = gh.getGoal()->command.position;
00260 command_struct_.max_effort_ = gh.getGoal()->command.max_effort;
00261 command_.writeFromNonRT(command_struct_);
00262
00263 pre_alloc_result_->reached_goal = false;
00264 pre_alloc_result_->stalled = false;
00265
00266 last_movement_time_ = ros::Time::now();
00267
00268
00269 goal_handle_timer_ = controller_nh_.createTimer(action_monitor_period_,
00270 &RealtimeGoalHandle::runNonRealtime,
00271 rt_goal);
00272 goal_handle_timer_.start();
00273 rt_active_goal_ = rt_goal;
00274 ROS_INFO("GRIPPER: Got new goal");
00275 }
00276
00277 template <class HardwareInterface>
00278 void GripperActionControllerTwo<HardwareInterface>::
00279 cancelCB(GoalHandle gh)
00280 {
00281 RealtimeGoalHandlePtr current_active_goal(rt_active_goal_);
00282
00283
00284 if (current_active_goal && current_active_goal->gh_ == gh)
00285 {
00286
00287 rt_active_goal_.reset();
00288
00289
00290 setHoldPosition(ros::Time(0.0));
00291 ROS_DEBUG_NAMED(name_, "Canceling active action goal because cancel callback recieved from actionlib.");
00292
00293
00294 current_active_goal->gh_.setCanceled();
00295 }
00296 }
00297
00298 template <class HardwareInterface>
00299 void GripperActionControllerTwo<HardwareInterface>::
00300 setHoldPosition(const ros::Time& time)
00301 {
00302 ROS_WARN("INSIDE setHoldPosition");
00303 ROS_WARN("rightjoint_.getPosition(): %f", rightjoint_.getPosition());
00304
00305 command_struct_.position_ = pos2Gap(rightjoint_.getPosition()) - 0.03;
00306
00307 ROS_WARN("command_struct_.position_ = pos2Gap(rightjoint_.getPosition()): %f", pos2Gap(rightjoint_.getPosition()));
00308
00309 command_.writeFromNonRT(command_struct_);
00310
00311 }
00312
00313 template <class HardwareInterface>
00314 void GripperActionControllerTwo<HardwareInterface>::
00315 checkForSuccess(const ros::Time &time, double error_position, double current_position, double current_velocity,
00316 double current_effort,double max_effort)
00317 {
00318
00319
00320 if(!rt_active_goal_) {
00321 return;
00322 }
00323
00324 if(rt_active_goal_->gh_.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE){
00325 return;
00326 }
00327 if(fabs(error_position) < goal_tolerance_)
00328 {
00329 pre_alloc_result_->effort = computed_command_;
00330 pre_alloc_result_->position = current_position;
00331 pre_alloc_result_->reached_goal = true;
00332 pre_alloc_result_->stalled = false;
00333 rt_active_goal_->setSucceeded(pre_alloc_result_);
00334 ROS_INFO("GRIPPER: Reached Goal");
00335 }
00336 else
00337 {
00338 if (current_effort >= fabs(max_effort)) {
00339 ROS_WARN("GRIPPER: MAX EFFORT");
00340
00341
00342
00343 pre_alloc_result_->effort = computed_command_;
00344 pre_alloc_result_->position = current_position;
00345 pre_alloc_result_->reached_goal = false;
00346 pre_alloc_result_->stalled = true;
00347
00348
00349 ROS_WARN("pre_alloc_result_->effort: %f", pre_alloc_result_->effort);
00350 ROS_WARN("pre_alloc_result_->position: %f", pre_alloc_result_->position);
00351
00352 rt_active_goal_->setSucceeded(pre_alloc_result_);
00353 setHoldPosition(ros::Time(0.0));
00354 return;
00355 }
00356
00357 if(fabs(current_velocity) > stall_velocity_threshold_) {
00358
00359 last_movement_time_ = time;
00360 }
00361 else if( (time - last_movement_time_).toSec() > stall_timeout_)
00362 {
00363 ROS_WARN("GRIPPER: STALLED");
00364 pre_alloc_result_->effort = computed_command_;
00365 pre_alloc_result_->position = current_position;
00366 pre_alloc_result_->reached_goal = false;
00367 pre_alloc_result_->stalled = true;
00368 rt_active_goal_->setAborted(pre_alloc_result_);
00369 setHoldPosition(ros::Time(0.0));
00370
00371 }
00372 }
00373 }
00374
00375 }
00376
00377 #endif //ROBOTICAN_CONTROLLERS_GRIPPER_ACTION_CONTROLLER_IMPL_H