首页 > 其他分享 >Ros2- Moveit2- Subrame( 子坐标 )

Ros2- Moveit2- Subrame( 子坐标 )

时间:2024-09-18 10:50:40浏览次数:1  
标签:box cylinder target Subrame moveit pose 坐标 Moveit2 Ros2

子坐标是在CollisionObjects上定义的坐标。

它们可用于定义您放置在场景中的对象上的兴趣点,例如瓶子的开口、螺丝刀的尖端或螺丝的头部。它们可用于规划和编写机器人指令,例如“拿起瓶子,然后将开口移到水龙头的喷口下方”,或“拿起螺丝刀,然后将其放在螺丝头上方”。

编写专注于机器人操纵对象的代码不仅更易读,而且在机器人之间也更强大、更易于移植。本教程将向您展示如何在碰撞对象上定义子坐标,将它们发布到规划场景并使用它们来规划运动,以便您可以执行以下操作:

 

 

运行演示

完成入门中的步骤后,打开两个终端。在第一个终端中,执行此命令加载 panda,然后等待所有内容加载完成:

roslaunch panda_moveit_config demo.launch

在第二个终端运行教程:

rosrun moveit_tutorials subframes_tutorial

在这个终端您应该能够输入 1-12 的数字来发送命令,并查看机器人和场景如何反应。

代码

此示例的代码可以在 moveit_tutorials GitHub 项目中看到并在下面详细说明。

代码在规划场景中生成一个盒子和一个圆柱体,将圆柱体连接到机器人,然后让您通过命令行发送运动命令。它还定义了两个方便的函数,用于发送运动命令和发布对象。

使用子坐标定义两个 CollisionObjects

此辅助函数创建两个对象并将它们发布到 PlanningScene:一个盒子和一个圆柱体。盒子出现在夹持器前面,圆柱体出现在夹持器的尖端,就像被抓取一样。

void spawnCollisionObjects(moveit::planning_interface::PlanningSceneInterface& planning_scene_interface)
{
  double z_offset_box = .25;  // The z-axis points away from the gripper
  double z_offset_cylinder = .1;

首先,我们像往常一样开始定义CollisionObject 。

moveit_msgs::CollisionObject box;
box.id = "box";
box.header.frame_id = "panda_hand";
box.primitives.resize(1);
box.primitive_poses.resize(1);
box.primitives[0].type = box.primitives[0].BOX;
box.primitives[0].dimensions.resize(3);
box.primitives[0].dimensions[0] = 0.05;
box.primitives[0].dimensions[1] = 0.1;
box.primitives[0].dimensions[2] = 0.02;
box.primitive_poses[0].position.z = z_offset_box;

然后,我们定义 CollisionObject 的子坐标。子坐标在frame_id坐标系中定义,就像组成对象的形状一样。每个子坐标都包含一个名称和一个姿势。在本教程中,我们设置子坐标的方向,使子坐标的 z 轴指向远离对象的方向。这不是绝对必要的,但遵循惯例是有帮助的,并且可以避免在稍后设置目标姿势的方向时产生混淆。

box.subframe_names.resize(5);
box.subframe_poses.resize(5);

box.subframe_names[0] = "bottom";
box.subframe_poses[0].position.y = -.05;
box.subframe_poses[0].position.z = 0.0 + z_offset_box;

tf2::Quaternion orientation;
orientation.setRPY(90.0 / 180.0 * M_PI, 0, 0);
box.subframe_poses[0].orientation = tf2::toMsg(orientation);

最后,将对象发布到 PlanningScene。在本教程中,我们发布一个盒子和一个圆柱体。

  box.operation = moveit_msgs::CollisionObject::ADD;
  cylinder.operation = moveit_msgs::CollisionObject::ADD;
  planning_scene_interface.applyCollisionObjects({ box, cylinder });
}

创建计划请求

在本教程中,我们使用一个小辅助函数来创建规划请求并移动机器人。

