Moveit控制真实机械臂(2)

前提条件,已经根据URDF文件生成了Moveit功能包,并可以正常使用Rviz仿真。

一、修改Moveit生成的文件

1、./launch/demo.launch

  <!-- Choose controller manager: fake, simple, or ros_control -->
  <arg name="moveit_controller_manager" default="fake" />

找到这一句,把fake改成simple。

感觉这一步随便改也行吧,但是simple和ros_control有预留好的接口,比较方便。如果喜欢自己起名记得之后仔细检查每个文件,都把名字改过来。

<group if="$(eval arg('moveit_controller_manager') == 'fake')">
    <!-- We do not have a real robot connected, so publish fake joint states via a joint_state_publisher
         MoveIt's fake controller's joint states are considered via the 'source_list' parameter -->
    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" unless="$(arg use_gui)">
      <rosparam param="source_list">[move_group/fake_controller_joint_states]</rosparam>
    </node>
    <!-- If desired, a GUI version is available allowing to move the simulated robot around manually
         This corresponds to moving around the real robot without the use of MoveIt. -->
    <node name="joint_state_publisher" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" if="$(arg use_gui)">
      <rosparam param="source_list">[move_group/fake_controller_joint_states]</rosparam>
    </node>

    <!-- Given the published joint states, publish tf for the robot links -->
    <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" respawn="true" output="screen" />
  </group>

这一段是留给Rviz模拟的,虚拟的机械臂会发布关节值和机器人状态,在Rviz里面显示。

上面一步已经把fake改成simple,这一段应该不会运行,保险起见还是注释掉吧,然后在下面加一行代码,发布机器人状态,关节值让真实的机械臂发布。

<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" respawn="true" output="screen" />

二、./config/simple_moveit_controllers.yaml

为什么要改这个文件呢?因为把控制器从fake改成simple后,demo.launch包含的的文件就从fake_moveit_controller_manager.launch.xml变为simple_moveit_controller_manager.launch.xml了,有兴趣可以看一眼前者里面是什么,后者如下。

<launch>
  <!-- Define the MoveIt controller manager plugin to use for trajectory execution -->
  <param name="moveit_controller_manager" value="moveit_simple_controller_manager/MoveItSimpleControllerManager" />

  <!-- Load controller list to the parameter server -->
  <rosparam file="$(find manipulator_moveit)/config/simple_moveit_controllers.yaml" />
  <rosparam file="$(find manipulator_moveit)/config/ros_controllers.yaml" />
</launch>

这里面就显示控制器参数文件是simple_moveit_controllers.yaml和ros_controllers.yaml,暂时不知道为什么包含了两个,总之改前面一个吧,这个文件也预留好了(上面要是自己起的名字,这种文件就要自己创建一个了,可能还有其它的bug,没试过)。

进去之后发现应该是空的,改成下面这样就行。

controller_list:
  - name: Manipulator_controller
    action_ns: follow_joint_trajectory
    type: FollowJointTrajectory
    default: True
    joints:
      - Joint_1
      - Joint_2
      - Joint_3
      - Joint_4
      - Joint_5
      - Joint_6

有几个注意事项:

(1)name:应该可以随便写的,我暂时没遇到什么问题。

(2)action_ns:这个不能改,涉及到action通信话题,具体原因可以去看看别的文。

(3)type:暂时用FollowJointTrajectory,有其他种类,用到再学。

(4)joints:关节名字别打错了,可以去fake_moveit_controller_manager.yaml里面抄。

三、action服务器

改完之后,要自己编一个action服务器代码,实现的功能包括接受Moveit的轨迹规划路点,实时发布真实机械臂的关节位姿,把路点发布给真实机械臂执行。

由于我目前的机械臂仅支持单节点上、下位机通信,所以我把这三个功能集成到同一个节点了(因为这三个功能都要和真实机械臂通信才能实现),如果真实机械臂支持多节点通信,可以分不同节点实现。

服务器代码如下,这个由于要包含不同的库函数,借鉴一下思路就行了,硬抄没有用。

# include <ros/ros.h>
# include <actionlib/server/simple_action_server.h>
# include <control_msgs/FollowJointTrajectoryAction.h>
# include <std_msgs/Float32MultiArray.h>
# include <iostream>
# include <moveit_msgs/RobotTrajectory.h>
#include "std_msgs/String.h"

#include "Eigen/Dense"
#include "Eigen/Core"
#include "Eigen/Geometry"
#include "Eigen/StdVector"

#include "robot_msgs/Move.h"
#include "std_srvs/Empty.h"
#include "std_srvs/SetBool.h"
#include "robot_msgs/RobotMsg.h"
#include "robot_msgs/SetUserFrame.h"
#include "robot_msgs/SetTcp.h"
#include "robot_msgs/SetLoad.h"
#include "robot_msgs/ServoL.h"
#include "robot_msgs/ClearErr.h"
#include "robot_msgs/SetCollision.h"
#include "robot_msgs/SetAxis.h"

#include "sensor_msgs/JointState.h"
#include "geometry_msgs/Twist.h"
#include "geometry_msgs/TwistStamped.h"

#include <pthread.h>
#include <unistd.h>
#include <sstream>

#include <vector>

#include "libs/robot.h"
#include "libs/conversion.h"
#include "time.h"
#include <map>
#include <string>

