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

Add function to set the initial pose from RVIZ for pure localization mode #1284

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

tongtybj
Copy link

As mentioned in the closed PR #637, manually "tuning" of the robot initial pose from GUI (e.g. Rviz) is a very important function for home service robot, which is supported by the ROS default localization method AMCL.

I hope this PR can facilitate the development of this RFC.

To test my commit, please try following commands

  1. First follow the tutorial about pure localization to download rosbags and build the map (.pbstream).
  2. Then run following command instead:
$ roslaunch cartographer_ros demo_backpack_2d_localization.launch \
   load_state_filename:=${HOME}/Downloads/b3-2016-04-05-13-54-42.bag.pbstream \
   rosbag:=false
  1. Use the icon 2D Pose Estimation in Rviz to set the initial pose as shown in following image.
    Screenshot from 2019-05-12 19-06-45

  2. Play the rosbag:

$ rosbag play ${HOME}/Downloads/b2-2016-04-27-12-31-41.bag --clock -s 320

The whole sequence can be found in this video, and you can also try the 3D mode in this same way.

We have confirmed the 3D performance with our original data, please check this video.

Limitations: the multi-floor map is not supported, since we can not assign the height (i.e. z value) from Rviz.

@faizansid77
Copy link

I got the following error while I built your code

FAILED: /usr/bin/c++   -DROSCONSOLE_BACKEND_LOG4CXX -DROS_PACKAGE_NAME=\"cartographer_ros\" -I/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/cartographer_ros -isystem /usr/include/lua5.2 -isystem /usr/include/pcl-1.7 -isystem /usr/include/eigen3 -isystem /home/faizansid/catkin_carto/install_isolated/include -isystem /opt/ros/kinetic/include -isystem /opt/ros/kinetic/share/xmlrpcpp/cmake/../../../include/xmlrpcpp -I. -I/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng12 -isystem /usr/local/include -O3 -DNDEBUG    -pthread -std=c++11 -fPIC  -Wall -Wpedantic -Werror=format-security -Werror=missing-braces -Werror=reorder -Werror=return-type -Werror=switch -Werror=uninitialized -O3 -DNDEBUG -MMD -MT cartographer_ros/CMakeFiles/set_initpose_from_rviz.dir/set_initpose_main.cc.o -MF cartographer_ros/CMakeFiles/set_initpose_from_rviz.dir/set_initpose_main.cc.o.d -o cartographer_ros/CMakeFiles/set_initpose_from_rviz.dir/set_initpose_main.cc.o -c /home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc
/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc: In function ‘void move_base_simple_callback(const ConstPtr&)’:
/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc:123:32: error: ‘cartographer_ros_msgs::StartTrajectory::Request {aka struct cartographer_ros_msgs::StartTrajectoryRequest_<std::allocator<void> >}’ has no member named ‘configuration_directory’
   srv_start_trajectory.request.configuration_directory =
                                ^
/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc:125:32: error: ‘cartographer_ros_msgs::StartTrajectory::Request {aka struct cartographer_ros_msgs::StartTrajectoryRequest_<std::allocator<void> >}’ has no member named ‘configuration_basename’
   srv_start_trajectory.request.configuration_basename =
                                ^
/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc:128:32: error: ‘cartographer_ros_msgs::StartTrajectory::Request {aka struct cartographer_ros_msgs::StartTrajectoryRequest_<std::allocator<void> >}’ has no member named ‘relative_to_trajectory_id’
   srv_start_trajectory.request.relative_to_trajectory_id =
                                ^
/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc:130:32: error: ‘cartographer_ros_msgs::StartTrajectory::Request {aka struct cartographer_ros_msgs::StartTrajectoryRequest_<std::allocator<void> >}’ has no member named ‘use_initial_pose’
   srv_start_trajectory.request.use_initial_pose = true;
                                ^
/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc:131:65: error: ‘cartographer_ros_msgs::StartTrajectory::Request {aka struct cartographer_ros_msgs::StartTrajectoryRequest_<std::allocator<void> >}’ has no member named ‘initial_pose’
   tf2::toMsg(relative_initpose_tf, srv_start_trajectory.request.initial_pose);
                                                                 ^