bool moveToCartPose(const geometry_msgs::PoseStamped& pose, moveit::planning_interface::MoveGroupInterface& group,
                    const std::string& end_effector_link)
{

要在规划中使用附在机器人上的对象的子坐标,您需要将 move_group 的末端效应器设置为对象的子坐标。格式必须是object_name/subframe_name,如“示例 1 ”行中所示。当您分离对象时,不要忘记将您的 end_effector_link 重置为机器人链接,并且子坐标不再是机器人的一部分!

group.clearPoseTargets();
group.setEndEffectorLink(end_effector_link);
/*
group.setEndEffectorLink("cylinder/tip");    // Example 1
group.setEndEffectorLink("panda_hand");      // Example 2
*/
group.setStartStateToCurrentState();
group.setPoseTarget(pose);

其余的规划工作照常进行。当然,你也可以使用命令go()代替 plan()execute()

  ROS_INFO_STREAM("Planning motion to pose:");
  ROS_INFO_STREAM(pose.pose.position.x << ", " << pose.pose.position.y << ", " << pose.pose.position.z);
  moveit::planning_interface::MoveGroupInterface::Plan myplan;
  if (group.plan(myplan) && group.execute(myplan))
    return true;

  ROS_WARN("Failed to perform motion.");
  return false;
}

准备场景

在主函数中,我们首先在规划场景中生成对象,然后将圆柱体附加到机器人上。附加圆柱体后,它在 Rviz 中变为紫色。

spawnCollisionObjects(planning_scene_interface);
moveit_msgs::AttachedCollisionObject att_coll_object;
att_coll_object.object.id = "cylinder";
att_coll_object.link_name = "panda_hand";
att_coll_object.object.operation = att_coll_object.object.ADD;
ROS_INFO_STREAM("Attaching cylinder to robot.");
planning_scene_interface.applyAttachedCollisionObject(att_coll_object);

交互式测试机器人

我们设置了一个小型命令行界面,以便您可以与模拟进行交互,并查看它如何响应某些命令。您可以使用它来试验机器人在移除盒子和圆柱体、重生并重新连接它们或创建新的规划请求时的行为。尝试将机器人移动到新位置并在那里重生盒子和圆柱体(它们是相对于机器人手腕生成的)。或者尝试命令 7 和 8 将不同的帧移动到空间中的相同位置。

命令“2”将圆柱尖端移动到盒子的顶部(顶部动画中的右侧)。

else if (character_input == 2)
{
  ROS_INFO_STREAM("Moving to top of box with cylinder tip");
  target_pose.header.frame_id = "box/top";
  target_orientation.setRPY(180.0 / 180.0 * M_PI, 0, 90.0 / 180.0 * M_PI);
  target_pose.pose.orientation = tf2::toMsg(target_orientation);
  target_pose.pose.position.z = 0.01;
  showFrames(target_pose, "cylinder/tip");
  moveToCartPose(target_pose, group, "cylinder/tip");
}

设置方向

目标姿势相对于箱体子坐标给出:

target_pose.header.frame_id = "box/bottom";

方向由 RPY 角度决定,以对齐圆柱体和箱形副车架:

target_orientation.setRPY(0, 180.0 / 180.0 * M_PI, 90.0 / 180.0 * M_PI);
target_pose.pose.orientation = tf2::toMsg(target_orientation);

为了与盒子保持一定的距离,我们使用一个小的偏移:

target_pose.pose.position.z = 0.01;
showFrames(target_pose, "cylinder/tip");
moveToCartPose(target_pose, group, "cylinder/tip");

技术说明

TF 无法识别子坐标,因此它们不能在 MoveIt 规划请求之外使用。如果您需要对子坐标进行变换,可以使用getFrameTransform函数从PlanningScene中 获取它。这将返回一个Eigen::Isometry3d对象,您可以从中提取平移和四元数(请参阅此处)。然后可以使用平移和四元数来创建变换并将其注册到您的 TFListener中。

可视化子坐标

目前没有子坐标的可视化!

故障排除

对于您最近没有自己生成的旧版 moveit_config 包,可能没有配置用于子坐标的规划适配器,可能找不到子坐标链接。要修复您的 moveit_config 包,请打开机器人配置文件中的 ompl_planning_pipeline.launch 文件,该文件位于 <robot_moveit_config>/launch 文件夹中。以 Panda 机器人为例,这就是这个文件。编辑此启动文件,找到提到 <arg name="planning_adapters"> 的行,然后在 default_planning_request_adapters/FixStartStatePathConstraints 之后插入 default_planning_request_adapters/ResolveConstraintFrames

标签:box,cylinder,target,Subrame,moveit,pose,坐标,Moveit2,Ros2
From: https://www.cnblogs.com/ai-ldj/p/18418088

