ROS Industrial 软件包_笛卡尔路径规划器_实现

2024-04-28 04:58

本文主要是介绍ROS Industrial 软件包_笛卡尔路径规划器_实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

笛卡尔(Descarte)路径规划

使用笛卡尔包

使用笛卡尔包需要软件开发人员创建三个对象Obiects:

一个机器人模型(a robot model),将用来计算正向运动学和逆向运动学。

一个轨迹点的轨迹(a trajectory of trajectory points),用于定义路径。

一个规划器(a planner),将使用提供的机器人模型来完成沿着轨迹寻找有效路线的工作。

 

代码解读

源码地址

在descartes_tutorials/src/中,tutorial1.cpp是一个单个文件程序,该程序定义了一条简单的轨迹,使用Moveit创建了机器人模型规划轨迹并执行了它。

顶部是几个函数声明,源代码将在下文中详细解读。

 

   1 // Core ros functionality like ros::init and spin

   2 #include <ros/ros.h>

   3 // ROS Trajectory Action server definition

   4 #include <control_msgs/FollowJointTrajectoryAction.h>

   5 // Means by which we communicate with above action-server

   6 #include <actionlib/client/simple_action_client.h>

   7

头文件的第一部分包含了打印,定义轨迹和发送这些轨迹所需的基本ROS组件。 ROS-Industrial支持的大多数机器人都为仿真模拟实际硬件提供了FollowJointTrajectory动作(action)接口。

 

   8 // Includes the descartes robot model we will be using

   9 #include <descartes_moveit/moveit_state_adapter.h>

  10 // Includes the descartes trajectory type we will be using

  11 #include <descartes_trajectory/axial_symmetric_pt.h>

  12 #include <descartes_trajectory/cart_trajectory_pt.h>

  13 // Includes the planner we will be using

  14 #include <descartes_planner/dense_planner.h>

