00001
00002
00003
00004
00005 #ifndef ROBOTICAN_CONTROLLERS_JOINT_WITH_EFFORT_TRAJECTORY_CONTROLLER_IMPL_H
00006 #define ROBOTICAN_CONTROLLERS_JOINT_WITH_EFFORT_TRAJECTORY_CONTROLLER_IMPL_H
00007
00008 namespace joint_with_effort_trajectory_controller
00009 {
00010
00011 namespace internal
00012 {
00013
00014 template <class Enclosure, class Member>
00015 inline boost::shared_ptr<Member> share_member(boost::shared_ptr<Enclosure> enclosure, Member &member)
00016 {
00017 actionlib::EnclosureDeleter<Enclosure> d(enclosure);
00018 boost::shared_ptr<Member> p(&member, d);
00019 return p;
00020 }
00021
00022 std::vector<std::string> getStrings(const ros::NodeHandle& nh, const std::string& param_name)
00023 {
00024 using namespace XmlRpc;
00025 XmlRpcValue xml_array;
00026 if (!nh.getParam(param_name, xml_array))
00027 {
00028 ROS_ERROR_STREAM("Could not find '" << param_name << "' parameter (namespace: " << nh.getNamespace() << ").");
00029 return std::vector<std::string>();
00030 }
00031 if (xml_array.getType() != XmlRpcValue::TypeArray)
00032 {
00033 ROS_ERROR_STREAM("The '" << param_name << "' parameter is not an array (namespace: " <<
00034 nh.getNamespace() << ").");
00035 return std::vector<std::string>();
00036 }
00037
00038 std::vector<std::string> out;
00039 for (int i = 0; i < xml_array.size(); ++i)
00040 {
00041 if (xml_array[i].getType() != XmlRpcValue::TypeString)
00042 {
00043 ROS_ERROR_STREAM("The '" << param_name << "' parameter contains a non-string element (namespace: " <<
00044 nh.getNamespace() << ").");
00045 return std::vector<std::string>();
00046 }
00047 out.push_back(static_cast<std::string>(xml_array[i]));
00048 }
00049 return out;
00050 }
00051
00052 boost::shared_ptr<urdf::Model> getUrdf(const ros::NodeHandle& nh, const std::string& param_name)
00053 {
00054 boost::shared_ptr<urdf::Model> urdf(new urdf::Model);
00055
00056 std::string urdf_str;
00057
00058 if (nh.getParam(param_name, urdf_str))
00059 {
00060 if (!urdf->initString(urdf_str))
00061 {
00062 ROS_ERROR_STREAM("Failed to parse URDF contained in '" << param_name << "' parameter (namespace: " <<
00063 nh.getNamespace() << ").");
00064 return boost::shared_ptr<urdf::Model>();
00065 }
00066 }
00067
00068 else if (!urdf->initParam("robot_description"))
00069 {
00070 ROS_ERROR_STREAM("Failed to parse URDF contained in '" << param_name << "' parameter");
00071 return boost::shared_ptr<urdf::Model>();
00072 }
00073 return urdf;
00074 }
00075
00076 typedef boost::shared_ptr<const urdf::Joint> UrdfJointConstPtr;
00077 std::vector<UrdfJointConstPtr> getUrdfJoints(const urdf::Model& urdf, const std::vector<std::string>& joint_names)
00078 {
00079 std::vector<UrdfJointConstPtr> out;
00080 for (unsigned int i = 0; i < joint_names.size(); ++i)
00081 {
00082 UrdfJointConstPtr urdf_joint = urdf.getJoint(joint_names[i]);
00083 if (urdf_joint)
00084 {
00085 out.push_back(urdf_joint);
00086 }
00087 else
00088 {
00089 ROS_ERROR_STREAM("Could not find joint '" << joint_names[i] << "' in URDF model.");
00090 return std::vector<UrdfJointConstPtr>();
00091 }
00092 }
00093 return out;
00094 }
00095
00096 std::string getLeafNamespace(const ros::NodeHandle& nh)
00097 {
00098 const std::string complete_ns = nh.getNamespace();
00099 std::size_t id = complete_ns.find_last_of("/");
00100 return complete_ns.substr(id + 1);
00101 }
00102
00103 }
00104
00105 template <class SegmentImpl, class HardwareInterface>
00106 inline void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00107 starting(const ros::Time& time)
00108 {
00109
00110 TimeData time_data;
00111 time_data.time = time;
00112 time_data.uptime = ros::Time(0.0);
00113 time_data_.initRT(time_data);
00114
00115
00116 setHoldPosition(time_data.uptime);
00117
00118
00119 last_state_publish_time_ = time_data.uptime;
00120
00121
00122 hw_iface_adapter_.starting(time_data.uptime);
00123 }
00124
00125 template <class SegmentImpl, class HardwareInterface>
00126 inline void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00127 stopping(const ros::Time& )
00128 {
00129 preemptActiveGoal();
00130 }
00131
00132 template <class SegmentImpl, class HardwareInterface>
00133 inline void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00134 trajectoryCommandCB(const JointTrajectoryConstPtr& msg)
00135 {
00136 const bool update_ok = updateTrajectoryCommand(msg, RealtimeGoalHandlePtr());
00137 if (update_ok) {preemptActiveGoal();}
00138 }
00139
00140 template <class SegmentImpl, class HardwareInterface>
00141 inline void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00142 preemptActiveGoal()
00143 {
00144 RealtimeGoalHandlePtr current_active_goal(rt_active_goal_);
00145
00146
00147 if (current_active_goal)
00148 {
00149
00150 rt_active_goal_.reset();
00151 current_active_goal->gh_.setCanceled();
00152 }
00153 }
00154
00155 template <class SegmentImpl, class HardwareInterface>
00156 inline void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00157 checkPathTolerances(const typename Segment::State& state_error,
00158 const Segment& segment)
00159 {
00160 const RealtimeGoalHandlePtr rt_segment_goal = segment.getGoalHandle();
00161 const SegmentTolerances<Scalar>& tolerances = segment.getTolerances();
00162 ROS_INFO("CUR: %f, Goal: %f", _currentEffort, _goalEffort);
00163 if(_goalEffort != 0 && _currentEffort > _goalEffort) {
00164 ROS_INFO("MAX effort");
00165 rt_segment_goal->preallocated_result_->error_code = control_msgs::FollowJointTrajectoryResult::SUCCESSFUL;
00166 rt_segment_goal->setSucceeded(rt_segment_goal->preallocated_result_);
00167 rt_active_goal_.reset();
00168 }
00169 else if (!checkStateTolerance(state_error, tolerances.state_tolerance))
00170 {
00171 rt_segment_goal->preallocated_result_->error_code =
00172 control_msgs::FollowJointTrajectoryResult::PATH_TOLERANCE_VIOLATED;
00173 rt_segment_goal->setAborted(rt_segment_goal->preallocated_result_);
00174 rt_active_goal_.reset();
00175 }
00176 }
00177
00178 template <class SegmentImpl, class HardwareInterface>
00179 inline void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00180 checkGoalTolerances(const typename Segment::State& state_error,
00181 const Segment& segment)
00182 {
00183
00184 const ros::Time uptime = time_data_.readFromRT()->uptime;
00185
00186
00187 const RealtimeGoalHandlePtr rt_segment_goal = segment.getGoalHandle();
00188 const SegmentTolerances<Scalar>& tolerances = segment.getTolerances();
00189 const bool inside_goal_tolerances = checkStateTolerance(state_error, tolerances.goal_state_tolerance);
00190
00191 if (inside_goal_tolerances || (_goalEffort != 0 && _currentEffort >= _goalEffort))
00192 {
00193 rt_segment_goal->preallocated_result_->error_code = control_msgs::FollowJointTrajectoryResult::SUCCESSFUL;
00194 rt_segment_goal->setSucceeded(rt_segment_goal->preallocated_result_);
00195 rt_active_goal_.reset();
00196 if(_goalEffort != 0 && _currentEffort >= _goalEffort) {
00197 ROS_INFO("MAX effort");
00198 }
00199 }
00200 else if (uptime.toSec() < segment.endTime() + tolerances.goal_time_tolerance)
00201 {
00202
00203 }
00204 else
00205 {
00206 if (verbose_)
00207 {
00208 ROS_ERROR_STREAM_NAMED(name_,"Goal tolerances failed");
00209
00210 checkStateTolerance(state_error, tolerances.goal_state_tolerance, true);
00211 }
00212
00213 rt_segment_goal->preallocated_result_->error_code = control_msgs::FollowJointTrajectoryResult::GOAL_TOLERANCE_VIOLATED;
00214 rt_segment_goal->setAborted(rt_segment_goal->preallocated_result_);
00215 rt_active_goal_.reset();
00216 }
00217 }
00218
00219 template <class SegmentImpl, class HardwareInterface>
00220 JointTrajectoryController<SegmentImpl, HardwareInterface>::
00221 JointTrajectoryController()
00222 : verbose_(false),
00223 hold_trajectory_ptr_(new Trajectory)
00224 {}
00225
00226 template <class SegmentImpl, class HardwareInterface>
00227 bool JointTrajectoryController<SegmentImpl, HardwareInterface>::init(HardwareInterface* hw,
00228 ros::NodeHandle& root_nh,
00229 ros::NodeHandle& controller_nh)
00230 {
00231 using namespace internal;
00232
00233 controller_nh_ = controller_nh;
00234
00235
00236 name_ = getLeafNamespace(controller_nh_);
00237
00238
00239 double state_publish_rate = 50.0;
00240 controller_nh_.getParam("state_publish_rate", state_publish_rate);
00241 ROS_DEBUG_STREAM_NAMED(name_, "Controller state will be published at " << state_publish_rate << "Hz.");
00242 state_publisher_period_ = ros::Duration(1.0 / state_publish_rate);
00243
00244
00245 double action_monitor_rate = 20.0;
00246 controller_nh_.getParam("action_monitor_rate", action_monitor_rate);
00247 action_monitor_period_ = ros::Duration(1.0 / action_monitor_rate);
00248 ROS_DEBUG_STREAM_NAMED(name_, "Action status changes will be monitored at " << action_monitor_rate << "Hz.");
00249
00250
00251 stop_trajectory_duration_ = 0.0;
00252 _currentEffort = 0;
00253 if (!controller_nh_.getParam("stop_trajectory_duration", stop_trajectory_duration_))
00254 {
00255
00256 if (controller_nh_.getParam("hold_trajectory_duration", stop_trajectory_duration_))
00257 {
00258 ROS_WARN("The 'hold_trajectory_duration' has been deprecated in favor of the 'stop_trajectory_duration' parameter. Please update your controller configuration.");
00259 }
00260 }
00261 ROS_DEBUG_STREAM_NAMED(name_, "Stop trajectory has a duration of " << stop_trajectory_duration_ << "s.");
00262
00263
00264 joint_names_ = getStrings(controller_nh_, "joints");
00265 if (joint_names_.empty()) {return false;}
00266 const unsigned int n_joints = joint_names_.size();
00267
00268
00269 boost::shared_ptr<urdf::Model> urdf = getUrdf(root_nh, "robot_description");
00270 if (!urdf) {return false;}
00271
00272 std::vector<UrdfJointConstPtr> urdf_joints = getUrdfJoints(*urdf, joint_names_);
00273 if (urdf_joints.empty()) {return false;}
00274 assert(n_joints == urdf_joints.size());
00275
00276
00277 joints_.resize(n_joints);
00278 angle_wraparound_.resize(n_joints);
00279 for (unsigned int i = 0; i < n_joints; ++i)
00280 {
00281
00282 try {joints_[i] = hw->getHandle(joint_names_[i]);}
00283 catch (...)
00284 {
00285 ROS_ERROR_STREAM_NAMED(name_, "Could not find joint '" << joint_names_[i] << "' in '" <<
00286 this->getHardwareInterfaceType() << "'.");
00287 return false;
00288 }
00289
00290
00291 angle_wraparound_[i] = urdf_joints[i]->type == urdf::Joint::CONTINUOUS;
00292 const std::string not_if = angle_wraparound_[i] ? "" : "non-";
00293
00294 ROS_DEBUG_STREAM_NAMED(name_, "Found " << not_if << "continuous joint '" << joint_names_[i] << "' in '" <<
00295 this->getHardwareInterfaceType() << "'.");
00296 }
00297
00298 assert(joints_.size() == angle_wraparound_.size());
00299 ROS_DEBUG_STREAM_NAMED(name_, "Initialized controller '" << name_ << "' with:" <<
00300 "\n- Number of joints: " << joints_.size() <<
00301 "\n- Hardware interface type: '" << this->getHardwareInterfaceType() << "'" <<
00302 "\n- Trajectory segment type: '" << hardware_interface::internal::demangledTypeName<SegmentImpl>() << "'");
00303
00304
00305 ros::NodeHandle tol_nh(controller_nh_, "constraints");
00306 default_tolerances_ = getSegmentTolerances<Scalar>(tol_nh, joint_names_);
00307
00308
00309 hw_iface_adapter_.init(joints_, controller_nh_);
00310
00311
00312 trajectory_command_sub_ = controller_nh_.subscribe("command", 1, &JointTrajectoryController::trajectoryCommandCB, this);
00313
00314
00315 state_publisher_.reset(new StatePublisher(controller_nh_, "state", 1));
00316
00317
00318 action_server_.reset(new ActionServer(controller_nh_, "follow_joint_trajectory",
00319 boost::bind(&JointTrajectoryController::goalCB, this, _1),
00320 boost::bind(&JointTrajectoryController::cancelCB, this, _1),
00321 false));
00322 action_server_->start();
00323
00324
00325 query_state_service_ = controller_nh_.advertiseService("query_state",
00326 &JointTrajectoryController::queryStateService,
00327 this);
00328
00329
00330 current_state_ = typename Segment::State(n_joints);
00331 desired_state_ = typename Segment::State(n_joints);
00332 state_error_ = typename Segment::State(n_joints);
00333 hold_start_state_ = typename Segment::State(n_joints);
00334 hold_end_state_ = typename Segment::State(n_joints);
00335
00336 Segment hold_segment(0.0, current_state_, 0.0, current_state_);
00337 hold_trajectory_ptr_->resize(1, hold_segment);
00338
00339 {
00340 state_publisher_->lock();
00341 state_publisher_->msg_.joint_names = joint_names_;
00342 state_publisher_->msg_.desired.positions.resize(n_joints);
00343 state_publisher_->msg_.desired.velocities.resize(n_joints);
00344 state_publisher_->msg_.desired.accelerations.resize(n_joints);
00345 state_publisher_->msg_.actual.positions.resize(n_joints);
00346 state_publisher_->msg_.actual.velocities.resize(n_joints);
00347 state_publisher_->msg_.error.positions.resize(n_joints);
00348 state_publisher_->msg_.error.velocities.resize(n_joints);
00349 state_publisher_->unlock();
00350 }
00351
00352 return true;
00353 }
00354
00355 template <class SegmentImpl, class HardwareInterface>
00356 void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00357 update(const ros::Time& time, const ros::Duration& period)
00358 {
00359
00360 TrajectoryPtr curr_traj_ptr;
00361 curr_trajectory_box_.get(curr_traj_ptr);
00362 Trajectory& curr_traj = *curr_traj_ptr;
00363
00364
00365 TimeData time_data;
00366 time_data.time = time;
00367 time_data.period = period;
00368 time_data.uptime = time_data_.readFromRT()->uptime + period;
00369 time_data_.writeFromNonRT(time_data);
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 typename Trajectory::const_iterator segment_it = sample(curr_traj, time_data.uptime.toSec(), desired_state_);
00381 if (curr_traj.end() == segment_it)
00382 {
00383
00384 ROS_ERROR_NAMED(name_,
00385 "Unexpected error: No trajectory defined at current time. Please contact the package maintainer.");
00386 return;
00387 }
00388
00389
00390 double maxCurrentEffort = -100.0;
00391 for (unsigned int i = 0; i < joints_.size(); ++i)
00392 {
00393 current_state_.position[i] = joints_[i].getPosition();
00394 current_state_.velocity[i] = joints_[i].getVelocity();
00395 maxCurrentEffort = (maxCurrentEffort <= joints_[i].getEffort()) ? joints_[i].getEffort() : maxCurrentEffort;
00396
00397
00398 state_error_.position[i] = desired_state_.position[i] - current_state_.position[i];
00399 state_error_.velocity[i] = desired_state_.velocity[i] - current_state_.velocity[i];
00400 state_error_.acceleration[i] = 0.0;
00401 }
00402 _currentEffort = maxCurrentEffort;
00403
00404 const RealtimeGoalHandlePtr rt_segment_goal = segment_it->getGoalHandle();
00405 if (rt_segment_goal && rt_segment_goal == rt_active_goal_)
00406 {
00407
00408 if (time_data.uptime.toSec() < segment_it->endTime())
00409 {
00410
00411 checkPathTolerances(state_error_,
00412 *segment_it);
00413 }
00414 else if (segment_it == --curr_traj.end())
00415 {
00416 if (verbose_)
00417 ROS_DEBUG_STREAM_THROTTLE_NAMED(1,name_,"Finished executing last segement, checking goal tolerances");
00418
00419
00420 checkGoalTolerances(state_error_,
00421 *segment_it);
00422 }
00423 }
00424
00425
00426 hw_iface_adapter_.updateCommand(time_data.uptime, time_data.period,
00427 desired_state_, state_error_);
00428
00429
00430 publishState(time_data.uptime);
00431 }
00432
00433 template <class SegmentImpl, class HardwareInterface>
00434 bool JointTrajectoryController<SegmentImpl, HardwareInterface>::
00435 updateTrajectoryCommand(const JointTrajectoryConstPtr& msg, RealtimeGoalHandlePtr gh)
00436 {
00437 typedef InitJointTrajectoryOptions<Trajectory> Options;
00438
00439
00440 if (!this->isRunning())
00441 {
00442 ROS_ERROR_NAMED(name_, "Can't accept new commands. Controller is not running.");
00443 return false;
00444 }
00445
00446 if (!msg)
00447 {
00448 ROS_WARN_NAMED(name_, "Received null-pointer trajectory message, skipping.");
00449 return false;
00450 }
00451
00452
00453 TimeData* time_data = time_data_.readFromRT();
00454
00455
00456 const ros::Time next_update_time = time_data->time + time_data->period;
00457
00458
00459 ros::Time next_update_uptime = time_data->uptime + time_data->period;
00460
00461
00462 if (msg->points.empty())
00463 {
00464 setHoldPosition(time_data->uptime);
00465 ROS_DEBUG_NAMED(name_, "Empty trajectory command, stopping.");
00466 return true;
00467 }
00468
00469
00470 TrajectoryPtr curr_traj_ptr;
00471 curr_trajectory_box_.get(curr_traj_ptr);
00472
00473 Options options;
00474 options.other_time_base = &next_update_uptime;
00475 options.current_trajectory = curr_traj_ptr.get();
00476 options.joint_names = &joint_names_;
00477 options.angle_wraparound = &angle_wraparound_;
00478 options.rt_goal_handle = gh;
00479 options.default_tolerances = &default_tolerances_;
00480
00481
00482 try
00483 {
00484 TrajectoryPtr traj_ptr(new Trajectory);
00485 *traj_ptr = initJointTrajectory<Trajectory>(*msg, next_update_time, options);
00486 if (!traj_ptr->empty())
00487 {
00488 curr_trajectory_box_.set(traj_ptr);
00489 }
00490 else
00491 {
00492
00493 return false;
00494 }
00495 }
00496 catch(const std::invalid_argument& ex)
00497 {
00498 ROS_ERROR_STREAM_NAMED(name_, ex.what());
00499 return false;
00500 }
00501 catch(...)
00502 {
00503 ROS_ERROR_NAMED(name_, "Unexpected exception caught when initializing trajectory from ROS message data.");
00504 return false;
00505 }
00506
00507 return true;
00508 }
00509
00510 template <class SegmentImpl, class HardwareInterface>
00511 void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00512 goalCB(GoalHandle gh)
00513 {
00514 ROS_DEBUG_STREAM_NAMED(name_,"Recieved new action goal");
00515
00516
00517 if (!this->isRunning())
00518 {
00519 ROS_ERROR_NAMED(name_, "Can't accept new action goals. Controller is not running.");
00520 control_msgs::FollowJointTrajectoryResult result;
00521 result.error_code = control_msgs::FollowJointTrajectoryResult::INVALID_GOAL;
00522 gh.setRejected(result);
00523 return;
00524 }
00525
00526
00527 using joint_trajectory_controller::internal::permutation;
00528 std::vector<unsigned int> permutation_vector = permutation(joint_names_, gh.getGoal()->trajectory.joint_names);
00529
00530 if (permutation_vector.empty())
00531 {
00532 ROS_ERROR_NAMED(name_, "Joints on incoming goal don't match the controller joints.");
00533 control_msgs::FollowJointTrajectoryResult result;
00534 result.error_code = control_msgs::FollowJointTrajectoryResult::INVALID_JOINTS;
00535 gh.setRejected(result);
00536 return;
00537 }
00538
00539
00540 RealtimeGoalHandlePtr rt_goal(new RealtimeGoalHandle(gh));
00541 const bool update_ok = updateTrajectoryCommand(internal::share_member(gh.getGoal(), gh.getGoal()->trajectory),
00542 rt_goal);
00543
00544 if (update_ok)
00545 {
00546
00547 preemptActiveGoal();
00548 gh.setAccepted();
00549 rt_active_goal_ = rt_goal;
00550 size_t size = rt_goal->gh_.getGoal()->trajectory.points.size();
00551 if(!rt_goal->gh_.getGoal()->trajectory.points.empty() && !rt_goal->gh_.getGoal()->trajectory.points[size - 1].effort.empty()) {
00552
00553 _goalEffort = rt_goal->gh_.getGoal()->trajectory.points[size - 1].effort[0];
00554 ROS_INFO("goal effort is: %f", _goalEffort);
00555 } else {
00556 _goalEffort = 0.0;
00557 }
00558
00559 goal_handle_timer_ = controller_nh_.createTimer(action_monitor_period_,
00560 &RealtimeGoalHandle::runNonRealtime,
00561 rt_goal);
00562 goal_handle_timer_.start();
00563 }
00564 else
00565 {
00566
00567 control_msgs::FollowJointTrajectoryResult result;
00568 result.error_code = control_msgs::FollowJointTrajectoryResult::INVALID_GOAL;
00569 gh.setRejected(result);
00570 }
00571 }
00572
00573 template <class SegmentImpl, class HardwareInterface>
00574 void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00575 cancelCB(GoalHandle gh)
00576 {
00577 RealtimeGoalHandlePtr current_active_goal(rt_active_goal_);
00578
00579
00580 if (current_active_goal && current_active_goal->gh_ == gh)
00581 {
00582
00583 rt_active_goal_.reset();
00584
00585
00586 const ros::Time uptime = time_data_.readFromRT()->uptime;
00587
00588
00589 setHoldPosition(uptime);
00590 ROS_DEBUG_NAMED(name_, "Canceling active action goal because cancel callback recieved from actionlib.");
00591
00592
00593 current_active_goal->gh_.setCanceled();
00594 }
00595 }
00596
00597 template <class SegmentImpl, class HardwareInterface>
00598 bool JointTrajectoryController<SegmentImpl, HardwareInterface>::
00599 queryStateService(control_msgs::QueryTrajectoryState::Request& req,
00600 control_msgs::QueryTrajectoryState::Response& resp)
00601 {
00602
00603 if (!this->isRunning())
00604 {
00605 ROS_ERROR_NAMED(name_, "Can't sample trajectory. Controller is not running.");
00606 return false;
00607 }
00608
00609
00610 TimeData* time_data = time_data_.readFromRT();
00611 const ros::Duration time_offset = req.time - time_data->time;
00612 const ros::Time sample_time = time_data->uptime + time_offset;
00613
00614
00615 TrajectoryPtr curr_traj_ptr;
00616 curr_trajectory_box_.get(curr_traj_ptr);
00617 Trajectory& curr_traj = *curr_traj_ptr;
00618
00619 typename Segment::State state;
00620 typename Trajectory::const_iterator segment_it = sample(curr_traj, sample_time.toSec(), state);
00621 if (curr_traj.end() == segment_it)
00622 {
00623 ROS_ERROR_STREAM_NAMED(name_, "Requested sample time preceeds trajectory start time.");
00624 return false;
00625 }
00626
00627
00628 resp.name = joint_names_;
00629 resp.position = state.position;
00630 resp.velocity = state.velocity;
00631 resp.acceleration = state.acceleration;
00632
00633 return true;
00634 }
00635
00636 template <class SegmentImpl, class HardwareInterface>
00637 void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00638 publishState(const ros::Time& time)
00639 {
00640
00641 if (!state_publisher_period_.isZero() && last_state_publish_time_ + state_publisher_period_ < time)
00642 {
00643 if (state_publisher_ && state_publisher_->trylock())
00644 {
00645 last_state_publish_time_ += state_publisher_period_;
00646
00647 state_publisher_->msg_.header.stamp = time_data_.readFromRT()->time;
00648 state_publisher_->msg_.desired.positions = desired_state_.position;
00649 state_publisher_->msg_.desired.velocities = desired_state_.velocity;
00650 state_publisher_->msg_.desired.accelerations = desired_state_.acceleration;
00651 state_publisher_->msg_.actual.positions = current_state_.position;
00652 state_publisher_->msg_.actual.velocities = current_state_.velocity;
00653 state_publisher_->msg_.error.positions = state_error_.position;
00654 state_publisher_->msg_.error.velocities = state_error_.velocity;
00655
00656 state_publisher_->unlockAndPublish();
00657 }
00658 }
00659 }
00660
00661 template <class SegmentImpl, class HardwareInterface>
00662 void JointTrajectoryController<SegmentImpl, HardwareInterface>::
00663 setHoldPosition(const ros::Time& time)
00664 {
00665
00666
00667
00668
00669
00670
00671 assert(1 == hold_trajectory_ptr_->size());
00672
00673 const typename Segment::Time start_time = time.toSec();
00674 const typename Segment::Time end_time = time.toSec() + stop_trajectory_duration_;
00675 const typename Segment::Time end_time_2x = time.toSec() + 2.0 * stop_trajectory_duration_;
00676
00677
00678 const unsigned int n_joints = joints_.size();
00679 for (unsigned int i = 0; i < n_joints; ++i)
00680 {
00681 hold_start_state_.position[i] = joints_[i].getPosition();
00682 hold_start_state_.velocity[i] = joints_[i].getVelocity();
00683 hold_start_state_.acceleration[i] = 0.0;
00684
00685 hold_end_state_.position[i] = joints_[i].getPosition();
00686 hold_end_state_.velocity[i] = -joints_[i].getVelocity();
00687 hold_end_state_.acceleration[i] = 0.0;
00688 }
00689 hold_trajectory_ptr_->front().init(start_time, hold_start_state_,
00690 end_time_2x, hold_end_state_);
00691
00692
00693 hold_trajectory_ptr_->front().sample(end_time, hold_end_state_);
00694
00695
00696 hold_trajectory_ptr_->front().init(start_time, hold_start_state_,
00697 end_time, hold_end_state_);
00698
00699 curr_trajectory_box_.set(hold_trajectory_ptr_);
00700 }
00701
00702 }
00703
00704 #endif //ROBOTICAN_CONTROLLERS_JOINT_WITH_EFFORT_TRAJECTORY_CONTROLLER_IMPL_H