相关文章

  • Ros2 - Moveit2 - DeepGrasp(深度抓握)
    MoveIt深度把握本教程演示了如何在MoveIt任务构造器中使用抓握姿势检测(GPD)和 Dex-Net。GPD(左)和Dex-Net(右)用于生成拾取圆柱体的抓取姿势。https://moveit.picknik.ai/main/_images/mtc_gpd_panda.gif 入门如果您还没有这样做,请确保您已经完成入门指南中的步骤。......
  • ROS2图形化方式新建功能包工具- Turtle Nest
    提示:全文AI生成。链接:https://github.com/Jannkar/turtle_nest配置TurtleNest使用说明(中文版)一、TurtleNest简介正如海龟巢是幼海龟的诞生地,ROS2TurtleNest是ROS2包的诞生和成长之地。TurtleNest提供了一个易用的图形用户界面(GUI),简化了ROS2包的创建......
  • Ros2 - Moveit2 - Grasps(抓握)
    MoveItGrasps是一款用于抓取块或圆柱体等物体的抓取生成器,可用作MoveIt拾取和放置管道的替代品。MoveItGrasps提供基于可达性和接近、抬起和后退运动的笛卡尔规划来过滤抓取的功能。抓握生成算法基于简单的长方体形状,不考虑摩擦锥或其他抓握动力。MoveItGrasps可与平行......
  • Ros2 - Moveit2 - Pick And Place(拾取和放置)
    拾取和放置注意:本教程中使用的功能已弃用。要执行拾取和放置操作,应使用MoveIt任务构造器(MTC)(使用MoveIt任务构造器拾取和放置)。 在MoveIt中,抓取是使用MoveGroup接口完成的。为了抓取一个物体,我们需要创建moveit_msgs::Graspmsg,以便定义抓取操作中涉及的各种姿势和姿......
  • ROS2 - Moveit2 - Planning with Approximated Constraint Manifolds(使用近似约束流
    使用近似约束流形进行规划OMPL支持自定义约束,以使规划轨迹遵循所需的行为。约束可以在关节空间和笛卡尔空间中定义,后者基于方向或位置。在规划轨迹时,每个关节状态都需要遵循所有设置的约束,默认情况下,这是通过拒绝采样来执行的。然而,这可能会导致非常长的规划时间,特别是当约束非......
  • Ros2 - Moveit2 - TimeParameter(时间参数化)
    时间参数化MoveIt目前主要是一个运动规划框架-它规划关节或末端执行器的位置,但不规划速度或加速度。但是,MoveIt确实利用后处理来对速度和加速度值的运动轨迹进行时间参数化。下面我们将解释MoveIt这一部分所涉及的设置和组件。 速度控制来自文件默认情况下,MoveIt将关......
  • ROS2开发前置基础知识
    前言笔者发现现在市面上(主要是某站上)的ros2相关的教程内容大多不太基础(例如古某居(手动狗头保命),对于那些不熟悉Linux和C++甚至Python的童鞋来说不太友好,之前笔者自己在跟着学习过程中也有不少疑惑,踩了不少坑,现进行一些前置知识的总结(主要学习古某居和鱼香ros的教程,墙裂推荐),一......
  • Ros2- Moveit2 - Visualizing Collisions(可视化碰撞)
    本节将引导您了解C++示例代码,该代码可让您在RViz中移动和与机器人手臂交互时可视化机器人本身与世界之间的碰撞接触点。入门运行代码使用Roslaunch启动文件直接从moveit_tutorials运行代码:roslaunchmoveit_tutorialsvisualizing_collisions_tutorial.launch现在......
  • ROS2 - Moveit2 - 创建Moveit插件(MoveIt Plugins)
    创建MoveIt插件本节详细说明了如何在ROS中添加插件。两个必需元素是基类和插件类。插件类继承自基类并覆盖其虚拟函数。用于此目的的主要库是pluginlib。本教程包含三种不同类型的插件,即运动规划器、控制器管理器和约束采样器。运动规划器插件在本节中,我们将展示如何将新......
  • 拉取ros2_control_demos存储库
    目录克隆存储库方法1:使用gitclone和rosdep安装依赖方法2:使用vcs工具管理多个存储库区别总结rosdep和APT的关系网络问题安装依赖克隆存储库方法1:使用gitclone和rosdep安装依赖下载存储库:mkdir-p~/ros2_ws/srccd~/ros2_ws/srcgitclo......