最新教程见MoveIt!教程

在MoveIt!中主要的用户界面是通过MoveGroup类实现,为用户可能想要执行的大多数操作提供了易于使用的功能,特别是设置关节或姿态目标,创建运动计划,移动机器人,将对象添加到环境中,并从机器人中添加/分离对象。该接口将ROS主题、服务和动作传递给MoveGroup节点。

创建Catkin工作空间

编译示例代码

在您的catkin工作区(cd~/ws_moveit/src)中,下载本教程:

git clonehttps://github.com/ros-planning/moveit_tutorials.git

临时PR2动力学介绍

您还需要一个pr2moveitconfig包来运行本教程。目前,这是在ROS动力学中未释放的,但下面是一个临时的解决方法:

git clonehttps://github.com/PR2/pr2_common.git -b kinetic-devel
git clonehttps://github.com/davetcoleman/pr2_moveit_config.git

安装依赖关系和构建

在编译新代码之前,扫描您的catkin工作空间,寻找丢失的包:

rosdep install--from-paths . --ignore-src --rosdistro kinetic
cd ~/ws_moveit
catkin config--extend /opt/ros/kinetic --cmake-args -DCMAKE_BUILD_TYPE=Release
catkin build

启动Rviz和MoveGroup节点

确保您已经重新获得了安装文件:

source ~/ws_moveit/devel/setup.bash

启动Rviz,等待一切完成加载:

roslaunch pr2_moveit_config demo.launch

运行演示

在一个新的终端窗口中,运行move_group_interface_tutorial.launchroslaunch文件:

roslaunch moveit_tutorials move_group_interface_tutorial.launch

在短暂的片刻之后,Rviz窗口应该出现,并且看起来与页面顶部的那个窗口相似。在屏幕下方按下一个按钮,或者按下键盘上的“n”键,而Rviz则专注于在每个演示步骤中取得进展。

解释演示

整个代码位于moveit教程github的子文件夹“pr2_tutorials/planning”下。接下来,我们逐段逐段地分析代码,解释它的功能。

设置

只需使用要控制和计划的组的名称,就可以轻松设置MoveGroup类。

moveit::planning_interface::MoveGroup group("right_arm");

我们将使用PlanningSceneInterface类直接处理世界。

moveit::planning_interface::PlanningSceneInterface planning_scene_interface;

(可选)创建用于在Rviz中可视化计划的发布程序。

ros::Publisher display_publisher = node_handle.advertise<moveit_msgs::DisplayTrajectory>("/move_group/display_planned_path", 1, true);
moveit_msgs::DisplayTrajectory display_trajectory;

获取基本信息

可以为这个机器人输出参考帧的名称

ROS_INFO("Reference frame: %s", group.getPlanningFrame().c_str());

还可以输出这个组的末端执行器链接的名称

ROS_INFO("Reference frame: %s", group.getEndEffectorLink().c_str());

规划到目标姿态

可以为这一组设计一个运动来达到末端执行器想要的姿态

geometry_msgs::Pose target_pose1;
target_pose1.orientation.w = 1.0;
target_pose1.position.x = 0.28;
target_pose1.position.y = -0.7;
target_pose1.position.z = 1.0;
group.setPoseTarget(target_pose1);

现在,调用规划器来计算规划并将其可视化。注意,我们只是规划,而不是要求move_group实际移动机器人

moveit::planning_interface::MoveGroup::Plan my_plan;
bool success = group.plan(my_plan);ROS_INFO("Visualizing plan 1 (pose goal) %s",success?"":"FAILED");
/* Sleep to give Rviz time to visualize the plan. */
sleep(5.0);

可视化规划

现在有了一个规划,可以在Rviz中将它可视化。这是不必要的,因为上面的group.plan()调用是自动执行的。但是,在希望可视化先前创建的规划的情况下,显式发布计划是有用的

if (1)
{ROS_INFO("Visualizing plan 1 (again)");display_trajectory.trajectory_start = my_plan.start_state_;display_trajectory.trajectory.push_back(my_plan.trajectory_);display_publisher.publish(display_trajectory);/* Sleep to give Rviz time to visualize the plan. */sleep(5.0);
}

移向目标姿态

