【MoveIt2】MoveItCpp Tutorial

本文详细介绍了MoveItCpp高级接口,展示了如何在MoveIt2环境中使用C++ API进行实时控制和规划,包括设置起始状态、目标位姿、规划示例及与RViz的交互。适合寻求更高效控制的开发者和工业应用。

Introduction

MoveItCpp 是一个新的高级接口,一个统一的 C++ API,不需要使用 ROS 动作、服务和消息来访问核心 MoveIt 功能,并且是现有 MoveGroup API 的替代(不是完全替代),我们推荐此接口适用于需要更多实时控制的高级用户或工业应用。该接口是 PickNik Robotics 为我们的许多商业应用程序开发的

图片

按照官方步骤编译的moveit2_tutorials并没有编译该demo。所以需要修改一下才能启动该demo.

第一步:修改CMakeLists.txt 

打开:/home/cxy/ws_moveit2/src/moveit2_tutorials/CMakeLists.txt 添加一行:

add_subdirectory(doc/moveit_cpp)

第二步:构建

source ~/ws_moveit2/install/setup.bash

colcon build --mixin release --packages-select moveit2_tutorials

. install/setup.bash

图片

第三步:修改launch文件

        #prefix="xterm -e",

        prefix="gnome-terminal -x",

 

图片

第四步:运行demo

ros2 launch moveit2_tutorials moveit_cpp_tutorial.launch.py

源码:

#include <rclcpp/rclcpp.hpp>
#include <memory>
// MoveitCpp
#include <moveit/moveit_cpp/moveit_cpp.h>
#include <moveit/moveit_cpp/planning_component.h>

#include <geometry_msgs/msg/point_stamped.h>

#include <moveit_visual_tools/moveit_visual_tools.h>

namespace rvt = rviz_visual_tools;

// All source files that use ROS logging should define a file-specific
// static const rclcpp::Logger named LOGGER, located at the top of the file
// and inside the namespace with the narrowest scope (if there is one)
// 所有使用 ROS 日志记录的源文件都应该定义一个特定于文件的静态 const rclcpp::Logger 名为 LOGGER,位于文件顶部和范围最窄的命名空间内(如果有的话)
static const rclcpp::Logger LOGGER = rclcpp::get_logger("moveit_cpp_tutorial");