using namespace std;
JAKAZuRobot robot;
// 重命名类型为 Server
typedef actionlib::SimpleActionServer<control_msgs::FollowJointTrajectoryAction> Server;

// 用于存储 moveit 发送出来的轨迹数据
moveit_msgs::RobotTrajectory moveit_tra;
void execute_callback(const control_msgs::FollowJointTrajectoryGoalConstPtr& goalPtr, Server* moveit_server)
{
    // 1、解析提交的目标值
    int n_joints = goalPtr->trajectory.joint_names.size();
    int n_tra_Points = goalPtr->trajectory.points.size();
    JointValue* joint_pos1 = new JointValue[n_tra_Points];

    moveit_tra.joint_trajectory.header.frame_id = goalPtr->trajectory.header.frame_id;
    moveit_tra.joint_trajectory.joint_names = goalPtr->trajectory.joint_names;
    moveit_tra.joint_trajectory.points.resize(n_tra_Points);

    for(int i=0; i<n_tra_Points; i++) // 遍历每组路点
    {
        moveit_tra.joint_trajectory.points[i].positions.resize(n_joints);
        moveit_tra.joint_trajectory.points[i].velocities.resize(n_joints);
        moveit_tra.joint_trajectory.points[i].accelerations.resize(n_joints);

        moveit_tra.joint_trajectory.points[i].time_from_start = goalPtr->trajectory.points[i].time_from_start;
        for(int j=0;j<n_joints; j++) // 遍历每组路点中的每个关节数据
        {
            moveit_tra.joint_trajectory.points[i].positions[j] = goalPtr->trajectory.points[i].positions[j];
            moveit_tra.joint_trajectory.points[i].velocities[j] = goalPtr->trajectory.points[i].velocities[j];
            moveit_tra.joint_trajectory.points[i].accelerations[j] = goalPtr->trajectory.points[i].accelerations[j];
        }
        joint_pos1[i] = 
        {
            moveit_tra.joint_trajectory.points[i].positions[0],
            moveit_tra.joint_trajectory.points[i].positions[1],
            moveit_tra.joint_trajectory.points[i].positions[2],
            moveit_tra.joint_trajectory.points[i].positions[3],
            moveit_tra.joint_trajectory.points[i].positions[4],
            moveit_tra.joint_trajectory.points[i].positions[5],
        };
        // robot.joint_move(&joint_pos1, ABS, FALSE, 2,20,5,NULL);

    }

    std::cout << "The trajectory data is:" << "********************************************" << endl;
    std::cout << moveit_tra;
    std::cout << "********************************************" << "The trajectory data is finished printing." << endl;
    ROS_INFO("The number of joints is %d.",n_joints);
    ROS_INFO("The waypoints number of the trajectory is %d.",n_tra_Points);
    ROS_INFO("Receive trajectory successfully");
    BOOL in_pos;
    for (int k = 0; k < n_tra_Points; k++)
    {
        robot.joint_move(&joint_pos1[k], ABS, FALSE,20,5,1,NULL);
    }
    // while (1)
    // {
    //     robot.is_in_pos(&in_pos);
    //     if (in_pos == TRUE)
    //     {
    //         PoseStop.publish(in_pos);
    //         break;
    //     }
    // }
    
    delete [] joint_pos1;
    moveit_server->setSucceeded();
   
}
void joint_states_callback(ros::Publisher joint_states_pub)
{
    //        clock_t t1 = clock();

    sensor_msgs::JointState joint_states;
    JointValue joint_pose;

    //        joint_states.position.clear(); // clear position vector
    robot.get_joint_position(&joint_pose); // get current joint pose
  //
    // joint_pose.jVal[0] = 0;
    // joint_pose.jVal[1] = 1;
    // joint_pose.jVal[2] = 2;
    // joint_pose.jVal[3] = 3;
    // joint_pose.jVal[4] = 4;
    // joint_pose.jVal[5] = 5;
//
    for(int i = 0; i < 6; i++)
    {
        joint_states.position.push_back(joint_pose.jVal[i]); // write data into standard ros msg
        int j = i+1;
        joint_states.name.push_back("joint_"+std::to_string(j));
        joint_states.header.stamp = ros::Time::now();
    }

    joint_states_pub.publish(joint_states); // publish data

    //        cout << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << endl;
}



int main(int argc, char *argv[])
{
    ros::init(argc,argv,"moveit_action_server");
    ros::AsyncSpinner spinner(2);
    spinner.start();
    std::cout << robot.login_in("10.5.5.100") << std::endl;
    robot.power_on();
    robot.enable_robot();
    ros::NodeHandle nh;
    ros::Publisher joint_states_pub = nh.advertise<sensor_msgs::JointState>("/joint_states", 10);
    ros::Publisher PoseStop = nh.advertise<std_msgs::String>("/PoseStop",10);
    // 创建 action 对象(NodeHandle,话题名称,回调函数解析传入的目标值,服务器是否自启动)
    Server moveit_server(nh,"jaka_controller/follow_joint_trajectory", boost::bind(&execute_callback, _1, &moveit_server), false);
    // 手动启动服务器
    moveit_server.start();
    // ros::Rate rate(5);
        while (ros::ok())
    {   
        joint_states_callback(joint_states_pub);
        
        ros::spinOnce();
        // rate.sleep();
    }
    ros::spin();
    return 0;
}

接下来要编写连续规划和运动的程序了,毕竟用Rviz只能单次运行,要实现多段连续运动。

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值