移动到目标姿态类似于上面的步骤,只是我们现在使用move()函数。注意,之前设定的目标姿态仍然是活动的,所以机器人会尝试移动到那个目标。在本教程中,我们将不使用该函数,因为它是一个阻塞函数,需要控制器处于活动状态,并报告轨迹执行成功

/* Uncomment below line when working with a real robot*/
/* group.move() */

规划到目标关节空间

让我们设定一个共同的空间目标并朝着它前进。这将替换我们上面设置的位姿目标。

首首先获取组的当前联合值集。

std::vector<double> group_variable_values;
group.getCurrentState()->copyJointGroupPositions(group.getCurrentState()->getRobotModel()->getJointModelGroup(group.getName()), group_variable_values);

现在,让我们修改其中一个关节,规划为新的关节空间目标,并可视化该计划。

group_variable_values[0] = -1.0;
group.setJointValueTarget(group_variable_values);
success = group.plan(my_plan);ROS_INFO("Visualizing plan 2 (joint space goal) %s",success?"":"FAILED");
/* Sleep to give Rviz time to visualize the plan. */
sleep(5.0);

路径约束规划

可以很容易地为机器人上的链接指定路径约束。让我们为我们的组指定一个路径约束和一个位姿目标。首先定义路径约束。

moveit_msgs::OrientationConstraint ocm;
ocm.link_name = "r_wrist_roll_link";
ocm.header.frame_id = "base_link";
ocm.orientation.w = 1.0;
ocm.absolute_x_axis_tolerance = 0.1;
ocm.absolute_y_axis_tolerance = 0.1;
ocm.absolute_z_axis_tolerance = 0.1;
ocm.weight = 1.0;

现在,将它设置为group的路径约束。

moveit_msgs::Constraints test_constraints;
test_constraints.orientation_constraints.push_back(ocm);
group.setPathConstraints(test_constraints);

我们将重新利用我们的旧目标,并计划它。注意,只有当当前状态已经满足路径约束时,这才会工作。所以,我们需要将起始状态设置为一个新的姿态。

robot_state::RobotState start_state(*group.getCurrentState());
geometry_msgs::Pose start_pose2;
start_pose2.orientation.w = 1.0;
start_pose2.position.x = 0.55;
start_pose2.position.y = -0.05;
start_pose2.position.z = 0.8;
const robot_state::JointModelGroup *joint_model_group =start_state.getJointModelGroup(group.getName());
start_state.setFromIK(joint_model_group, start_pose2);
group.setStartState(start_state);

现在,我们将从刚刚创建的新start状态开始计划早期的pose目标。

group.setPoseTarget(target_pose1);
success = group.plan(my_plan);ROS_INFO("Visualizing plan 3 (constraints) %s",success?"":"FAILED");
/* Sleep to give Rviz time to visualize the plan. */
sleep(10.0);

当使用路径约束时,一定要清除它。

group.clearPathConstraints();

笛卡尔路径

您可以通过指定末端执行器要经过的路径点列表来直接规划笛卡尔路径。注意,我们从上面的新start状态开始。初始姿态(开始状态)不需要添加到waypoint列表中。

std::vector<geometry_msgs::Pose> waypoints;geometry_msgs::Pose target_pose3 = start_pose2;
target_pose3.position.x += 0.2;
target_pose3.position.z += 0.2;
waypoints.push_back(target_pose3);  // up and outtarget_pose3.position.y -= 0.2;
waypoints.push_back(target_pose3);  // lefttarget_pose3.position.z -= 0.2;
target_pose3.position.y += 0.2;
target_pose3.position.x -= 0.2;
waypoints.push_back(target_pose3);  // down and right (back to start)

我们想要笛卡尔坐标路径以1cm的分辨率插值这就是为什么我们要指定0。01作为笛卡尔坐标平移的最大步长。我们将把跳转阈值指定为0.0,从而有效地禁用它。