int main(int argc, char** argv)
{
  rclcpp::init(argc, argv);
  rclcpp::NodeOptions node_options;//声明节点选项
  RCLCPP_INFO(LOGGER, "Initialize node");

  // This enables loading undeclared parameters
  // best practice would be to declare parameters in the corresponding classes
  // and provide descriptions about expected use
  //这允许加载未声明的参数最佳实践是在相应的类中声明参数并提供有关预期用途的描述
  node_options.automatically_declare_parameters_from_overrides(true);//节点选项
  rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("run_moveit_cpp", "", node_options);//创建节点

  // We spin up a SingleThreadedExecutor for the current state monitor to get information
  // about the robot's state.我们为当前状态监视器启动一个 SingleThreadexecutor 以获取有关机器人状态的信息。
  rclcpp::executors::SingleThreadedExecutor executor;//初始化执行器    单线程执行器
  executor.add_node(node);//将要实时控制的节点添加到Executor  Executor 不维护对节点的强引用(只是一个weak_ptr,所以shared_ptr 计数不会增加)
  std::thread([&executor]() { executor.spin(); }).detach();//spin直到 rclcpp::ok() 返回 false

  // 开始教程
  //
  // 设置
  // ^^^^^
  //
  static const std::string PLANNING_GROUP = "panda_arm";//规划组名称
  static const std::string LOGNAME = "moveit_cpp_tutorial";//日志记录器名称

  /* Otherwise robot with zeros joint_states */
  rclcpp::sleep_for(std::chrono::seconds(1));//等1秒,否则机器人处于关节零位状态

  RCLCPP_INFO(LOGGER, "Starting MoveIt Tutorials...");

  auto moveit_cpp_ptr = std::make_shared<moveit_cpp::MoveItCpp>(node);//创建 moveit_cpp::MoveItCpp 对象实例的共享指针
  moveit_cpp_ptr->getPlanningSceneMonitor()->providePlanningSceneService();//规划场景监视器 提供规划场景服务

  auto planning_components = std::make_shared<moveit_cpp::PlanningComponent>(PLANNING_GROUP, moveit_cpp_ptr);//创建 moveit_cpp::PlanningComponent 对象实例的 共享指针
  auto robot_model_ptr = moveit_cpp_ptr->getRobotModel();//获取机器人模型指针
  auto robot_start_state = planning_components->getStartState();//获取起始状态指针
  auto joint_model_group_ptr = robot_model_ptr->getJointModelGroup(PLANNING_GROUP);//获取规划组的机器人模型组指针

  // 可视化
  // ^^^^^^^^^^^^^
  //
  // The package MoveItVisualTools provides many capabilties for visualizing objects, robots,
  // and trajectories in RViz as well as debugging tools such as step-by-step introspection of a script
  // MoveItVisualTools 包提供了许多功能,用于在 RViz 中可视化对象、机器人和轨迹以及调试工具,例如脚本的逐步内省
  moveit_visual_tools::MoveItVisualTools visual_tools(node, "panda_link0", "moveit_cpp_tutorial",
                                                      moveit_cpp_ptr->getPlanningSceneMonitor());//初始化moveit 可视化工具
  visual_tools.deleteAllMarkers();//删除所有标记
  visual_tools.loadRemoteControl();//加载远程控件

  Eigen::Isometry3d text_pose = Eigen::Isometry3d::Identity();//文本位姿矩阵
  text_pose.translation().z() = 1.75;//文本位置z
  visual_tools.publishText(text_pose, "MoveItCpp_Demo", rvt::WHITE, rvt::XLARGE);//发布文本:位姿,文字,颜色,尺寸
  visual_tools.trigger();//触发显示更新

  // 开始演示
  // ^^^^^^^^^^^^^^^^^^^^^^^^^
  visual_tools.prompt("Press 'next' in the RvizVisualToolsGui window to start the demo");// 提示

  // 使用 MoveItCpp 进行规划
  // ^^^^^^^^^^^^^^^^^^^^^^^
  // 有多种方法可以设置规划的开始和目标状态
  // 它们在以下规划示例中进行了说明 
  //
  // Plan #1
  // ^^^^^^^
  // 
  // We can set the start state of the plan to the current state of the robot
  planning_components->setStartStateToCurrentState();//将规划的开始状态设置为机器人的当前状态

  // The first way to set the goal of the plan is by using geometry_msgs::PoseStamped ROS message type as follow
  //设置规划目标的第一种方法是使用 geometry_msgs::PoseStamped ROS 消息类型如下
  geometry_msgs::msg::PoseStamped target_pose1;//目标位姿1
  target_pose1.header.frame_id = "panda_link0";//父坐标系
  target_pose1.pose.orientation.w = 1.0;//四元数
  target_pose1.pose.position.x = 0.28;//位置
  target_pose1.pose.position.y = -0.2;
  target_pose1.pose.position.z = 0.5;
  planning_components->setGoal(target_pose1, "panda_link8");//设置目标位姿1

  // 现在,我们调用 PlanningComponents 来计算规划并将其可视化。
  //请注意,我们只是在规划
  auto plan_solution1 = planning_components->plan();//执行规划

  // 检查 PlanningComponents 是否成功找到了规划
  if (plan_solution1)
  {
    // 在 Rviz 中可视化起始位姿
    visual_tools.publishAxisLabeled(robot_start_state->getGlobalLinkTransform("panda_link8"), "start_pose");
    // 在 Rviz 中可视化目标位姿
    visual_tools.publishAxisLabeled(target_pose1.pose, "target_pose");
    visual_tools.publishText(text_pose, "setStartStateToCurrentState", rvt::WHITE, rvt::XLARGE);//显示文本:设置起始状态为当前状态
    //在 Rviz 中可视化轨迹
    visual_tools.publishTrajectoryLine(plan_solution1.trajectory, joint_model_group_ptr);//显示轨迹
    visual_tools.trigger();//触发显示更新

    /* 如果要执行规划,取消注释 */
    /* planning_components->execute(); // 执行规划*/
  }

  // Plan #1 visualization可视化:
  //截图
  // .. image:: images/moveitcpp_plan1.png
  //    :width: 250pt
  //    :align: center
  //
  // 开始下一个规划
  visual_tools.prompt("Press 'next' in the RvizVisualToolsGui window to continue the demo");//提示
  visual_tools.deleteAllMarkers();//删除所有标记 
  visual_tools.trigger();//触发更新显示

  // Plan #2
  // ^^^^^^^
  //这里我们将使用 moveit::core::RobotState 设置规划的当前状态
  // Here we will set the current state of the plan using
  // moveit::core::RobotState
  auto start_state = *(moveit_cpp_ptr->getCurrentState());//获取当前状态指针
  geometry_msgs::msg::Pose start_pose;//起始位姿
  start_pose.orientation.w = 1.0;//姿态四元数
  start_pose.position.x = 0.55;//位置
  start_pose.position.y = 0.0;
  start_pose.position.z = 0.6;

  start_state.setFromIK(joint_model_group_ptr, start_pose);//设置起始位姿对应的状态为当前起始状态的值

  planning_components->setStartState(start_state);//更新起始状态设置

  //我们将重用我们已有的旧目标并规划实现它。
  auto plan_solution2 = planning_components->plan();
  if (plan_solution2)
  {//规划成功
    moveit::core::RobotState robot_state(robot_model_ptr);//机器人状态 
    moveit::core::robotStateMsgToRobotState(plan_solution2.start_state, robot_state);//机器人状态消息 转换为 机器人状态 

    visual_tools.publishAxisLabeled(robot_state.getGlobalLinkTransform("panda_link8"), "start_pose");//显示起始位姿框架及标签
    visual_tools.publishAxisLabeled(target_pose1.pose, "target_pose");//显示目标位姿及标签 
    visual_tools.publishText(text_pose, "moveit::core::RobotState_Start_State", rvt::WHITE, rvt::XLARGE);//显示文本
    visual_tools.publishTrajectoryLine(plan_solution2.trajectory, joint_model_group_ptr);
    visual_tools.trigger();

    /* 如果要执行规划,取消注释 */
    /* planning_components->execute(); // 执行规划*/
  }

  // Plan #2 visualization:
  //截图
  // .. image:: images/moveitcpp_plan2.png
  //    :width: 250pt
  //    :align: center
  //
  // Start the next plan
  visual_tools.prompt("Press 'next' in the RvizVisualToolsGui window to continue the demo");//提示 
  visual_tools.deleteAllMarkers();//删除标记 
  visual_tools.trigger();//触发更新

  // Plan #3
  // ^^^^^^^
  //我们还可以使用 moveit::core::RobotState 设置规划的目标
  // We can also set the goal of the plan using
  // moveit::core::RobotState
  auto target_state = *robot_start_state;//机器人起始状态指针
  geometry_msgs::msg::Pose target_pose2;//机器人目标位姿
  target_pose2.orientation.w = 1.0;
  target_pose2.position.x = 0.55;
  target_pose2.position.y = -0.05;
  target_pose2.position.z = 0.8;

  target_state.setFromIK(joint_model_group_ptr, target_pose2);//根据目标位姿设置目标状态值

  planning_components->setGoal(target_state);//将目标状态值更新到目标

  // 我们将重用我们拥有的旧起始位姿并从中进行规划。
  auto plan_solution3 = planning_components->plan();
  if (plan_solution3)//规划成功
  {
    moveit::core::RobotState robot_state(robot_model_ptr);//声明一个机器人状态对象
    moveit::core::robotStateMsgToRobotState(plan_solution3.start_state, robot_state);//用规划结果中的起始状态消息 初始化机器人状态对象

    visual_tools.publishAxisLabeled(robot_state.getGlobalLinkTransform("panda_link8"), "start_pose");//显示机器人起始位姿及标签
    visual_tools.publishAxisLabeled(target_pose2, "target_pose");//显示机器人目标位姿及标签
    visual_tools.publishText(text_pose, "moveit::core::RobotState_Goal_Pose", rvt::WHITE, rvt::XLARGE);//显示文本标题 
    visual_tools.publishTrajectoryLine(plan_solution3.trajectory, joint_model_group_ptr);//显示轨迹 
    visual_tools.trigger();//触发显示

    /* 如果要执行规划,取消注释*/
    /* planning_components->execute(); // 执行规划 */
  }

  // Plan #3 visualization:
  //截图
  // .. image:: images/moveitcpp_plan3.png
  //    :width: 250pt
  //    :align: center
  //
  // Start the next plan
  visual_tools.prompt("Press 'next' in the RvizVisualToolsGui window to continue the demo");//提示 
  visual_tools.deleteAllMarkers();//删除标记 
  visual_tools.trigger();//触发更新

  // Plan #4
  // ^^^^^^^
  //
  // We can set the start state of the plan to the current state of the robot
  // We can set the goal of the plan using the name of a group states
  // for panda robot we have one named robot state for "panda_arm" planning group called "ready"
  // see `panda_arm.xacro
  //我们可以将规划的开始状态设置为机器人的当前状态
  //我们可以使用组状态的名称来设定规划的目标
  //对于panda机器人,我们有一个名为“panda_arm”规划组的名为“ready”的机器人状态,参见`panda_arm.xacro
  // <https://github.com/ros-planning/panda_moveit_config/blob/melodic-devel/config/panda_arm.xacro#L13>`_

  /* //从命名机器人状态设置规划的开始状态 */
  /* planning_components->setStartState("ready"); // 尚未实施 */
  // 从命名的机器人状态设置规划的目标状态Set the goal state of the plan from a named robot state
  planning_components->setGoal("ready");

  // 我们将再次重用我们拥有的旧起始位姿并从中进行规划。
  auto plan_solution4 = planning_components->plan();
  if (plan_solution4)
  {
    moveit::core::RobotState robot_state(robot_model_ptr);
    moveit::core::robotStateMsgToRobotState(plan_solution4.start_state, robot_state);

    visual_tools.publishAxisLabeled(robot_state.getGlobalLinkTransform("panda_link8"), "start_pose");
    visual_tools.publishAxisLabeled(robot_start_state->getGlobalLinkTransform("panda_link8"), "target_pose");
    visual_tools.publishText(text_pose, "Goal_Pose_From_Named_State", rvt::WHITE, rvt::XLARGE);
    visual_tools.publishTrajectoryLine(plan_solution4.trajectory, joint_model_group_ptr);
    visual_tools.trigger();

    /* Uncomment if you want to execute the plan */
    /* planning_components->execute(); // Execute the plan */
  }

  // Plan #4 visualization:
  //
  // .. image:: images/moveitcpp_plan4.png
  //    :width: 250pt
  //    :align: center
  //
  // Start the next plan
  visual_tools.prompt("Press 'next' in the RvizVisualToolsGui window to continue the demo");
  visual_tools.deleteAllMarkers();
  visual_tools.trigger();

  // Plan #5
  // ^^^^^^^
  //
  // We can also generate motion plans around objects in the collision scene.
  //我们还可以围绕碰撞场景中的对象生成运动规划。
  // First we create the collision object首先我们创建碰撞对象
  moveit_msgs::msg::CollisionObject collision_object;//声明 碰撞对象消息
  collision_object.header.frame_id = "panda_link0";//碰撞对向的父坐标系 ID
  collision_object.id = "box";//碰撞对象的ID

  shape_msgs::msg::SolidPrimitive box;//图元box
  box.type = box.BOX;//设置图元的类型 BOX
  box.dimensions = { 0.1, 0.4, 0.1 }; //尺寸 

  geometry_msgs::msg::Pose box_pose;//位姿
  box_pose.position.x = 0.4;
  box_pose.position.y = 0.0;
  box_pose.position.z = 1.0;

  collision_object.primitives.push_back(box);//将图元box添加到碰撞对象的图元集合
  collision_object.primitive_poses.push_back(box_pose);//将box位姿添加到碰撞对向的图元位姿集合
  collision_object.operation = collision_object.ADD;//碰撞对向的操作: ADD 

  // 将对象添加到规划场景
  {  // 锁定规划场景
    planning_scene_monitor::LockedPlanningSceneRW scene(moveit_cpp_ptr->getPlanningSceneMonitor());//获取规划场景监视器
    scene->processCollisionObjectMsg(collision_object);//监视器处理碰撞对象消息
  }  // 解锁规划场景
  planning_components->setStartStateToCurrentState();//设置起始状态为当前状态 
  planning_components->setGoal("extended");//设置目标 

  auto plan_solution5 = planning_components->plan();//执行规划 
  if (plan_solution5)
  {//规划成功
    visual_tools.publishText(text_pose, "Planning_Around_Collision_Object", rvt::WHITE, rvt::XLARGE);//显示文本 
    visual_tools.publishTrajectoryLine(plan_solution5.trajectory, joint_model_group_ptr);//显示轨迹 
    visual_tools.trigger();//触发更新

    /* 如果要执行规划,取消注释*/
    /* planning_components->execute(); // 执行规划 */
  }

  // Plan #5 visualization:
  //
  // .. image:: images/moveitcpp_plan5.png
  //    :width: 250pt
  //    :align: center
  //
  // END_TUTORIAL
  visual_tools.prompt("Press 'next' to end the demo");//提示 
  visual_tools.deleteAllMarkers();//删除所有标记
  visual_tools.trigger();//触发更新 

  RCLCPP_INFO(LOGGER, "Shutting down.");
  rclcpp::shutdown();
  return 0;
}

 

