Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00056
00057
00058
00059
00060 #include <sys/types.h>
00061 #include <unistd.h>
00062 #include <math.h>
00063 #include <boost/bind.hpp>
00064 #include <sstream>
00065 #include <string>
00066
00067
00068
00069
00070 #include "ros/ros.h"
00071
00072
00073
00074
00075 #include "std_msgs/String.h"
00076 #include "control_msgs/FollowJointTrajectoryAction.h"
00077
00078
00079
00080
00081 #include "actionlib/server/simple_action_server.h"
00082
00083
00084
00085
00086 #include "Hekateros/hekateros.h"
00087 #include "Hekateros/hekJoint.h"
00088 #include "Hekateros/hekTraj.h"
00089 #include "Hekateros/hekUtils.h"
00090 #include "Hekateros/hekRobot.h"
00091
00092
00093
00094
00095 #include "hekateros_control.h"
00096 #include "hekateros_as_follow_traj.h"
00097
00098
00099 using namespace std;
00100 using namespace hekateros;
00101 using namespace control_msgs;
00102 using namespace trajectory_msgs;
00103 using namespace hekateros_control;
00104
00105
00106
00107
00108 const double ASFollowTrajectory::TolWaypoint = 0.01745;
00109 const double ASFollowTrajectory::TolGoal = 0.00087;
00110 const int ASFollowTrajectory::MaxIters = 10;
00111
00112
00113
00114 #define HACK_MAX_GEAR_RATIO 4.0 // gear ratios vary from 1.5 to 4.0
00115 #define HACK_MIN_SERVO_RPM 45.0 // MXs vary from 45.0 to 78.0
00116 #define HACK_MAX_RADS_PER_SEC \
00117 ( (HACK_MIN_SERVO_RPM / HACK_MAX_GEAR_RATIO / 60.0) * M_TAU )
00118
00119
00120 inline double velPerCent(double velRadsPerSec)
00121 {
00122 double vel = fabs(velRadsPerSec) / HACK_MAX_RADS_PER_SEC * 100.0;
00123
00124 if( vel < 0.0 )
00125 {
00126 return 0.0;
00127 }
00128 else if( vel > 100.0 )
00129 {
00130 return 100.0;
00131 }
00132 else
00133 {
00134 return vel;
00135 }
00136 }
00137
00138
00139 void ASFollowTrajectory::execute_cb(
00140 const FollowJointTrajectoryGoalConstPtr &goal)
00141 {
00142 JointTrajectory jt;
00143 ssize_t numWaypoints;
00144 ssize_t iWaypoint;
00145 int rc;
00146
00147 ROS_INFO("%s: Executing FollowJointTrajectory goal of %zu waypoints.",
00148 action_name_.c_str(), goal->trajectory.points.size());
00149
00150
00151
00152
00153
00154
00155 jt = goal->trajectory;
00156
00157 numWaypoints = (ssize_t)jt.points.size();
00158
00159
00160 if( numWaypoints <= 0 )
00161 {
00162 ROS_ERROR("%s: No joint trajectory path.", action_name_.c_str());
00163 result_.error_code = FollowJointTrajectoryResult::INVALID_GOAL;
00164 as_.setAborted(result_);
00165 return;
00166 }
00167
00168
00169 feedback_.joint_names = jt.joint_names;
00170
00171 iWaypoint = -1;
00172
00173
00174 ros::Rate ctl_rate(10);
00175
00176
00177
00178
00179 while( (iWaypoint < numWaypoints) && ros::ok() )
00180 {
00181
00182
00183
00184 if( as_.isPreemptRequested() )
00185 {
00186 ROS_INFO("%s: Action execution preempted on waypoint %zd.",
00187 action_name_.c_str(), iWaypoint);
00188 result_.error_code = FollowJointTrajectoryResult::INVALID_GOAL;
00189 as_.setPreempted(result_);
00190 return;
00191 }
00192
00193
00194
00195
00196 else if( (iWaypoint == -1) || atWaypoint(jt, iWaypoint) )
00197 {
00198 ++iWaypoint;
00199
00200
00201 if( iWaypoint >= numWaypoints )
00202 {
00203 break;
00204 }
00205
00206 if( (rc = moveToWaypoint(jt, iWaypoint)) == HEK_OK )
00207 {
00208 ROS_INFO("%s: Moving to trajectory waypoint %zd.",
00209 action_name_.c_str(), iWaypoint);
00210 m_fTolerance = iWaypoint < numWaypoints-1? TolWaypoint: TolGoal;
00211 m_iterMonitor = 0;
00212 feedback_.desired = jt.points[iWaypoint];
00213 }
00214 else
00215 {
00216 ROS_ERROR("%s: Failed moving arm to trajectory waypoint %zd.",
00217 action_name_.c_str(), iWaypoint);
00218 result_.error_code = FollowJointTrajectoryResult::INVALID_JOINTS;
00219 as_.setAborted(result_);
00220 return;
00221 }
00222 }
00223
00224
00225
00226
00227 else if ( failedWaypoint(jt, iWaypoint) )
00228 {
00229 ROS_ERROR("%s: Failed to reach waypoint %zd.",
00230 action_name_.c_str(), iWaypoint);
00231 result_.error_code = FollowJointTrajectoryResult::INVALID_GOAL;
00232 as_.setAborted(result_);
00233 return;
00234 }
00235
00236
00237
00238
00239 monitorMove(jt, iWaypoint);
00240
00241 ctl_rate.sleep();
00242 }
00243
00244
00245
00246
00247 if( ros::ok() )
00248 {
00249 ROS_INFO("%s: Follow trajectory succeeded.", action_name_.c_str());
00250 result_.error_code = FollowJointTrajectoryResult::SUCCESSFUL;
00251 as_.setSucceeded(result_);
00252 }
00253
00254
00255
00256
00257 else
00258 {
00259 ROS_ERROR("%s: Follow trajectory failed.", action_name_.c_str());
00260 result_.error_code = FollowJointTrajectoryResult::GOAL_TOLERANCE_VIOLATED;
00261 as_.setAborted(result_);
00262 }
00263 }
00264
00265 int ASFollowTrajectory::moveToWaypoint(JointTrajectory &jt, ssize_t iWaypoint)
00266 {
00267 HekRobot &robot(node_.getRobot());
00268 HekJointTrajectoryPoint pt;
00269 int j;
00270
00271
00272
00273
00274 for(j=0; j<jt.joint_names.size(); ++j)
00275 {
00276 pt.append(jt.joint_names[j],
00277 jt.points[iWaypoint].positions[j],
00278 velPerCent(jt.points[iWaypoint].velocities[j]));
00279
00280 ROS_INFO("%s: pos=%5.3f speed=%2.1f",
00281 jt.joint_names[j].c_str(),
00282 jt.points[iWaypoint].positions[j],
00283 velPerCent(jt.points[iWaypoint].velocities[j]));
00284 }
00285
00286
00287
00288
00289 return robot.moveArm(pt);
00290 }
00291
00292 void ASFollowTrajectory::monitorMove(JointTrajectory &jt, ssize_t iWaypoint)
00293 {
00294 HekRobot &robot(node_.getRobot());
00295 HekJointStatePoint jointCurState;
00296 string jointName;
00297 double jointWpPos;
00298 double jointWpVel;
00299 double jointCurPos;
00300 double jointCurVel;
00301 double jointDistPos;
00302 double jointDistVel;
00303 double waypointDist;
00304 size_t j;
00305
00306 robot.getJointState(jointCurState);
00307
00308 m_fWaypointDist = 1000.0;
00309 waypointDist = 0.0;
00310
00311 feedback_.joint_names.clear();
00312 feedback_.desired.positions.clear();
00313 feedback_.desired.velocities.clear();
00314 feedback_.desired.accelerations.clear();
00315 feedback_.actual.positions.clear();
00316 feedback_.actual.velocities.clear();
00317 feedback_.actual.accelerations.clear();
00318 feedback_.error.positions.clear();
00319 feedback_.error.velocities.clear();
00320 feedback_.error.accelerations.clear();
00321
00322
00323
00324
00325
00326
00327
00328
00329 for(j=0; j<jt.joint_names.size(); ++j)
00330 {
00331 jointName = jt.joint_names[j];
00332 jointWpPos = jt.points[iWaypoint].positions[j];
00333 jointWpVel = jt.points[iWaypoint].velocities[j];
00334
00335 if( jointCurState.hasJoint(jointName) )
00336 {
00337 jointCurPos = jointCurState[jointName].m_fPosition;
00338 jointCurVel = jointCurState[jointName].m_fVelocity;
00339
00340 jointDistPos = fabs(jointWpPos - jointCurPos);
00341 jointDistVel = jointWpVel - jointCurVel;
00342
00343 if( jointDistPos > waypointDist )
00344 {
00345 waypointDist = jointDistPos;
00346 }
00347
00348 }
00349 else
00350 {
00351 jointDistPos = 0.0;
00352 jointDistVel = 0.0;
00353 }
00354
00355
00356 feedback_.joint_names.push_back(jointName);
00357 feedback_.desired.positions.push_back(jointWpPos);
00358 feedback_.desired.velocities.push_back(jointWpVel);
00359 feedback_.desired.accelerations.push_back(0.0);
00360 feedback_.actual.positions.push_back(jointCurPos);
00361 feedback_.actual.velocities.push_back(jointCurVel);
00362 feedback_.actual.accelerations.push_back(0.0);
00363 feedback_.error.positions.push_back(jointDistPos);
00364 feedback_.error.velocities.push_back(jointDistVel);
00365 feedback_.error.accelerations.push_back(0.0);
00366 }
00367
00368 publishFeedback(iWaypoint);
00369
00370 m_fWaypointDist = waypointDist;
00371
00372 ++m_iterMonitor;
00373
00374
00375 ROS_INFO("Monitoring waypoint %zd: iter=%d, dist=%lf\n",
00376 iWaypoint, m_iterMonitor, m_fWaypointDist);
00377 }
00378
00379 bool ASFollowTrajectory::failedWaypoint(JointTrajectory &jt, ssize_t iWaypoint)
00380 {
00381 HekRobot &robot(node_.getRobot());
00382
00383 if( robot.isEStopped() || robot.isAlarmed() || !robot.areServosPowered() )
00384 {
00385 return true;
00386 }
00387
00388 else if( atWaypoint(jt, iWaypoint) )
00389 {
00390 return false;
00391 }
00392
00393 else if( (m_iterMonitor > MaxIters) && !robot.isInMotion() )
00394 {
00395 return true;
00396 }
00397
00398 else
00399 {
00400 return false;
00401 }
00402 }
00403
00404 void ASFollowTrajectory::publishFeedback(ssize_t iWaypoint)
00405 {
00406 stringstream ss;
00407
00408 ss << iWaypoint;
00409
00410
00411
00412
00413 feedback_.header.stamp = ros::Time::now();
00414 feedback_.header.frame_id = ss.str();
00415 feedback_.header.seq++;
00416
00417 as_.publishFeedback(feedback_);
00418 }
00419
00420 void ASFollowTrajectory::preempt_cb()
00421 {
00422 ROS_INFO("%s: Preempt trajectory following.", action_name_.c_str());
00423 node_.getRobot().freeze();
00424 }