-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Slow control loop with dwa_local_planner (melodic) #956
base: melodic-devel
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,6 +99,7 @@ namespace base_local_planner { | |
const geometry_msgs::PoseStamped& global_pose, | ||
const costmap_2d::Costmap2D& costmap, | ||
const std::string& global_frame, | ||
const ros::Time& time, | ||
std::vector<geometry_msgs::PoseStamped>& transformed_plan){ | ||
transformed_plan.clear(); | ||
|
||
|
@@ -110,8 +111,7 @@ namespace base_local_planner { | |
const geometry_msgs::PoseStamped& plan_pose = global_plan[0]; | ||
try { | ||
// get plan_to_global_transform from plan frame to global_frame | ||
geometry_msgs::TransformStamped plan_to_global_transform = tf.lookupTransform(global_frame, ros::Time(), | ||
plan_pose.header.frame_id, plan_pose.header.stamp, plan_pose.header.frame_id, ros::Duration(0.5)); | ||
geometry_msgs::TransformStamped plan_to_global_transform = tf.lookupTransform(global_frame, plan_pose.header.frame_id, time, ros::Duration(0.5)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here, it seems the correct thing to use is not a passed in time, but rather the timestamp of global_pose (which will usually have just been determined by a call to getRobotPose(). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree, it'll be more consistent, though global_pose's timestamp can be quite in the past (tens of ms). |
||
|
||
//let's get the pose of the robot in the frame of the plan | ||
geometry_msgs::PoseStamped robot_pose; | ||
|
@@ -173,7 +173,7 @@ namespace base_local_planner { | |
|
||
bool getGoalPose(const tf2_ros::Buffer& tf, | ||
const std::vector<geometry_msgs::PoseStamped>& global_plan, | ||
const std::string& global_frame, geometry_msgs::PoseStamped &goal_pose) { | ||
const std::string& global_frame, const ros::Time& time, geometry_msgs::PoseStamped &goal_pose) { | ||
if (global_plan.empty()) | ||
{ | ||
ROS_ERROR("Received plan with zero length"); | ||
|
@@ -182,9 +182,7 @@ namespace base_local_planner { | |
|
||
const geometry_msgs::PoseStamped& plan_goal_pose = global_plan.back(); | ||
try{ | ||
geometry_msgs::TransformStamped transform = tf.lookupTransform(global_frame, ros::Time(), | ||
plan_goal_pose.header.frame_id, plan_goal_pose.header.stamp, | ||
plan_goal_pose.header.frame_id, ros::Duration(0.5)); | ||
geometry_msgs::TransformStamped transform = tf.lookupTransform(global_frame, plan_goal_pose.header.frame_id, time, ros::Duration(0.5)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is ros::Time() a problem here? that should simply give us the latest transform - we don't even appear to be ever using the timestamp of the goal_pose returned, so? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't use the timestamp of returned goal_pose, but the timestamp is used to define transformation itself. And it's better to be consistent with the rest of computations. That is why I still propose to pass timestamp here and pass robot's pose timestamp (in LatchedStopRotateController). |
||
|
||
tf2::doTransform(plan_goal_pose, goal_pose, transform); | ||
} | ||
|
@@ -210,14 +208,15 @@ namespace base_local_planner { | |
const std::vector<geometry_msgs::PoseStamped>& global_plan, | ||
const costmap_2d::Costmap2D& costmap GOAL_ATTRIBUTE_UNUSED, | ||
const std::string& global_frame, | ||
const ros::Time& time, | ||
geometry_msgs::PoseStamped& global_pose, | ||
const nav_msgs::Odometry& base_odom, | ||
double rot_stopped_vel, double trans_stopped_vel, | ||
double xy_goal_tolerance, double yaw_goal_tolerance){ | ||
|
||
//we assume the global goal is the last point in the global plan | ||
geometry_msgs::PoseStamped goal_pose; | ||
getGoalPose(tf, global_plan, global_frame, goal_pose); | ||
getGoalPose(tf, global_plan, global_frame, time, goal_pose); | ||
|
||
double goal_x = goal_pose.pose.position.x; | ||
double goal_y = goal_pose.pose.position.y; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -406,7 +406,7 @@ namespace base_local_planner { | |
|
||
std::vector<geometry_msgs::PoseStamped> transformed_plan; | ||
//get the global plan in our frame | ||
if (!transformGlobalPlan(*tf_, global_plan_, global_pose, *costmap_, global_frame_, transformed_plan)) { | ||
if (!transformGlobalPlan(*tf_, global_plan_, global_pose, *costmap_, global_frame_, ros::Time::now(), transformed_plan)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and here, now() is later than the stamp we just got on the global_pose, so again, it would seem that approach would be reasonable. |
||
ROS_WARN("Could not transform the global plan to the frame of the controller"); | ||
return false; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -161,6 +161,15 @@ namespace dwa_local_planner { | |
return false; | ||
} | ||
|
||
// Set current time that will be used by LocalPlannerUtil for TF extraction | ||
// during current move_base control loop cycle. | ||
// If not set, LocalPlannerUtil will wait for TF transform each time | ||
// getGoal or getLocalPlan is called incurring multiple delays. | ||
// Current robot pose must be obtained prior to this (and not updated later) | ||
// to avoid possible TF extrapolation error, | ||
// as getLocalPlan will also try to transform at its time stamp. | ||
planner_util_.setTime(ros::Time::now()); | ||
|
||
if(latchedStopRotateController_.isGoalReached(&planner_util_, odom_helper_, current_pose_)) { | ||
ROS_INFO("Goal reached"); | ||
return true; | ||
|
@@ -263,10 +272,6 @@ namespace dwa_local_planner { | |
|
||
bool DWAPlannerROS::computeVelocityCommands(geometry_msgs::Twist& cmd_vel) { | ||
// dispatches to either dwa sampling control or stop and rotate control, depending on whether we have been close enough to goal | ||
if ( ! costmap_ros_->getRobotPose(current_pose_)) { | ||
ROS_ERROR("Could not get robot pose"); | ||
return false; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. while we currently call isGoalReached() right before computeVelocityCommands(), I really don't think we want to make this API harder to use -- using the timestamp of the current_pose_ rather than an extra timestamp allows this to stay and avoids extra bookkeeping. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree. |
||
std::vector<geometry_msgs::PoseStamped> transformed_plan; | ||
if ( ! planner_util_.getLocalPlan(current_pose_, transformed_plan)) { | ||
ROS_ERROR("Could not get local plan"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've spent quite a bit of time looking at this now - I really don't like littering extra params all over, and having all this book-keeping going on as to what time we are using for things (it seems like this will be very easy to use incorrectly).