原文:【MoveIt2】MoveItCpp Tutorial

 

03-08
### MoveIt2 安装配置教程及常见问题解决 #### 一、MoveIt2 概述 MoveIt 是一个用于机器人运动规划的强大框架,广泛应用于工业和服务机器人领域。随着ROS 2的发展,MoveIt也升级到了MoveIt2版本,在ROS 2环境中提供了更强大的功能和支持[^1]。 #### 二、安装准备工作 为了顺利安装MoveIt2,需先完成一些前置条件的设置: - **环境准备**:确保已安装Ubuntu操作系统以及对应的ROS 2发行版(如Foxy Fitzroy)。对于特定的操作系统和ROS版本组合,请参照官方文档确认兼容性。 - **依赖项安装**:通过命令行工具`apt-get update && apt-get install ros-$ROS_DISTRO-moveit`来获取必要的依赖库和其他组件。 #### 三、安装MoveIt2源码并构建工作空间 按照如下步骤操作可以将最新的MoveIt2源码克隆到本地,并建立相应的工作目录结构以便后续开发: 1. 创建一个新的ROS 2工作区: ```bash mkdir -p ~/ws_moveit2/src cd ~/ws_moveit2/ ``` 2. 下载MoveIt2仓库中的最新代码: ```bash vcs import src < https://raw.githubusercontent.com/ros-planning/moveit2/main/dependencies.repos git clone --branch main https://github.com/ros-planning/moveit2.git src/moveit2 ``` 3. 更新子模块并初始化: ```bash cd src/moveit2 git submodule update --init --recursive cd .. ``` 4. 构建整个项目: ```bash colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release source install/setup.bash ``` #### 四、验证安装成果 启动RViz可视化界面测试是否能正常加载MoveIt2插件及相关资源文件: ```bash ros2 launch moveit2_examples demo.launch.py ``` 如果一切正常,则可以在图形界面上看到机器人的模型及其周围的空间障碍物表示形式。 #### 常见问题解答 当尝试运行上述过程时可能会遇到各种各样的挑战,下面列举了一些常见的错误提示及其解决方案: - 如果收到关于找不到某些包的信息,这通常意味着还需要额外安装其他依赖关系;可以通过搜索具体的报错信息找到相应的APT包名来进行补充安装。 - 对于编译失败的情况,建议仔细检查CMakeLists.txt文件内的路径定义是否有误,同时注意不同平台间可能存在差异化的编译参数需求。 - 当无法连接至互联网从而影响git拉取速度甚至失败时,考虑更换国内镜像站点加速下载效率。 ```cpp // 示例:创建简单的MoveIt!节点 #include <moveit/move_group_interface/move_group_interface.h> int main(int argc, char **argv){ rclcpp::init(argc, argv); auto const node = std::make_shared<rclcpp::Node>("hello_moveit"); // 初始化MoveGroup接口实例... } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值