moveit_msgs::RobotTrajectory trajectory;
double fraction = group.computeCartesianPath(waypoints,0.01,  // eef_step0.0,   // jump_thresholdtrajectory);ROS_INFO("Visualizing plan 4 (cartesian path) (%.2f%% acheived)",fraction * 100.0);
/* Sleep to give Rviz time to visualize the plan. */
sleep(15.0);

添加/删除对象和附加/分离对象

首先定义碰撞对象消息。

moveit_msgs::CollisionObject collision_object;
collision_object.header.frame_id = group.getPlanningFrame();/* The id of the object is used to identify it. */
collision_object.id = "box1";/* Define a box to add to the world. */
shape_msgs::SolidPrimitive primitive;
primitive.type = primitive.BOX;
primitive.dimensions.resize(3);
primitive.dimensions[0] = 0.4;
primitive.dimensions[1] = 0.1;
primitive.dimensions[2] = 0.4;/* A pose for the box (specified relative to frame_id) */
geometry_msgs::Pose box_pose;
box_pose.orientation.w = 1.0;
box_pose.position.x =  0.6;
box_pose.position.y = -0.4;
box_pose.position.z =  1.2;collision_object.primitives.push_back(primitive);
collision_object.primitive_poses.push_back(box_pose);
collision_object.operation = collision_object.ADD;std::vector<moveit_msgs::CollisionObject> collision_objects;
collision_objects.push_back(collision_object);

现在将碰撞对象添加到这个世界中

ROS_INFO("Add an object into the world");
planning_scene_interface.addCollisionObjects(collision_objects);/* Sleep so we have time to see the object in RViz */
sleep(2.0);

带有碰撞检测的规划可能很慢。让我们设定规划时间,以确保计划员有足够的时间来做计划。10秒应该足够了。

group.setPlanningTime(10.0);

当我们规划轨迹时,它会避开障碍物

group.setStartState(*group.getCurrentState());
group.setPoseTarget(target_pose1);
success = group.plan(my_plan);ROS_INFO("Visualizing plan 5 (pose goal move around box) %s",success?"":"FAILED");
/* Sleep to give Rviz time to visualize the plan. */
sleep(10.0);

现在把碰撞物体附加到机器人上。

ROS_INFO("Attach the object to the robot");
group.attachObject(collision_object.id);
/* Sleep to give Rviz time to show the object attached (different color). */
sleep(4.0);

现在把碰撞物体从机器人中分离出来。

ROS_INFO("Detach the object from the robot");
group.detachObject(collision_object.id);
/* Sleep to give Rviz time to show the object detached. */
sleep(4.0);

现在将碰撞对象从世界中移除。

ROS_INFO("Remove the object from the world");
std::vector<std::string> object_ids;
object_ids.push_back(collision_object.id);
planning_scene_interface.removeCollisionObjects(object_ids);
/* Sleep to give Rviz time to show the object is no longer there. */
sleep(4.0);

双臂的目标姿态

首先定义一个新的组来处理这两个分支。然后定义两个独立的姿态目标,每个末端执行器一个。请注意,我们正在为上面的右臂重用目标

moveit::planning_interface::MoveGroup two_arms_group("arms");two_arms_group.setPoseTarget(target_pose1, "r_wrist_roll_link");geometry_msgs::Pose target_pose2;
target_pose2.orientation.w = 1.0;
target_pose2.position.x = 0.7;
target_pose2.position.y = 0.15;
target_pose2.position.z = 1.0;two_arms_group.setPoseTarget(target_pose2, "l_wrist_roll_link");

现在,我们可以规划和可视化

moveit::planning_interface::MoveGroup::Plan two_arms_plan;
two_arms_group.plan(two_arms_plan);
sleep(4.0);

运行代码

entire code    Compiling the code    launch file

从moveit_tutorials直接运行代码的启动文件:

roslaunch moveit_tutorials move_group_interface_tutorial.launch

过一会儿,Rviz窗口应该会出现:

可以关闭窗口右下角的运动规划部分,以便更好地查看机器人。

期望输出

在Rviz中,我们应该能够看到以下内容(每一步之间会有5-10秒的延迟):

1. 机器人将右臂移向右前方的姿势。

2. 机器人将右臂移动到右侧的关节处。

3. 在保持末端执行器的水平的同时,机器人将右臂移回到新的姿势目标。

4. 机器人沿着理想的笛卡尔路径移动它的右手臂(一个三角形向上+向前,左,向下+后)。

5. 将一个盒子对象添加到右边的右边的环境中。

6. 该机器人将右臂移至姿势目标,避免与盒子发生碰撞。

7. 这个物体附着在手腕上(它的颜色会变成紫色/橙色/绿色)。

8. 这个物体脱离了手腕(它的颜色会变回绿色)。

9. 对象从环境中删除。

10. 这个机器人同时将两个手臂同时移动到两个不同的姿势。

MoveIt!教程 - MoveGroup接口相关推荐

  1. MoveIt! Tutorials, MoveIt! 教程——demo

    MoveIt! Tutorials,gihub地址:https://github.com/ros-planning/moveit_tutorials/blob/kinetic-devel/index. ...

  2. 调用bing图片html代码,网站背景调用必应Bing每日图片教程附接口

    本次为大家带来的是为网站背景调用必应Bing每日图片教程附接口 微软的必应搜索的每日图片的内容也是非常好看非常美的 小编突发奇想把必应每日更新的图片应用到网站背景 然后就能每天自动换很好看的网站背景了 ...

  3. MoveIt教程[9]:Motion Planning API

    在MoveIt中,运动规划器加载使用插件基础设施.这允许MoveIt在运行时加载运动规划器.在本例中,将运行完成此任务所需的C++代码. 一.Running the Demo 打开两个shell.在第 ...

  4. Windows下Libvirt Java API使用教程(二)- 接口使用说明

    介绍完libvirt Java API的部署工作: <Windows下Libvirt Java API使用教程(一)- 开发环境部署> 接下来我们就介绍一下接口的使用和代码样例. libv ...

  5. 通信教程 | USB接口、标准和基础原理

    关注+星标公众号,不错过精彩内容 视频号 | strongerHuang 微信公众号 | strongerHuang 1写在前面 USB:Universal Serial Bus,通用串行总线. US ...

  6. MoveIt教程[20]:TRAC-IK Kinematics Solver

    TRAC-IK是由TRACLabs开发的一个逆向运动学求解器,它通过线程将两个IK实现组合在一起,以获得比常见的开源IK求解器更可靠的解决方案.从它们的文档: [TRAC-IK]为KDL中流行的逆雅可 ...

  7. MoveIt教程[19]:IKFast Kinematics Solver

    在本节中,将介绍为MoveIt配置IKFast插件. 一.What is IKFast 来自Wikipedia: IKFast,机器人运动学编译器,是Rosen Diankov的OpenRAVE运动规 ...

  8. MoveIt教程[10]:Motion Planning Pipeline

    在MoveIt中,motion planners被设置为规划路径.然而,在很多情况下,可能希望对运动规划请求进行预处理,或者对规划的路径进行后处理[例如,对时间参数化].在这种情况下,使用规划管道,其 ...

  9. 通信教程05_USB接口、标准和基础原理

    关注.星标公众号,不错过精彩内容 本教程由作者strongerHuang于2019年11月原创发布. 标签:串口. USB. 通信 版权所有:禁止商用 申明:该文档仅供个人学习使用,转载请公众号联系作 ...

最新文章

  1. 在Vue的webpack中结合runder函数
  2. linux shell读取文件
  3. react 当前时间_如何使用 useRef 优化 React 性能问题
  4. 【HDU6667】Roundgod and Milk Tea【贪心】
  5. BZOJ 2326 数学作业(分段矩阵快速幂)
  6. 第114天:Ajax跨域请求解决方法(二)
  7. Android开发中如何调用摄像头的功能
  8. docker挂载目录
  9. python成语接龙_python——成语接龙小游戏
  10. MDCC2013会议笔记
  11. 【Unity Shader 消融效果_案例分享】
  12. Java项目员工信息管理系统
  13. qt快速读取excel
  14. css3波浪纹路_css3线条波浪动画效果
  15. hive 计算两个经纬度之间的距离
  16. 今天终于把网络协作学习系统做完了
  17. 莫逸风CSDN文章目录
  18. 关于war3中的随机数获取
  19. xilinx ps-pl间的共享中断如何使用
  20. 关于数理统计学及其与概率论之间联系的一些理解

热门文章

  1. 【离散数学】集合论 第四章 函数与集合(3) 鸽巢原理
  2. 30天搜索量激增298%!赛盈分销浅谈家具沙发市场的5个消费痛点!
  3. Java基础编程之输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数
  4. Linux 分区方案介绍
  5. jsonp在html什么作用,使用JSONP 解析HTML网页。
  6. Keep上市,打响健身科技第一炮?
  7. 网络安全:源码免杀lcx过nod32,KAV,mcafee,Avira,AVG,Symantec,金山和360
  8. laravel如何使用websocket
  9. 如何实现闲聊群里自动发战绩
  10. python sql注入如何防止_Python如何防止sql注入