实现机械臂抓取Marker,并放置到指定位置

10 篇文章 2 订阅

实现机械臂抓取Marker,并放置到指定位置

1. Version-1 Program

  1. 实现了kinova的end effector随Marker的移动而移动
  2. 仍需改进的地方
    (1)代码结构凌乱,可以引入类来提高代码的整洁与可读性。
    (2)实现kinova抓取Marker并可以将其放置到指定位置的demo
#include "ros/ros.h"
#include<iostream> //C++标准输入输出库 
#include <vector>
#include "std_msgs/String.h"
#include "geometry_msgs/PoseStamped.h"
#include <kinova_msgs/ArmPoseActionGoal.h> // 注意格式源文件名字为ArmPose.action
#include <ros/ros.h>
#include <kinova_driver/kinova_ros_types.h>

#include <actionlib/client/simple_action_client.h>
#include <kinova_msgs/SetFingersPositionAction.h>
#include <kinova_msgs/ArmPoseAction.h>
#include <kinova_msgs/HomeArm.h>
#include <kinova_msgs/ArmJointAnglesAction.h>

const int FINGER_MAX = 6400;

bool cartesian_pose_client(float x, float y, float z, float qx, float qy, float qz, float qw)//四元数
{


    actionlib::SimpleActionClient <kinova_msgs::ArmPoseAction> *client = new actionlib::SimpleActionClient<kinova_msgs::ArmPoseAction>(
            "/j2n6s300_driver/pose_action/tool_pose");//取的主题

    client->waitForServer();

    kinova_msgs::ArmPoseGoal pose_goal;//注意形式ArmPose.action
    pose_goal.pose.header.frame_id = "j2n6s300_link_base";

    pose_goal.pose.pose.position.x = x;
    pose_goal.pose.pose.position.y = y;
    pose_goal.pose.pose.position.z = z;

    pose_goal.pose.pose.orientation.x = qx;
    pose_goal.pose.pose.orientation.y = qy;
    pose_goal.pose.pose.orientation.z = qz;
    pose_goal.pose.pose.orientation.w = qw;


    client->sendGoal(pose_goal);


    if (client->waitForResult(ros::Duration(150.0)))//延时得高机械臂不会发送,只能自己检测坐标,奇异值也不会告诉所有信息都通过主题反馈
    {
        client->getResult();
        return true;
    } else {
        client->cancelAllGoals();
        ROS_WARN_STREAM("The gripper action timed-out");
        return false;
    }

}

bool finger_control_client(float finger1, float finger2, float finger3)//0-1
{


    actionlib::SimpleActionClient <kinova_msgs::SetFingersPositionAction> *finger_client = new actionlib::SimpleActionClient<kinova_msgs::SetFingersPositionAction>(
            "j2n6s300_driver/fingers_action/finger_positions");

    finger_client->waitForServer();

    kinova_msgs::SetFingersPositionGoal finger_goal;

    finger_goal.fingers.finger1 = finger1 * FINGER_MAX;
    finger_goal.fingers.finger2 = finger2 * FINGER_MAX;
    finger_goal.fingers.finger3 = finger3 * FINGER_MAX;


    finger_client->sendGoal(finger_goal);


    if (finger_client->waitForResult(ros::Duration(100.0))) {
        finger_client->getResult();
        return true;
    } else {
        finger_client->cancelAllGoals();
        ROS_WARN_STREAM("The gripper action timed-out");
        return false;
    }

}

void MarkerCallback(const geometry_msgs::PoseStamped::ConstPtr& msg)
{
    float Tf_Mat[4][4];

    const float tf[16] = {0.9998, -0.0143, 0.0161, -0.002768, -0.0149, -0.9991, 0.0402, -0.56808, 0.0155, -0.0404, -0.9991, 1.09819, 0, 0, 0, 1};
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            Tf_Mat[i][j] = tf[i*4+j];

        }
    }
//    ROS_INFO("I heard the pose from the robot"); 
    ROS_INFO("the marker pose with cam_frame position(x,y,z) is %f , %f, %f", msg->pose.position.x, msg->pose.position.y, msg->pose.position.z);


    std::cout<<"\n \n"<<std::endl; 
    float x, y, z, qx, qy, qz, qw, finger1, finger2, finger3, p[4], pm[4] = {msg->pose.position.x, msg->pose.position.y,  msg->pose.position.z, 1};
    ROS_INFO("the marker pose with pm position(x,y,z) is %f , %f, %f", pm[0], pm[1], pm[2]);

    for (int i = 0; i < 4; ++i) {
        p[i] = Tf_Mat[i][0]*pm[0]+Tf_Mat[i][1]*pm[1]+Tf_Mat[i][2]*pm[2]+Tf_Mat[i][3]*pm[3];
    }
    x=p[0];
    y=p[1];//y可能需要补偿4cm y的原值为-0.528081440518
    z=0.2582;
    qx=0.999739147086;
    qy=-0.00729168962601;
    qz=0.00791491117064;
    qw=0.0201450546611;
    finger1 = finger2 = 0;
    finger3 = 0;


    try {

        bool result = cartesian_pose_client(x, y, z, qx, qy, qz, qw);
        if (result) {
            bool finger_re = finger_control_client(finger1, finger2, finger3);

            ROS_INFO("Cartesian pose sent! %f , %f, %f", x, y, z);
            if (finger_re)ROS_INFO("finger move!.");
        }
    }
    catch (ros::Exception) {
        ROS_INFO("program interrupted before completion.");
    }
}