/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc: In function ‘int main(int, char**)’:
/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc:169:18: error: ‘absl’ has not been declared
   map_builder_ = absl::make_unique<cartographer::mapping::MapBuilder>(
                  ^
/home/faizansid/catkin_carto/src/cartographer_ros/cartographer_ros/cartographer_ros/set_initpose_main.cc:169:69: error: expected primary-expression before ‘>’ token
   map_builder_ = absl::make_unique<cartographer::mapping::MapBuilder>(
                                                                     ^

@tongtybj
Copy link
Author

@faizansid77

"cartographer_ros_msgs::StartTrajectory" has been changed by #1245 , and absl::make_unique is introduced by #955 .

Can you tell me the detail about the build condition?

Copy link
Contributor

@MichaelGrupp MichaelGrupp left a comment

Choose a reason for hiding this comment

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

Although I can see that this code is useful for your type of experiments, I don't think this code serves the general use case as it makes a lot of assumptions... For example, a pose sent on the /initialpose topic is not necessarily pure 2D and 3D users probably don't always want the z-component to be automatically set.

But I fear that initial pose handling is something that almost always requires some customization, so I don't think we will find an implementation that is generally useful so it can be integrated into this repository... especially one that supports both 2D and 3D.

P.S.: But maybe it makes sense to help people with implementing their custom initial pose tool by providing a minimal example, e.g. in the documentation?
Because a minimal initial pose handler can be implemented with a few lines of Python or C++ code using the ROS services /get_trajectory_states, /finish_trajectory and /start_trajectory.

"Filename of a pbstream to draw a map from.");

namespace {
int current_trajectory_id_ = 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a hack, and there are numerous possible situations where this would be wrong.

A proper implementation would be to check the trajectory states for an active trajectory. The ROS service for that is /get_trajectory_states.

Copy link
Author

@tongtybj tongtybj Jun 11, 2019

Choose a reason for hiding this comment

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

Thank you for your advice. I have revised based on your comment (f0b35a4)

FLAGS_configuration_directory, FLAGS_configuration_basename);
map_builder_ = absl::make_unique<cartographer::mapping::MapBuilder>(
node_options.map_builder_options);
map_builder_->LoadState(&reader, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you have a map builder? It's not used.

Copy link
Author

Choose a reason for hiding this comment

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

map build is used to get the frozen trajectory information:
https://github.com/googlecartographer/cartographer_ros/blob/5b09b08daf6a6f1f51296f44e11f8c1f5ba48d40/cartographer_ros/cartographer_ros/set_initpose_main.cc#L109

The trajectory information is required here, since the initial pose of the new trajectory should be provided w.r.t the reference trajectory (i.e. the frozen trajectory). Is it right?


// find the best submap, which is closest to the initial pose
// and assign the height (i.e. z value) of this submap to the initial pose
if (delta_pos.length() < min_dist) {
Copy link
Contributor

Choose a reason for hiding this comment

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

oof... this looks like it could have funny side effects in buildings with multiple floors.

Copy link
Author

Choose a reason for hiding this comment

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

I have removed this part (5b09b08)

@tongtybj
Copy link
Author

tongtybj commented Jun 11, 2019

@MichaelGrupp Thank you for your review. I agree that my original implementation is specialized for the 2.5D case. So I improve the code according to your comments.

But, about following comment, I want to discuss further:

Because a minimal initial pose handler can be implemented with a few lines of Python or C++ code using the ROS services /get_trajectory_states, /finish_trajectory and /start_trajectory.

Besides these three services, I think the information about the reference trajectory (i.e. the frozen trajectory) is also necessary, since the initial pose should be provided w.r.t. the reference trajectory; otherwise, users should covert the transformation by themselves (but common robotics users are tend to use simple gui like rviz):
https://github.com/googlecartographer/cartographer_ros/blob/5b09b08daf6a6f1f51296f44e11f8c1f5ba48d40/cartographer_ros/cartographer_ros/set_initpose_main.cc#L109-L124

BTW, calling /finish_trajectory can stop an ongoing trajectory building, but the map would remain. This effects the navigation performance (e.g. move_base) based on the /map topic published by cartographer_occupancy_grid_node. So I think there should be a service to delete the unnecessary trajectory, or is there already some solution?

Copy link

@MUZUIXIAOHAI MUZUIXIAOHAI left a comment

Choose a reason for hiding this comment

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

@wesigj
Copy link

wesigj commented Nov 5, 2020

@tongtybj
have you finish this issue, i want to use 'Add function to set the initial pose from RVIZ for pure localization mode ' this function in my cartographer,but i don't know how to use your function, could you help me?
Thank you for your contributions

@greymfm
Copy link

greymfm commented Jul 4, 2021

Maybe it's more elegant to do the rviz initial pose feature 'outside' Cartographer via a simple Python script? At least that's how I did it :-) #1652

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

Successfully merging this pull request may close these issues.

8 participants