ROS中Moveit生成轨迹如何作用于实际的机械臂(一)

您所在的位置:网站首页 机械臂中的两臂是什么 ROS中Moveit生成轨迹如何作用于实际的机械臂(一)

ROS中Moveit生成轨迹如何作用于实际的机械臂(一)

2024-07-12 08:13| 来源: 网络整理| 查看: 265

ROS使用Moveit来对机械臂进行轨迹规划,而Moveit使用ControllerManager插件接口的形式来发布轨迹信息给机械臂的控制器。为了能让机械臂(无论是真实的还是虚拟的)按照计算的轨迹动起来,就必须实现这一个接口。在Moveit中提供了两个具体的接口实现,即simple_controller_manager和fake_controller_manager。fake_controller_manager就是一个假的ControllerManager,只用于仿真使用。这里不做讨论,仿真时直接使用就好了。simple_controller_manager则是一个可以与实际硬件关联的ControllerManager,所以为了能够很好地理解Moveit如何对真实机械臂进行轨迹运动控制,分析一下simple_controller_manager是很有必要的。

simple_controller_manager代码分析

在这个我们对simple_controller_manager的代码进行简要的分析。因为我们的目的并不是要写一个ControllerManager,使用simple_controller_manager来操控机械臂已经足够了。

simple_controller_manager的代码可在Moveit的github中查看。 在其include目录中,有三个文件:

action_based_controller_handle.hfollow_joint_trajectory_controller_handle.hgripper_controller_handle.h

第一个头文件定义用于action相关操作的类ActionBasedControllerHandle:

class ActionBasedControllerHandle { ActionBasedControllerHandle(const std::string& name, const std::string& ns); bool isConnected(); bool cancelExecution() bool waitForExecution(const ros::Duration& timeout = ros::Duration(0)); ExecutionStatus getLastExecutionStatus(); void addJoint(const std::string& name); void getJoints(std::vector& joints); protected: std::string getActionName(void); void finishControllerExecution(const actionlib::SimpleClientGoalState& state); }

第二个头文件中以ActionBasedControllerHandle为基类,定义一个关节轨迹Controller的handle类:

class FollowJointTrajectoryControllerHandle : public ActionBasedControllerHandle { FollowJointTrajectoryControllerHandle(const std::string& name, const std::string& action_ns):ActionBasedControllerHandle(name, action_ns) ; bool sendTrajectory(const moveit_msgs::RobotTrajectory& trajectory); void configure(XmlRpc::XmlRpcValue& config); }

第三个头文件仍以ActionBasedControllerHandle为基类,定义一个手抓controller的handle类GripperControllerHandle。 在src目录中,有两个cpp源文件:

follow_joint_trajectory_controller_handle.cpp,对应FollowJointTrajectoryControllerHandle类中成员函数的实现。这里面最重要的函数为sendTrajectory,其传入的参数为moveit_msgs::RobotTrajectory。RobotTrajectory是一个包裹JointTrajectory类型的消息结构体。然后将JointTrajectory作为Action的goal发送给Action Server。Action Server收到该goal后就控制电机来让机器人运动起来。moveit_simple_controller_manager.cpp,这就是MoveItControllerManager插件接口的具体实现类MoveItSimpleControllerManager的源代码。在其构造函数中,首先确定ROS的参数服务器中存在/moveit_group/controller_list参数。从controller_list中取得controller的一个列表,对列表中每一个controller,获得它的名称,action的命名空间,以及controller的类型。类型包含“GripperCommand”和“FollowJointTrajectory”,所对应的handle类就分别为在前面介绍的头文件中定义的类,即GripperControllerHandle和FollowJointTrajectoryControllerHandle。然后跟据controller的类型创建对应handle类的实例。再然后,使用addJoint添加所有关节名称。 JointTrajectory消息

JointTrajectory作为轨迹规划中用来描述轨迹点信息的重要消息类型,值得介绍一下。其定义在include/trajectory_msgs/JointTrajectory.h中,它包含了如下的内容:

std_msgs/Header header uint32 seq time stamp string frame_id string[] joint_names trajectory_msgs/JointTrajectoryPoint[] points float64[] positions float64[] velocities float64[] accelerations float64[] effort duration time_from_start

frame_id并没有什么意义,不去管它。joint_names是一系列关节名的list,应该和URDF中对应的关节名称一致。另外,每次发送的命令中不必包含所有的关节,因为有些关节在当时可能是不动的。

该消息的核心部分是trajectory_msgs/JointTrajectoryPoint,对应于轨迹中的每个点,它包含了四个浮点数list和一个duration类型。对于前四个浮点数,可以使用其中的一个或多个。例如一个最小的用法就是仅指定positions。

为了控制一个七自由度机械臂的七个关节,应该提供N个包含相近positions的points。另一种方式是,points仅包含粗糙的路径点,然后再交给插值器产生精细的运动命令。

每个点中的time_from_start值指示该路径(或轨迹)点对应的时间。

尽管轨迹message可以是精细的且冗长的。通常还是将轨迹message做成粗略的,再由动作服务器(action server)来完成插值。

Setup Assistant

在使用Setup Assistant配置机器人之后,在demo.launch文件中包含move_group.launch部分,fake_execution默认是为true的,这就意味着并不执行真正操作而只是仿真。为了控制实际的机器人,我们需要将其设为false。

在move_group.launch可以看到在包含trajectory_excution.launch.xml部分,会根据fake_execution的值将moveit_controller_manager的值设为panda或fake。fake_execution的值若为false则使用panda。

再在trajectory_execution.launch.xml中包含panda_moveit_controller_manager.launch.xml或fake_moveit_controller_manager.launch.xml。

在panda_moveit_controller_manager.launch.xml文件中,即使用了moveit_simple_controller_manager/MoveItSimpleControllerManager。同时使用ros_controllers.yaml作为配置文件放入ROS参数服务器。

在ros_controllers.yaml中,可以看到如下内容:

controller_list: - name: follow_joint_trajectory_controller action_ns: follow_joint_trajectory default: True type: FollowJointTrajectory joints: - panda_joint1 - panda_joint2 - panda_joint3 - panda_joint4 - panda_joint5 - panda_joint6 - panda_joint7

当moveit启动后,根据panda_moveit_controller_manager.launch.xml加载moveIt_simple_ controller_manager,然后根据controller_list中指定的FollowJointTrajectory类型实例化FollowJointTrajectoryControllerHandle来完成关节轨迹指令的发布。

那么,现在我们经过理清了Moveit控制机械臂的流程了。

首先运行一个自己开发的Action Server用于接受轨迹运行指令。其名称必须与ros_controllers.yaml中的name指定的名字一致。然后运行move_group节点,载入机器人相关信息,并等待机器人操作节点的操控。再运行一个自己设计的机器人操作节点,连接move_group进行关节轨迹运动操作,move_group则通过moveIt_simple_ controller_manager提供的功能将运动指令以Action的形式发送给Action Server。 3用于轨迹指令接受的Action Server

为了论述的简洁性,这里只编写一个简单的框架性的Action Server节点。具体的轨迹执行并不做讨论。

在工作空间创建一个名为trajectory_test的package。在CMakeLists.txt的find_package中添加actionlib和actionlib_msgs。取消add_executable对应的行,并修改为正确的源文件。取消target_link_libraries对应的行。

然后在src目录中添加 main.cpp。其内容如下:

#include #include #include #include using namespace std; class JointTrajectoryActionServer { public: JointTrajectoryActionServer(std::string name): as_(nh_, name, false), action_name_(name) { // register callback for goal as_.registerGoalCallback(boost::bind(&JointTrajectoryActionServer::goalCallback, this)); as_.start(); } ~JointTrajectoryActionServer(void){} // when a trajectory command comes, this function will be called. void goalCallback() { boost::shared_ptr goal; goal=as_.acceptNewGoal(); cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3