int main(int argc, char **argv) {


    ros::init(argc, argv, "paragram1");
    ros::NodeHandle node_handle;

    ros::ServiceClient start_to_home = node_handle.serviceClient<kinova_msgs::HomeArm>("j2n6s300_driver/in/home_arm");

    kinova_msgs::HomeArm srv;

    try {

        start_to_home.call(srv);
        ROS_INFO("go to home");

    }
    catch (ros::Exception) {
        ROS_INFO("Failed to HOme.");
    }
    ros::Subscriber Marke_sub = node_handle.subscribe("aruco_single/pose", 1, MarkerCallback);
    ros::spin();
    return 0;
}

2. Version-2 Program

  1. Record several kinova end effector oriention:
    (1) 记录了一个当前的Marker
    在这里插入图片描述
    (2)End effector竖直向下的oriention:
    qx=0.999739147086;
    qy=-0.00729168962601;
    qz=0.00791491117064;
    qw=0.0201450546611;

    (3) End effector 水平向前的oriention:
    在这里插入图片描述
    (4) Marker 最终放置位置:
    在这里插入图片描述

代码:

#include "ros/ros.h"
#include <cstdlib> 
#include "std_msgs/Float64.h"
#include <unistd.h>
#include<iostream> //C++标准输入输出库 
#include <vector>
#include "std_msgs/String.h"
#include "geometry_msgs/PoseStamped.h"
#include <kinova_msgs/ArmPoseActionGoal.h> // 注意格式源文件名字为ArmPose.action
#include <ros/ros.h>
#include <kinova_driver/kinova_ros_types.h>

#include <actionlib/client/simple_action_client.h>
#include <kinova_msgs/SetFingersPositionAction.h>
#include <kinova_msgs/ArmPoseAction.h>
#include <kinova_msgs/HomeArm.h>
#include <kinova_msgs/ArmJointAnglesAction.h>

const int FINGER_MAX = 6400;

class tl1{
public:
    tl1();
    void registerNodeHandle(ros::NodeHandle& _nh);
    void registerSub();
    void registerSrv();
    void MarkerCallback(const geometry_msgs::PoseStamped::ConstPtr& msg);
    bool cartesian_pose_client(float x, float y, float z, float qx, float qy, float qz, float qw);
    bool finger_control_client(float finger1, float finger2, float finger3);
    void GotoHome(kinova_msgs::HomeArm& _srv);
private:
    ros::Subscriber Marke_sub;
    ros::NodeHandle nh;
    ros::ServiceClient start_to_home;
};

int main(int argc, char **argv) {


    ros::init(argc, argv, "paragram1");
    ros::NodeHandle node_handle;

    tl1 loandmove;
    kinova_msgs::HomeArm srv;

    loandmove.registerNodeHandle(node_handle);

    loandmove.registerSrv();
    loandmove.GotoHome(srv);
    loandmove.registerSub();





    ros::spin();
    return 0;
}


tl1::tl1(){};

void tl1::registerNodeHandle(ros::NodeHandle& _nh){
    nh = _nh;
};

void tl1::registerSub(){

    Marke_sub = nh.subscribe("aruco_single/pose", 1, &tl1::MarkerCallback, this); //this pointer here means the class itself


};

void tl1::registerSrv(){

    start_to_home = nh.serviceClient<kinova_msgs::HomeArm>("j2n6s300_driver/in/home_arm");
};
bool tl1::cartesian_pose_client(float x, float y, float z, float qx, float qy, float qz, float qw)//四元数
{
    actionlib::SimpleActionClient <kinova_msgs::ArmPoseAction> *client = new actionlib::SimpleActionClient<kinova_msgs::ArmPoseAction>(
            "/j2n6s300_driver/pose_action/tool_pose");//取的主题

    client->waitForServer();

    kinova_msgs::ArmPoseGoal pose_goal;//注意形式ArmPose.action
    pose_goal.pose.header.frame_id = "j2n6s300_link_base";

    pose_goal.pose.pose.position.x = x;
    pose_goal.pose.pose.position.y = y;
    pose_goal.pose.pose.position.z = z;

    pose_goal.pose.pose.orientation.x = qx;
    pose_goal.pose.pose.orientation.y = qy;
    pose_goal.pose.pose.orientation.z = qz;
    pose_goal.pose.pose.orientation.w = qw;


    client->sendGoal(pose_goal);


    if (client->waitForResult(ros::Duration(200.0)))//延时得高机械臂不会发送,只能自己检测坐标,奇异值也不会告诉所有信息都通过主题反馈
    {
        client->getResult();
        return true;
    } else {
        client->cancelAllGoals();
        ROS_WARN_STREAM("The gripper action timed-out");
        return false;
    }

}

