Skip to content
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

Open
wants to merge 3 commits into
base: melodic-devel
Choose a base branch
from

Conversation

pavloblindnology
Copy link
Contributor

Fix for #679. Replication of #688 for melodic.

@pavloblindnology
Copy link
Contributor Author

Any updates on this?

Copy link
Contributor

@mikeferguson mikeferguson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've finally spent an appropriate amount of time looking this one (and the kinetic version) over -- I see the issues you're trying to fix, and very much appreciate your attempt to fix them - but I'm really not thrilled with the extra bookkeeping -- I'm convinced there has to be a better/simpler approach. Please let me know what you think of the proposed alternatives.

@@ -102,6 +102,7 @@ namespace base_local_planner {
const geometry_msgs::PoseStamped& global_robot_pose,
const costmap_2d::Costmap2D& costmap,
const std::string& global_frame,
const ros::Time& time,
Copy link
Contributor

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).

@@ -105,8 +106,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));
Copy link
Contributor

Choose a reason for hiding this comment

The 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().

Copy link
Contributor Author

@pavloblindnology pavloblindnology May 22, 2020

Choose a reason for hiding this comment

The 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).

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));
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

@pavloblindnology pavloblindnology May 22, 2020

Choose a reason for hiding this comment

The 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).
And we can define this timestamp argument's default value to be ros::Time() in order not to break other local planners.

@@ -387,7 +387,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)) {
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

if ( ! costmap_ros_->getRobotPose(current_pose_)) {
ROS_ERROR("Could not get robot pose");
return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree.

@pavloblindnology
Copy link
Contributor Author

pavloblindnology commented May 22, 2020

@mikeferguson The whole idea was to keep all transformations done during one local planner cycle consistent. I agree it can be a little bit confusing. I see your point and agree that this consistent time is better to be the latest robot pose's time, though it can be quite in the past (tens of ms). This way we know that we're using the same time when making computations based on both robot's pose and transformed global plan. The only inconsistency left is goal computations, which, if using ros::Time() instead of book-kept time are not tied to robot's pose timestamp. Though goal computations seem less important than transformed plan computations, we still can fix it by passing robot's pose timestamp to LocalPlannerUtil::getGoal and goal_functions::getGoalPose:

bool LocalPlannerUtil::getGoal(geometry_msgs::PoseStamped& goal_pose) {

and
bool getGoalPose(const tf2_ros::Buffer& tf,

BTW, this will be consistent with TrajectoryPlannerROS, which has its transformed_plan and goal timestamps consistent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants