89 double v1_x = x - pt_x;
90 double v1_y = y - pt_y;
91 double v2_x = cos(heading);
92 double v2_y = sin(heading);
94 double perp_dot = v1_x * v2_y - v1_y * v2_x;
95 double dot = v1_x * v2_x + v1_y * v2_y;
98 double vector_angle = atan2(perp_dot, dot);
100 return -1.0 * vector_angle;
127 geometry_msgs::Twist empty_twist;
128 cmd_vel = empty_twist;
138 ROS_DEBUG(
"HectorPathFollower: current robot pose %f %f ==> %f", robot_pose.getOrigin().x(), robot_pose.getOrigin().y(),
tf::getYaw(robot_pose.getRotation()));
139 ROS_DEBUG(
"HectorPathFollower: target robot pose %f %f ==> %f", target_pose.getOrigin().x(), target_pose.getOrigin().y(),
tf::getYaw(target_pose.getRotation()));
142 geometry_msgs::Twist diff =
diff2D(target_pose, robot_pose);
143 ROS_DEBUG(
"HectorPathFollower: diff %f %f ==> %f", diff.linear.x, diff.linear.y, diff.angular.z);
145 geometry_msgs::Twist limit_vel =
limitTwist(diff);
147 geometry_msgs::Twist test_vel = limit_vel;
148 bool legal_traj =
true;
150 double scaling_factor = 1.0;
151 double ds = scaling_factor /
samples_;
156 test_vel.linear.x = limit_vel.linear.x * scaling_factor;
157 test_vel.linear.y = limit_vel.linear.y * scaling_factor;
158 test_vel.angular.z = limit_vel.angular.z * scaling_factor;
164 scaling_factor -= ds;
169 ROS_ERROR(
"Not legal (%.2f, %.2f, %.2f)", limit_vel.linear.x, limit_vel.linear.y, limit_vel.angular.z);
170 geometry_msgs::Twist empty_twist;
171 cmd_vel = empty_twist;
178 bool in_goal_position =
false;
187 diff =
diff2D(target_pose, robot_pose);
191 ROS_INFO(
"Reached goal: %d", current_waypoint_);
192 in_goal_position =
true;
198 if(!in_goal_position)
203 geometry_msgs::Twist empty_twist;
204 cmd_vel = empty_twist;
214 ROS_ERROR(
"Could not transform the global plan to the frame of the controller");
232 geometry_msgs::Twist res;
253 if(fabs(neg_yaw_diff) < fabs(yaw_diff)){
254 ROS_DEBUG(
"Negative is better: %.2f", neg_yaw_diff);
255 yaw_diff = neg_yaw_diff;
264 diff = pose2.
inverse() * new_pose;
274 geometry_msgs::Twist res = twist;
283 double lin_overshoot = sqrt(res.linear.x * res.linear.x + res.linear.y * res.linear.y) /
max_vel_lin_;
284 double lin_undershoot =
min_vel_lin_ / sqrt(res.linear.x * res.linear.x + res.linear.y * res.linear.y);
285 if (lin_overshoot > 1.0)
287 res.linear.x /= lin_overshoot;
288 res.linear.y /= lin_overshoot;
292 if(lin_undershoot > 1.0)
294 res.linear.x *= lin_undershoot;
295 res.linear.y *= lin_undershoot;
302 if(sqrt(twist.linear.x * twist.linear.x + twist.linear.y * twist.linear.y) <
in_place_trans_vel_){
308 ROS_DEBUG(
"Angular command %f", res.angular.z);
313 const std::string& global_frame,
314 std::vector<geometry_msgs::PoseStamped>& transformed_plan){
315 const geometry_msgs::PoseStamped& plan_pose = global_plan[0];
317 transformed_plan.clear();
320 if (!global_plan.size() > 0)
322 ROS_ERROR(
"Received plan with zero length");
328 plan_pose.header.frame_id, plan_pose.header.stamp,
329 plan_pose.header.frame_id, transform);
332 geometry_msgs::PoseStamped newer_pose;
334 for(
unsigned int i = 0; i < global_plan.size(); ++i){
335 const geometry_msgs::PoseStamped& pose = global_plan[i];
336 poseStampedMsgToTF(pose, tf_pose);
337 tf_pose.
setData(transform * tf_pose);
338 tf_pose.stamp_ = transform.
stamp_;
339 tf_pose.frame_id_ = global_frame;
340 poseStampedTFToMsg(tf_pose, newer_pose);
342 transformed_plan.push_back(newer_pose);
346 ROS_ERROR(
"No Transform available Error: %s\n", ex.what());
350 ROS_ERROR(
"Connectivity Error: %s\n", ex.what());
354 ROS_ERROR(
"Extrapolation Error: %s\n", ex.what());
355 if (global_plan.size() > 0)
356 ROS_ERROR(
"Global Frame: %s Plan Frame size %d: %s\n", global_frame.c_str(), (
unsigned int)global_plan.size(), global_plan[0].header.frame_id.c_str());
367 global_pose.setIdentity();
369 robot_pose.setIdentity();
379 ROS_ERROR_THROTTLE(1.0,
"No Transform available Error looking up robot pose: %s\n", ex.what());
387 ROS_ERROR_THROTTLE(1.0,
"Extrapolation Error looking up robot pose: %s\n", ex.what());
double min_in_place_vel_th_
unsigned int current_waypoint_
bool setPlan(const std::vector< geometry_msgs::PoseStamped > &global_plan)
std::string p_global_frame_
void setData(const T &input)
static double getYaw(const Quaternion &bt_q)
geometry_msgs::Twist diff2D(const tf::Pose &pose1, const tf::Pose &pose2)
ros::Time goal_reached_time_
tf::TransformListener * tf_
bool getRobotPose(tf::Stamped< tf::Pose > &global_pose) const
TFSIMD_FORCE_INLINE const tfScalar & x() const
double rot_stopped_velocity_
#define ROS_ERROR_THROTTLE(rate,...)
double headingDiff(double pt_x, double pt_y, double x, double y, double heading)
static Quaternion createQuaternionFromYaw(double yaw)
double in_place_trans_vel_
double tolerance_timeout_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
TFSIMD_FORCE_INLINE const tfScalar & y() const
bool transformGlobalPlan(const tf::TransformListener &tf, const std::vector< geometry_msgs::PoseStamped > &global_plan, const std::string &global_frame, std::vector< geometry_msgs::PoseStamped > &transformed_plan)
TFSIMD_FORCE_INLINE tfScalar dot(const Quaternion &q1, const Quaternion &q2)
void initialize(tf::TransformListener *tf)
bool computeVelocityCommands(geometry_msgs::Twist &cmd_vel)
std::vector< geometry_msgs::PoseStamped > global_plan_
static void poseStampedMsgToTF(const geometry_msgs::PoseStamped &msg, Stamped< Pose > &bt)
geometry_msgs::Twist limitTwist(const geometry_msgs::Twist &twist)
double trans_stopped_velocity_
std::string p_robot_base_frame_