bool tl1::finger_control_client(float finger1, float finger2, float finger3)//0-1
{


    actionlib::SimpleActionClient <kinova_msgs::SetFingersPositionAction> *finger_client = new actionlib::SimpleActionClient<kinova_msgs::SetFingersPositionAction>(
            "j2n6s300_driver/fingers_action/finger_positions");

    finger_client->waitForServer();

    kinova_msgs::SetFingersPositionGoal finger_goal;

    finger_goal.fingers.finger1 = finger1 * FINGER_MAX;
    finger_goal.fingers.finger2 = finger2 * FINGER_MAX;
    finger_goal.fingers.finger3 = finger3 * FINGER_MAX;


    finger_client->sendGoal(finger_goal);


    if (finger_client->waitForResult(ros::Duration(200.0))) {
        finger_client->getResult();
        return true;
    } else {
        finger_client->cancelAllGoals();
        ROS_WARN_STREAM("The gripper action timed-out");
        return false;
    }

}

void tl1::MarkerCallback(const geometry_msgs::PoseStamped::ConstPtr& msg)
{
    float Tf_Mat[4][4];

    const float tf[16] = {0.9998, -0.0143, 0.0161, -0.002768, -0.0149, -0.9991, 0.0402, -0.56808, 0.0155, -0.0404, -0.9991, 1.09819, 0, 0, 0, 1};
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            Tf_Mat[i][j] = tf[i*4+j];

        }
    }

    ROS_INFO("the marker pose with cam_frame position(x,y,z) is %f , %f, %f", msg->pose.position.x, msg->pose.position.y, msg->pose.position.z);

    std::cout<<"\n \n"<<std::endl; //add two more blank row so that we can see the message more clearly

    float x, y, z, qx, qy, qz, qw, finger1, finger2, finger3, p[4], pm[4] = {msg->pose.position.x, msg->pose.position.y,  msg->pose.position.z, 1};
    ROS_INFO("the marker pose with pm position(x,y,z) is %f , %f, %f", pm[0], pm[1], pm[2]);

    for (int i = 0; i < 4; ++i) {
        p[i] = Tf_Mat[i][0]*pm[0]+Tf_Mat[i][1]*pm[1]+Tf_Mat[i][2]*pm[2]+Tf_Mat[i][3]*pm[3];
    }
    x=p[0];
    y=p[1];//y可能需要补偿4cm y的原值为-0.528081440518
    z=p[2]+0.1;
    qx=0.7041;
    qy=0.01358;
    qz=0.07847;
    qw=0.7056;
    finger1 = finger2 = finger3 = 0;


    try {

        bool result = cartesian_pose_client(x, y, z, qx, qy, qz, qw);
        if (result) {
            bool finger_re = finger_control_client(finger1, finger2, finger3);

            ROS_INFO("Move to Marker up! %f , %f, %f", x, y, z);
            if (finger_re)ROS_INFO("finger move!.");
        }
    }
    catch (ros::Exception) {
        ROS_INFO("program interrupted before completion.");
    }

    x=p[0];
    y=p[1];//y可能需要补偿4cm y的原值为-0.528081440518
    z=p[2]-0.03;
    qx=0.7041;
    qy=0.01358;
    qz=0.07847;
    qw=0.7056;
    finger1 = finger2 = finger3 = 1;


    try {

        bool result = cartesian_pose_client(x, y, z, qx, qy, qz, qw);
        if (result) {
            bool finger_re = finger_control_client(finger1, finger2, finger3);

            ROS_INFO("Catch the Marker! %f , %f, %f", x, y, z);
            if (finger_re)ROS_INFO("finger move!.");
        }
    }
    catch (ros::Exception) {
        ROS_INFO("program interrupted before completion.");
    }

    kinova_msgs::HomeArm srv;
    
    GotoHome(srv);

    x= 0.472484827042;
    y= -0.172647804022;
    z= 0.0302095841616;

    qx= -0.0346102192998;
    qy= -0.999143242836;
    qz= -0.00137171335518;
    qw= -0.0226511508226;
    finger1 = finger2 = finger3 = 0;


    try {

        bool result = cartesian_pose_client(x, y, z, qx, qy, qz, qw);
        if (result) {
            bool finger_re = finger_control_client(finger1, finger2, finger3);

            ROS_INFO("Marker move to final pose! %f , %f, %f", x, y, z);
            if (finger_re)ROS_INFO("finger open!.");
        }
    }
    catch (ros::Exception) {
        ROS_INFO("program interrupted before completion.");
    }
exit(0);
}

void tl1::GotoHome(kinova_msgs::HomeArm& _srv)
{

    kinova_msgs::HomeArm srv;

    try {

        start_to_home.call(srv);
        ROS_INFO("go to home");

    }
    catch (ros::Exception) {
        ROS_INFO("Failed to HOme.");
    }
}
  1. 代码更加简练,把几乎所有的函数变量都定义到类里面。
  2. 主题订阅中的函数callback仍然太繁琐,仍然需要精简!
  • 3
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值