#include <moveit/move_group_interface/move_group_interface.h> // 包含MoveIt的移动组接口
#include <moveit/planning_scene_interface/planning_scene_interface.h> // 包含规划场景接口
#include <moveit_msgs/msg/display_robot_state.hpp> // 包含显示机器人状态的消息
#include <moveit_msgs/msg/display_trajectory.hpp> // 包含显示轨迹的消息
#include <moveit_msgs/msg/attached_collision_object.hpp> // 包含附加碰撞物体的消息
#include <moveit_msgs/msg/collision_object.hpp> // 包含碰撞物体的消息
#include <moveit_visual_tools/moveit_visual_tools.h> // 包含MoveIt可视化工具
// 所有使用ROS日志的源文件应在文件顶部定义一个特定于文件的
// 静态常量rclcpp::Logger,位于命名空间内,范围最窄(如果有的话)
static const rclcpp::Logger LOGGER = rclcpp::get_logger("move_group_demo"); // 创建日志记录器
int main(int argc, char** argv) // 主函数
{
rclcpp::init(argc, argv); // 初始化ROS
rclcpp::NodeOptions node_options; // 创建节点选项
node_options.automatically_declare_parameters_from_overrides(true); // 自动声明参数
auto move_group_node = rclcpp::Node::make_shared("move_group_interface_tutorial", node_options); // 创建共享节点
// 我们为当前状态监视器启动一个单线程执行器,以获取机器人的状态信息
rclcpp::executors::SingleThreadedExecutor executor; // 创建单线程执行器
executor.add_node(move_group_node); // 添加节点到执行器
std::thread([&executor]() { executor.spin(); }).detach(); // 启动执行器线程
// 开始教程
//
// 设置
// ^^^^^
//
// MoveIt在称为“规划组”的关节集上操作,并将它们存储在名为
// ``JointModelGroup``的对象中。 在MoveIt中,“规划组”和“关节模型组”这两个术语可以互换使用。
static const std::string PLANNING_GROUP = "panda_arm"; // 定义规划组名
// :moveit_codedir:`MoveGroupInterface<moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h>`
// 类可以通过想要控制和规划的规划组的名称轻松设置。
moveit::planning_interface::MoveGroupInterface move_group(move_group_node, PLANNING_GROUP); // 创建MoveGroupInterface实例
// 我们将使用
// :moveit_codedir:`PlanningSceneInterface<moveit_ros/planning_interface/planning_scene_interface/include/moveit/planning_scene_interface/planning_scene_interface.h>`
// 类在我们的“虚拟世界”场景中添加和移除碰撞物体
moveit::planning_interface::PlanningSceneInterface planning_scene_interface; // 创建规划场景接口实例
// 原始指针通常用于引用规划组,以提高性能。
const moveit::core::JointModelGroup* joint_model_group = // 获取关节模型组
move_group.getCurrentState()->getJointModelGroup(PLANNING_GROUP); // 获取当前状态的关节模型组
// 可视化
// ^^^^^^^^^^^^^
namespace rvt = rviz_visual_tools; // 命名空间别名
moveit_visual_tools::MoveItVisualTools visual_tools(move_group_node, "panda_link0", "move_group_tutorial",
move_group.getRobotModel()); // 创建可视化工具实例
visual_tools.deleteAllMarkers(); // 删除所有标记
/* 远程控制是一种可以让用户通过按钮和键盘快捷键逐步执行高层脚本的工具 */
visual_tools.loadRemoteControl(); // 加载远程控制
// RViz提供了许多类型的标记,在本演示中我们将使用文本、圆柱体和球体
Eigen::Isometry3d text_pose = Eigen::Isometry3d::Identity(); // 创建文本位置的单位变换
text_pose.translation().z() = 1.0; // 设置文本的Z轴位置
visual_tools.publishText(text_pose, "MoveGroupInterface_Demo", rvt::WHITE, rvt::XLARGE); // 发布文本标记
// 批量发布用于减少大量可视化时发送给RViz的消息数量
visual_tools.trigger(); // 触发可视化工具
// 获取基本信息
// ^^^^^^^^^^^^^^^^^^^^^^^^^
//
// 我们可以打印出该机器人的参考框架名称。
RCLCPP_INFO(LOGGER, "Planning frame: %s", move_group.getPlanningFrame().c_str()); // 输出规划框架名称
// 我们还可以打印出该组的末端执行器链接的名称。
RCLCPP_INFO(LOGGER, "End effector link: %s", move_group.getEndEffectorLink().c_str()); // 输出末端执行器链接名称
// 我们可以获取机器人中的所有组的列表:
RCLCPP_INFO(LOGGER, "Available Planning Groups:"); // 输出可用规划组信息
std::copy(move_group.getJointModelGroupNames().begin(), move_group.getJointModelGroupNames().end(),
std::ostream_iterator<std::string>(std::cout, ", ")); // 输出所有关节模型组的名称
规划一个运动到末端执行器的期望姿态
// 开始演示
// ^^^^^^^^^^^^^^^^^^^^^^^^^
visual_tools.prompt("Press 'next' in the RvizVisualToolsGui window to start the demo"); // 提示用户按“下一个”开始演示
// .. _move_group_interface-planning-to-pose-goal:
//
// 规划到姿态目标
// ^^^^^^^^^^^^^^^^^^^^^^^
// 我们可以为该组规划一个运动到末端执行器的期望姿态。
geometry_msgs::msg::Pose target_pose1; // 创建目标姿态变量
target_pose1.orientation.w = 1.0; // 设置目标姿态的方向
target_pose1.position.x = 0.28; // 设置目标姿态的X轴位置
target_pose1.position.y = -0.2; // 设置目标姿态的Y轴位置
target_