第二批标题头包含我们生成轨迹所需的所有笛卡尔特定文件。 moveit_state_adapter.h定义了笛卡尔机器人模型(RobotModel),而descartes_trajectory中的两个文件定义了轨迹点(Trajectory Points)的特定类型。 最后,densage_planner.h提供对笛卡尔规划器的访问。 有关特定组件的更多信息,请参见笛卡尔(descartes)。

 

  46 {

  47   // Initialize ROS

  48   ros::init(argc, argv, "descartes_tutorial");

  49   ros::NodeHandle nh;

  50

  51   // Required for communication with moveit components

  52   ros::AsyncSpinner spinner (1);

  53   spinner.start();

在使用ROS组件之前,我们必须通过调用ros :: init初始化节点。 我还将在此处创建一个NodeHandle,该节点将稍后用于从ROS参数服务器中检索组件。

51-52行创建一个新线程来处理在执行笛卡尔时可能需要处理的所有回调。 在没有微调器(spinner)的情况下初始化MoveIt似乎会引起问题。

 

  54   // 1. Define sequence of points

  55   TrajectoryVec points;

  56   for (unsigned int i = 0; i < 10; ++i)

  57   {

  58     Eigen::Affine3d pose;

  59     pose = Eigen::Translation3d(0.0, 0.0, 1.0 + 0.05 * i);

  60     descartes_core::TrajectoryPtPtr pt = makeTolerancedCartesianPoint(pose);

  61     points.push_back(pt);

  62   }

  63

  64   for (unsigned int i = 0; i < 5; ++i)

  65   {

  66     Eigen::Affine3d pose;

  67     pose = Eigen::Translation3d(0.0, 0.04 * i, 1.3);

  68     descartes_core::TrajectoryPtPtr pt = makeTolerancedCartesianPoint(pose);

  69     points.push_back(pt);

  70   }

在这里,我们使用本征变换(Eigen transformations)定义了一系列轨迹点。 这些转换定义了末端执行器的向上运动,然后是侧向平移。

makeTolerancedCartesianPoint函数是用于生成笛卡尔点的辅助函数,该笛卡尔点绕末端执行器框架(end effector frame)z轴的旋转不受限制。 求解图(最短路径)时,笛卡尔将尝试通过实质上围绕z轴旋转目标姿态来搜索有效的IK解。

makeTolerancedCartesianPoint的定义很简单,将在稍后讨论。

 

  72   // 2. Create a robot model and initialize it

  73   descartes_core::RobotModelPtr model (new descartes_moveit::MoveitStateAdapter);

  74

  75   // Name of description on parameter server. Typically just "robot_description".

  76   const std::string robot_description = "robot_description";

  77

  78   // name of the kinematic group you defined when running MoveitSetupAssistant

  79   const std::string group_name = "manipulator";

  80

  81   // Name of frame in which you are expressing poses.

  82   // Typically "world_frame" or "base_link".

  83   const std::string world_frame = "base_link";

  84

  85   // tool center point frame (name of link associated with tool)

  86   const std::string tcp_frame = "tool0";

  87

  88   if (!model->initialize(robot_description, group_name, world_frame, tcp_frame))

  89   {

  90     ROS_INFO("Could not initialize robot model");

  91     return -1;

在此代码块中,我们通过提供有关我们要控制的机器人的信息来创建和初始化机器人模型。使用提供的moveit_state_adapter的先决条件是,在运行此示例之前,必须已运行Moveit设置助手并至少创建了一个运动学组。

接下来,代码从ROS参数服务器中搜索robot_description参数以获取对机器人(或包含机器人的系统)的描述。group_name参数应与运行Moveit设置助手时创建的运动组的名称匹配。默认的ROS-Industrial软件包通常使用'manipulator'作为其默认组名。

world_frame参数指定您传入的位置姿势的参考框架。如果要指定相对于某个预定原点的全局位置,则该原点的名称是world_frame的参数(它也是URDF中的根框架)。如果这些点是相对于机器人基座或其他固定框架表示的,则输入基础链接(base link)或您要使用的任何其他框架的名称。

tcp_frame工具中心点框架(tool center point frame)是计算正向和反向运动学时使用的参考框架。它几乎始终是操纵器组中的最后一个链接(与名称group_name关联)。

 

  94   // 3. Create a planner and initialize it with our robot model

  95   descartes_planner::DensePlanner planner;

  96   planner.initialize(model);

  97

  98   // 4. Feed the trajectory to the planner

  99   if (!planner.planPath(points))

 100   {

 101     ROS_ERROR("Could not solve for a valid path");

 102     return -2;

 103   }

 104

 105   TrajectoryVec result;

 106   if (!planner.getPath(result))

 107   {

 108     ROS_ERROR("Could not retrieve path");

 109     return -3;

一旦定义了机器人模型和轨迹,规划轨迹就很简单。 创建你所选择的规划器(DensePlanner / Sparse Planner),使用刚刚创建的模型对其进行初始化(并自行初始化),并在传递所需轨迹的同时调用planPath函数。 此函数调用会进行大量计算以生成适当的关节轨迹,并且可能需要一段时间才能返回,具体取决于所分析计划的复杂性。

getPath函数用于检索结果轨迹。 为了使规划器尽可能通用,它返回多态类型TrajectoryPtPtr,但对于密集规划器和稀疏规划器而言,其基础类型都是JointTrajectoryPt 关节值本身将在稍后的toROSJointTrajectory函数中解压缩。

确保检查planPathgetPath函数的返回值是否正确,因为它们可能由于各种原因而失败,包括无法到达的点不平滑的联合轨迹

 

 112   // 5. Translate the result into a type that ROS understands

 113   // Get Joint Names

 114   std::vector<std::string> names;

 115   nh.getParam("controller_joint_names", names);

 116   // Generate a ROS joint trajectory with the result path, robot model,

 117   // joint names, and a certain time delta between each trajectory point

 118   trajectory_msgs::JointTrajectory joint_solution =

 119       toROSJointTrajectory(result, *model, names, 1.0);

 120

 121   // 6. Send the ROS trajectory to the robot for execution

 122   if (!executeTrajectory(joint_solution))

 123   {

 124     ROS_ERROR("Could not execute trajectory!");

 125     return -4;

这个最终的代码块将笛卡尔生成的关节轨迹转换为ROS可以理解的格式。 toROSJointTrajectory辅助函数执行此任务,但需要一些信息:

1.笛卡尔关节轨迹解

2.用于插补这些点的笛卡尔机器人模型

3.被主动操控的关节名称

4.每个关节位置之间的时间

114-115行从ROS参数服务器中检索教程中机器人的关节名称。

 

 

辅助函数

   1 descartes_core::TrajectoryPtPtr makeTolerancedCartesianPoint(const Eigen::Affine3d& pose)

   2 {

   3   using namespace descartes_core;

   4   using namespace descartes_trajectory;

   5   return TrajectoryPtPtr(

new AxialSymmetricPt(pose, // Nominal pose

   6                            M_PI/2.0,           // Search discretization

   7                            AxialSymmetricPt::Z_AXIS) ); // Free axis                   

   8 }

makeTolerancedCartesianPoint是围绕笛卡尔的AxialSymmetricPt类的小型包装函数。 此类本身是笛卡尔点的一种特殊形式,其中的最后一个参数(此处为AxialSymmetricPt :: Z_AXIS)是工具可以围绕其自由旋转的名义姿态(nominal pose)的轴。 其他选项包括X_AXISY_AXIS

如果要创建固定的6DOF(6自由度)笛卡尔姿势,或者想要更好地控制可接受的公差,则可以创建具有相对应属性的笛卡尔点。

TrajectoryPtPtr是类型为descartes_core :: TrajectoryPtboost :: shared_ptr的别名。 共享指针是一种自动管理对象生存期的方法,在许多情况下,共享指针可以像普通指针一样使用。

 

   1 trajectory_msgs::JointTrajectory

   2 toROSJointTrajectory(const TrajectoryVec& trajectory,

   3                      const descartes_core::RobotModel& model,

   4                      const std::vector<std::string>& joint_names,

   5                      double time_delay)

   6 {

   7   // Fill out information about our trajectory

   8   trajectory_msgs::JointTrajectory result;

   9   result.header.stamp = ros::Time::now();

  10   result.header.frame_id = "world_frame";

  11   result.joint_names = joint_names;

  12

  13   // For keeping track of time-so-far in the trajectory

  14   double time_offset = 0.0;

  15   // Loop through the trajectory

  16   for (TrajectoryIter it = trajectory.begin(); it != trajectory.end(); ++it)

  17   {

  18     // Find nominal joint solution at this point

  19     std::vector<double> joints;

  20     it->get()->getNominalJointPose(std::vector<double>(), model, joints);

  21

  22     // Fill out a ROS trajectory point

  23     trajectory_msgs::JointTrajectoryPoint pt;

  24     pt.positions = joints;

  25     // velocity, acceleration, and effort are given dummy values

  26     // we'll let the controller figure them out

  27     pt.velocities.resize(joints.size(), 0.0);

  28     pt.accelerations.resize(joints.size(), 0.0);

  29     pt.effort.resize(joints.size(), 0.0);

  30     // set the time into the trajectory

  31     pt.time_from_start = ros::Duration(time_offset);

  32     // increment time

  33     time_offset += time_delay;

  34

  35     result.points.push_back(pt);

  36   }

  37

  38   return result;

  39 }

该函数负责将笛卡尔轨迹转换为ROS trajectory_msgs :: JointTrajectory 与任何ROS消息类型一样,请确保填写标头信息,包括frame_id和时间戳。

笛卡尔的规划器返回轨迹点指针的向量,因此我们必须以多态方式访问基础数据。 稀疏和密集规划器返回的基础类型是关节轨迹点。 getNominalJointPose函数可用于提取所需的关节位置。 对于这种类型的点,函数的第一个参数只是一个哑元(虚设的参数) 接下来,我们调整速度,加速度和力度字段(effort fields)的大小,并将所有值设置为零,以使控制器不会拒绝我们的点,并自己计算出合适的值。

 最终,我们对轨迹中的时间进行了连续计数。 相对于轨迹的起点(而不是先前的点)指定ROS轨迹点的时间。

 

   1 bool executeTrajectory(const trajectory_msgs::JointTrajectory& trajectory)

   2 {

   3   // Create a Follow Joint Trajectory Action Client

   4   actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction> ac("joint_trajectory_action", true);

   5   if (!ac.waitForServer(ros::Duration(2.0)))

   6   {

   7     ROS_ERROR("Could not connect to action server");

   8     return false;

   9   }

  10

  11   control_msgs::FollowJointTrajectoryGoal goal;

  12   goal.trajectory = trajectory;

  13   goal.goal_time_tolerance = ros::Duration(1.0);

  14   

  15   ac.sendGoal(goal);

  16

  17   if (ac.waitForResult(goal.trajectory.points[goal.trajectory.points.size()-1].time_from_start + ros::Duration(5)))

  18   {

  19     ROS_INFO("Action server reported successful execution");

  20     return true;

  21   } else {

  22     ROS_WARN("Action server could not execute trajectory");

  23     return false;

  24   }

  25 }

executeTrajectory函数创建了FollowJointTrajectoryAction客户端,通过动作客户端调用ac.sendGoal(goal)函数调用动作服务器执行动作。

 

 

 

构建

descartes_tutorials存储库中的CMakeLists.txt显示了上面代码的最小示例。 将必要的配置添加到您的CMakeLists.txt,然后通过catkin_make/catkin build等进行构建。

 

 

这篇关于ROS Industrial 软件包_笛卡尔路径规划器_实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/942376

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2