From f29e0252cf4f7330a00a1e96d60d952ddc601b40 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Thu, 6 Jan 2022 09:41:04 -0700 Subject: [PATCH] :sparkles: Your First MoveIt C++ Project Tutorial Signed-off-by: Tyler Weaver --- .../quickstart_in_rviz/launch/demo.launch.py | 4 +- .../quickstart_in_rviz_tutorial.rst | 10 +- doc/tutorials/tutorials.rst | 1 + doc/tutorials/your_first_project/rviz_1.png | Bin 0 -> 13709 bytes doc/tutorials/your_first_project/rviz_2.png | Bin 0 -> 13846 bytes .../your_first_project/your_first_project.rst | 276 ++++++++++++++++++ 6 files changed, 283 insertions(+), 8 deletions(-) create mode 100644 doc/tutorials/your_first_project/rviz_1.png create mode 100644 doc/tutorials/your_first_project/rviz_2.png create mode 100644 doc/tutorials/your_first_project/your_first_project.rst diff --git a/doc/tutorials/quickstart_in_rviz/launch/demo.launch.py b/doc/tutorials/quickstart_in_rviz/launch/demo.launch.py index 7800d5da72..cf03032bc8 100644 --- a/doc/tutorials/quickstart_in_rviz/launch/demo.launch.py +++ b/doc/tutorials/quickstart_in_rviz/launch/demo.launch.py @@ -91,8 +91,10 @@ def generate_launch_description(): } planning_scene_monitor_parameters = { - "publish_planning_scene": True, "publish_geometry_updates": True, + "publish_planning_scene": True, + "publish_robot_description": True, + "publish_robot_description_semantic": True, "publish_state_updates": True, "publish_transforms_updates": True, } diff --git a/doc/tutorials/quickstart_in_rviz/quickstart_in_rviz_tutorial.rst b/doc/tutorials/quickstart_in_rviz/quickstart_in_rviz_tutorial.rst index 0793a92e36..97f6694ac2 100644 --- a/doc/tutorials/quickstart_in_rviz/quickstart_in_rviz_tutorial.rst +++ b/doc/tutorials/quickstart_in_rviz/quickstart_in_rviz_tutorial.rst @@ -232,12 +232,8 @@ Saving Your Configuration +++++++++++++++++++++++++ RViz enables you to save your configuration under ``File->Save Config``. You should do this before continuing on to the next tutorials. -Next Tutorials -++++++++++++++ -* To easily control your robot using C++, check out the :doc:`Move Group C++ Interface ` -* To easily control your robot using Python, check out the :doc:`Move Group Python Interface ` +Next Tutorial ++++++++++++++ -* To create your own ``*_moveit_config`` package, check out the :doc:`Setup Assistant ` - -* Save and restore robot states from a database or from disk using :doc:`warehouse_ros ` +:doc:`/doc/tutorials/your_first_project/your_first_project` diff --git a/doc/tutorials/tutorials.rst b/doc/tutorials/tutorials.rst index afce4c1f3a..dc6fb376d8 100644 --- a/doc/tutorials/tutorials.rst +++ b/doc/tutorials/tutorials.rst @@ -13,3 +13,4 @@ In these tutorials, the Franka Emika Panda robot is used as a quick-start demo. getting_started/getting_started quickstart_in_rviz/quickstart_in_rviz_tutorial + your_first_project/your_first_project diff --git a/doc/tutorials/your_first_project/rviz_1.png b/doc/tutorials/your_first_project/rviz_1.png new file mode 100644 index 0000000000000000000000000000000000000000..19857c246134bd28f35b8e7d84e6e112899b011d GIT binary patch literal 13709 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 U>RGA<|BHnpE2$_^A!ZQxe`. + +This tutorial assumes you understand the basics of ROS 2. +To prepare yourself for this please complete the `Official ROS 2 Tutorials `_ up until "Writing a simple publisher and Subscriber (C++)". + +Steps +----- + +1 Create a package +^^^^^^^^^^^^^^^^^^ + +Open a terminal and `source your ROS 2 installation `_ so that ``ros2`` commands will work. + +Navigate to your ``ws_moveit2`` directory you created in the :doc:`Getting Started Tutorial `. + +Change directory into the ``src`` directory, as that is where we put our source code. + +Create a new package with the ROS 2 command line tools: + +.. code-block:: bash + + ros2 pkg create \ + --build-type ament_cmake \ + --dependencies moveit_ros_planning_interface rclcpp \ + --node-name hello_moveit hello_moveit + +The output of this will show that it created some files in a new directory. + +Note that we added ``moveit_ros_planning_interface`` and ``rclcpp`` as dependencies. +This will create the necessary changes in the ``package.xml`` and ``CMakeLists.txt`` files so that we can depend on these two packages. + +Open the new source file created for you at ``ws_moveit2/src/hello_moveit/src/hello_moveit.cpp`` in your favorite editor. + +2 Create a ROS Node and Executor +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This first bit is a bit of boilerplate but you should be used to seeing this from the ROS 2 tutorials. + +.. code-block:: C++ + + #include + #include + #include + + #include + #include + + int main(int argc, char * argv[]) + { + // Initialize ROS and create the Node + rclcpp::init(argc, argv); + const auto node = std::make_shared( + "hello_moveit", + rclcpp::NodeOptions().automatically_declare_parameters_from_overrides(true) + ); + + // Create a ROS logger + const auto logger = rclcpp::get_logger("hello_moveit"); + + // Create a thread to run to spin a Executor + auto thread = std::thread([node]() { + rclcpp::executors::SingleThreadedExecutor executor; + executor.add_node(node); + executor.spin(); + }); + + // Next step goes here + + // Shutdown ROS and our thread + rclcpp::shutdown(); + thread.join(); + return 0; + } + +2.1 Build and Run +~~~~~~~~~~~~~~~~~ + +We will build and run the program to see that everything is right before we move on. + +Change directory back to the workspace directory ``ws_moveit2`` and run this command: + +.. code-block:: bash + + colcon build --mixin debug + +After this succeeds, **open a new terminal**, then source the workspace environment script in that new terminal so that we can run our program. + +.. code-block:: bash + + source install/setup.bash + +Run your program and see the output. + +.. code-block:: bash + + ros2 run hello_moveit hello_moveit + +You will probably see this error: + +.. code-block:: + + terminate called after throwing an instance of 'rclcpp::exceptions::RCLError' + what(): the given context is not valid, either rcl_init() was not called or rcl_shutdown() was called., at /tmp/binarydeb/ros-rolling-rcl-4.0.0/src/rcl/guard_condition.c:67 + [ros2run]: Aborted + +This is because ``rclcpp::shutdown()`` was called before the Executor finished initializing. +We'll fix that in the next section by adding some code that does something after creating the thread. + +2.2 Examine the code +~~~~~~~~~~~~~~~~~~~~ + +The headers included at the top are just some standard C++ headers and the header for ROS and MoveIt that we will use later. + +After that we have the normal call to initialize rclcpp and then we create our Node. + +.. code-block:: C++ + + const auto node = std::make_shared( + "hello_moveit", + rclcpp::NodeOptions().automatically_declare_parameters_from_overrides(true) + ); + +The first argument is the string that ROS will use to make a unique node. +The second is needed for MoveIt because of how we use ROS Parameters. + +Before we can start use our ROS Node we have to give it to a spinning executor. +This is what will enable ROS to call callbacks to update our Robot State among other things. + +.. code-block:: C++ + + auto thread = std::thread([=]() { + rclcpp::executors::SingleThreadedExecutor executor; + executor.add_node(node); + executor.spin(); + }); + + Lastly we have the calls to shutdown ROS and cleanup our thread. + +3 Plan and Execute using MoveGroupInterface +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After the creation of the thread add this block of code: + +.. code-block:: C++ + + // Create the MoveIt MoveGroup Interface + using moveit::planning_interface::MoveGroupInterface; + auto move_group_interface = MoveGroupInterface(node, "panda_arm"); + + // Set a target Pose + const auto target_pose = []{ + geometry_msgs::msg::Pose msg; + msg.orientation.w = 1.0; + msg.position.x = 0.28; + msg.position.y = -0.2; + msg.position.z = 0.5; + return msg; + }(); + move_group_interface.setPoseTarget(target_pose); + + // Create a plan to that target pose + const auto [success, plan] = [&move_group_interface]{ + moveit::planning_interface::MoveGroupInterface::Plan msg; + const auto ok = static_cast(move_group_interface.plan(msg)); + return std::make_pair(ok, msg); + }(); + + // Execute the plan + if(success) { + move_group_interface.execute(plan); + } else { + RCLCPP_ERROR(logger, "Planing failed!"); + } + +3.1 Build and Run +~~~~~~~~~~~~~~~~~ + +Just like before we need to build the code before we can run it. + +In the workspace directory ``ws_moveit2`` run this command: + +.. code-block:: bash + + colcon build --mixin debug + +After this succeeds, we need to re-use the demo launch file from the previous tutorial to start RViz and the MoveGroup node. +In a separate terminal, source the workspace and then execute this: + +.. code-block:: bash + + ros2 launch moveit2_tutorials demo.launch.py + +Then in the ``Displays`` window under ``MotionPlanning/Planning Request`` uncheck the box ``Query Goal State``. + +.. image:: rviz_1.png + :width: 300px + +In a third terminal source the workspace and run your program. + +.. code-block:: bash + + ros2 run hello_moveit hello_moveit + +This should cause the robot in RViz to move and end up in this pose: + +.. image:: rviz_2.png + :width: 300px + +3.2 Examine the code +~~~~~~~~~~~~~~~~~~~~ + +The first thing we do is create the MoveGroupInterface. +Note that this is the only mutable object (other than the thread) that we create in this program. + +.. code-block:: C++ + + using moveit::planning_interface::MoveGroupInterface; + auto move_group_interface = MoveGroupInterface(node, "panda_arm"); + +Then we set our target pose and plan. + +.. code-block:: C++ + + // Set a target Pose + const auto target_pose = []{ + geometry_msgs::msg::Pose msg; + msg.orientation.w = 1.0; + msg.position.x = 0.28; + msg.position.y = -0.2; + msg.position.z = 0.5; + return msg; + }(); + move_group_interface.setPoseTarget(target_pose); + + // Create a plan to that target pose + const auto [success, plan] = [&move_group_interface]{ + moveit::planning_interface::MoveGroupInterface::Plan msg; + const auto ok = static_cast(move_group_interface.plan(msg)); + return std::make_pair(ok, msg); + }(); + +Finally we execute our plan if planning was successful, otherwise we log an error: + +.. code-block:: C++ + + // Execute the plan + if(success) { + move_group_interface.execute(plan); + } else { + RCLCPP_ERROR(logger, "Planing failed!"); + } + +Summary +------- + +You created a ROS 2 package and wrote your first program using MoveIt. + + +Further Reading +--------------- + +You may have noticed we used lambdas to be able to initialize objects as constants. +This is known as a technique called IIEE. You can read more about this pattern `here at C++ Stories `_. + +Next Step +--------- + +TODO