精华内容
下载资源
问答
  • ROS机械臂视觉抓取

    2021-04-20 10:10:14
    ROS机械臂视觉抓取 一、总述 视觉抓取主要是通过改变机器人的tool坐标系或base坐标系来实现的。物体位置的变化主要是它位置的X,Y,Z 方向的变化。而base坐标系可根据需要定义用户坐标系。当机器人配备多个工作台时,...

    ROS机械臂视觉抓取

    一、总述

    视觉抓取主要是通过改变机器人的tool坐标系或base坐标系来实现的。物体位置的变化主要是它位置的X,Y,Z 方向的变化。而base坐标系可根据需要定义用户坐标系。当机器人配备多个工作台时,选择用户坐标系可使操作更为简单 。
    在实际应用中,我们通常需要将相机观察到的外界环境中物体的姿态从相机坐标系转换到机械臂的坐标系中,辅助机械臂规划一些后续动作(如抓取)。为了得到机器人坐标系和相机坐标系的转换矩阵,我们还需要对机器人进行手眼标定。

    二、视觉抓取中的关键技术

    众所周知,无论将摄像头安装在机械臂上,还是固定在周围环境中,都需要确定相机和机械臂本身的位置关系,视觉识别方面不仅要完成物体位置的识别,还需要分析抓取姿态。
    而其中涉及的关键技术,主要是以下四个方面,与此同时ROS针对这些关键技术提供相应的功能包支持。
    参考网址:https://zhuanlan.zhihu.com/p/63757762

    1、手眼标定

    手眼标定即相机内参和外参的标定,其中内参标定使用camera_calibration功能包实现相机内参标定的过程。可参考博客:https://blog.csdn.net/weixin_45661757/article/details/113256274
    手眼标定外参标定分为两种方式:眼在手上(eye in hand)、眼在手外(eye to hand)。

    • eye-in-hand 眼在手上:相机固定在机器人末端。这种情况下,需要将标定板固定在地面上,机器人坐标系和标定板坐标系的转换关系始终不变。求解的量为相机坐标和机器人末端坐标系的位姿关系。
      在这里插入图片描述
    • eye-to-hand 眼在手外:相机固定在机器人外的固定底座上。这种情况下,需要将标定板固定在机器人末端,求解的量为相机坐标系和机器人坐标系之间的位姿关系。
      在这里插入图片描述注:推导过程参考网址:
      https://zhuanlan.zhihu.com/p/78855930
      https://zhuanlan.zhihu.com/p/93183788
      https://yongqi.blog.csdn.net/article/details/107421641
      https://blog.csdn.net/zxxxiazai/article/details/107979149
      https://blog.csdn.net/qq_34935373/article/details/103727968?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-12.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-12.control

    2、物体识别与定位

    视觉抓取中非常重要的一个部分就是对抓取物体的识别,无论是二维图像还是三维点云,在ROS中都可以找到对应的功能包,如果需要机器学习的话,也可以集成Tensorflow轻松实现。
    ROS功能包

    • find_object_2d:http://wiki.ros.org/object_recognition
    • Tensorflow Object Detection API:https://github.com/tensorflow/models/tree/master/research/object_detection
    • object_recognition:http://wiki.ros.org/object_recognition

    3、抓取姿态分析

    抓取姿态分析是视觉抓取中的一个难点,众所周知生活中物体种类和摆放场景的复杂度太高,谷歌曾尝试用几十台机械臂进行抓取训练,最终还是由于无法大规模推广而放弃,可以尝试ROS中这些姿态分析的功能包。
    ROS功能包

    • agile_grasp:http://wiki.ros.org/agile_grasp
    • graspit:http://wiki.ros.org/graspit
    • moveit_simple_grasps:http://wiki.ros.org/moveit_simple_grasps

    4、运动规划

    Moveit!为开发者提供了一个易于使用的集成化开发平台。由一系列移动操作的功能包组成,包括运动规划、操作控制、3D感知、运动学、控制与导航算法等。这些功能算法的实现都是通过插件的方式在Moveit!中集成,并提供友好的GUI,,可广泛应用于工业、商业、研发和其他领域。
    参考博客
    https://blog.csdn.net/weixin_45661757/article/details/109991238
    https://blog.csdn.net/weixin_45661757/article/details/110005283

    展开全文
  • 使用越疆科技的M1-B1机器人进行ROS下移动加机械臂视觉抓取代码 #include "ros/ros.h" #include "ar_track_alvar_msgs/AlvarMarkers.h" #include "iostream" #include "stdio.h" #include "cv.h" #include ...

    使用越疆科技的M1-B1机器人进行ROS下移动加机械臂加视觉抓取代码 

    #include "ros/ros.h"
    #include "ar_track_alvar_msgs/AlvarMarkers.h"
    #include "iostream"
    #include "stdio.h"
    #include "cv.h"
    #include "opencv2/opencv.hpp"
    #include "cv_bridge/cv_bridge.h"
    #include <unistd.h>
    #include <nav_msgs/Odometry.h>
    #include <string.h>
    #include <move_base_msgs/MoveBaseAction.h>
    #include <actionlib/client/simple_action_client.h>
    #include <cmath>
    
    #include "std_msgs/String.h"
    #include "dobot/SetCmdTimeout.h"
    #include "dobot/SetQueuedCmdClear.h"
    #include "dobot/SetQueuedCmdStartExec.h"
    #include "dobot/SetQueuedCmdForceStopExec.h"
    #include "dobot/GetDeviceVersion.h"
    
    #include "dobot/SetEndEffectorParams.h"
    #include "dobot/SetPTPJointParams.h"
    #include "dobot/SetPTPCoordinateParams.h"
    #include "dobot/SetPTPJumpParams.h"
    #include "dobot/SetPTPCommonParams.h"
    #include "dobot/SetPTPCmd.h"
    #include "dobot/SetEndEffectorGripper.h"
    #include "dobot/SetHOMECmd.h"
    #include "dobot/SetHOMEParams.h"
    #include "dobot/SetIODO.h"
    #include "dobot/GetAlarmsState.h"
    #include "dobot/ClearAllAlarmsState.h"
    
    
    using namespace std;
    using namespace cv;
    
    
    
    相机区域
    //机械臂拍照点位
    float picture_x = 237.633
        , picture_y = 60.6892
        , picture_z = 230.7879
    ;
    
    //标定像素坐标 3个点
    float cam_x1 = 159.387
        , cam_y1 = -21.6633
    
        , cam_x2 = 34.927
        , cam_y2 = 40.634
    
        , cam_x3 = 165.001
        , cam_y3 = 81.35
    ;
    
    //标定机械包坐标 3个点
    float rob_x1 = 327.7778
        , rob_y1 = -78.2467
    
        , rob_x2 = 357.0341
        , rob_y2 = 43.5529
        
        , rob_x3 = 250.8334
        , rob_y3 = -21.1507
    ;
    
    //标定像素坐标 3个点
    Mat A = (Mat_<float>(3,3) <<
    	cam_x1, cam_y1, 1,
    	cam_x2, cam_y2, 1,
    	cam_x3, cam_y3, 1
    	); //3×3
    	
    //标定机械包坐标 3个点
    Mat B = (Mat_<float>(3,3) <<
    	rob_x1, rob_y1, 1,
    	rob_x2, rob_y2, 1,
    	rob_x3, rob_y3, 1
    	); //3×3
    
    //矩阵参数
    Mat X;
    
    
    //相机得到图像的坐标和ID
    int   ar_ID;
    float cam_getX;
    float cam_getY;
    	
    //机械臂最后执行的点位
    float X_pose;
    float Y_pose;
    float Z_pose = 155.9403;
    
    //服务注册
    ros::ServiceClient client;
    ros::ServiceClient clientPTP;
    ros::ServiceClient clientIO;
    
    //函数声明
    void robot_pose(Mat X);
    void setIO(uint8_t address, uint8_t level, bool isQueued, ros::ServiceClient client);
    void setPTP(uint8_t ptpMode ,float x, float y, float z, float r, ros::ServiceClient client);
    int getState(ros::ServiceClient client);
    int ClearState(ros::ServiceClient client);
    void sub_ar_callback(const ar_track_alvar_msgs::AlvarMarkers::ConstPtr& msg);
    
    //回调函数获取二维码的位置
    void sub_ar_callback(const ar_track_alvar_msgs::AlvarMarkers::ConstPtr& msg)
    {
    ros::ServiceClient client;
     	cout<<"回调函数获取二维码的位置"	<<endl;
    	//if((msg->markers.size() > 0) && (msg->markers[0].id < 30) )
    	if(msg->markers.size() > 0 && (msg->markers[0].id < 30) )
    	{
    	ar_ID = msg->markers[0].id;
    	cam_getX = msg->markers[0].pose.pose.position.x*1000;
    	cam_getY = msg->markers[0].pose.pose.position.y*1000;
    
    	cout<<"获取二维码的位置"<<endl<<"二维码ID:"<<ar_ID<<endl;
    	cout<<"Point position:"<<endl;
    	cout<<"cam_getX: "<<cam_getX<<endl;
    	cout<<"cam_getY: "<<cam_getY<<endl;
    	cout<<"-----------"<<endl;
    	} 
    
    	//获取机器人抓取位置
    	robot_pose(X);
    
    	
    }
    
    //矩阵变换函数(只是开始调用一次,求出矩阵参数X)
    Mat solve_equation(Mat A, Mat B)
    {
    	//矩阵转换公式
    	solve(A, B, X, CV_SVD);
    	cout<<"矩阵转换完成,参数X:"<<endl<<X<<endl;
    	return X;
    }
    
    //机器人抓取位置函数
    void robot_pose(Mat X)
    {
    	cout<<"cam_getX"<<cam_getX<<endl;
    	cout<<"cam_getY"<<cam_getY<<endl;
    	//相机得到图像的坐标来计算机械臂点位
    	Mat cam_pose = (Mat_<float>(1,3) << cam_getX, cam_getY, 1);
    	//通过矩阵变换得到机器人抓取的物理坐标
    	Mat rot_pose = cam_pose*X; 
    	
    	//机械臂抓取点位输出
    	X_pose = rot_pose.at<float>(0);
    	Y_pose = rot_pose.at<float>(1);
    	cout<<"抓取点位:"<<endl;
    	cout<<"X_pose:"<<X_pose<<endl;
    	cout<<"Y_pose:"<<Y_pose<<endl;	
    
    	//运行到抓取点位PTP
    	setPTP(0 ,X_pose ,Y_pose ,Z_pose ,0 , clientPTP);
    
    	//开启气泵setIO	
    	setIO(18,0,1,clientIO);
    	setIO(17,1,1,clientIO);
    
    	//运行到拍照点位PTP
    	setPTP(0 ,picture_x ,picture_y ,picture_z ,0 , clientPTP);
    
    	//关闭气泵setIO	
    	//setIO(18,1,1,clientIO);
    	//setIO(17,1,1,clientIO);
    		
    }
    相机区域
    /机械臂区域
    
    
    //清除系统所有报警
    int ClearState(ros::ServiceClient client) 
    {
    	dobot::ClearAllAlarmsState srv;
    	client.call(srv);
    }
    
    //获取系统报警状态
    int getState(ros::ServiceClient client)
    {
    	dobot::GetAlarmsState srv;
    	client.call(srv);
    	cout<<"State result: "<<srv.response.result<<endl;
    	cout<<"size_alarmsState:"<<srv.response.alarmsState.size()<<endl;
    	for(int i = 0; i<srv.response.alarmsState.size(); i++)
    	{
    		cout<<srv.response.alarmsState[i];
    	}
    	cout<<"end  "<<endl;
    	//cout<<"State alarmsState: "<<srv.response.alarmsState[0]<<endl;
    }
    
    //执行 PTP 指令
    void setPTP(uint8_t ptpMode ,float x, float y, float z, float r, ros::ServiceClient client)
    {
    	dobot::SetPTPCmd srv;
    	srv.request.ptpMode = ptpMode;
            srv.request.x = x;
            srv.request.y = y;
            srv.request.z = z;
            srv.request.r = r;
            client.call(srv);   
    }
    
    //设置 I/O 输出电平
    void setIO(uint8_t address, uint8_t level, bool isQueued, ros::ServiceClient client)
    {
    	dobot::SetIODO IO;
    	IO.request.address = address;
    	IO.request.level = level;
    	IO.request.isQueued = isQueued;
    	client.call(IO);
    	ROS_INFO("SetIODO%d ok, %d", IO.request.address , IO.response.queuedCmdIndex);
    }
    /机械臂区域
    
    //调用拍照和机械臂抓取部分
    void cam_pick()
    {
    	ros::Rate loop_rate(0.5);
    	int i = 1;
    	while(i >= 0 && ros::ok())
    	{
    		ros::spinOnce();
    		i = i-1;
    		cout<<"call :"<<i<<endl;
    		loop_rate.sleep();
    	}	
    }
    
    //机械臂放置物料函数
    void robot_place()
    {
    	//关闭气泵setIO	
    	setIO(18,1,1,clientIO);
    	setIO(17,1,1,clientIO);
    		
    }
    
    int main(int argc, char** argv)
    {
    	ros::init(argc, argv, "cam_robot_sent_pose");
    	ros::NodeHandle n;
    
    	//订阅move_base操作服务器
    	actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> ac("move_base",true);
    
    	//设置我们要机器人走的几个点。
    	geometry_msgs::Point point;
    	geometry_msgs::Quaternion quaternion;
    	geometry_msgs::Pose pose_list1;
    	geometry_msgs::Pose pose_list2;
    	
    	point.x = -0.174;
    	point.y = -0.921;
    	point.z = 0.000;
    	quaternion.x = 0.000;
    	quaternion.y = 0.000;
    	quaternion.z = -0.728;
    	quaternion.w = 0.684;
    	pose_list1.position = point;
    	pose_list1.orientation = quaternion;
    	
    	point.x = 1.842;
    	point.y = 0.893;
    	point.z = 0.000;
    	quaternion.x = 0.000;
    	quaternion.y = 0.000;
    	quaternion.z = -0.0331;
    	quaternion.w = 0.999;
    	pose_list2.position = point;
    	pose_list2.orientation = quaternion;
    
    
        // SetCmdTimeout
        client = n.serviceClient<dobot::SetCmdTimeout>("/DobotServer/SetCmdTimeout");
        dobot::SetCmdTimeout srv1;
        srv1.request.timeout = 3000;
        if (client.call(srv1) == false) {
            ROS_ERROR("Failed to call SetCmdTimeout. Maybe DobotServer isn't started yet!");
            return -1;
        }
    
        // Clear the command queue
        client = n.serviceClient<dobot::SetQueuedCmdClear>("/DobotServer/SetQueuedCmdClear");
        dobot::SetQueuedCmdClear srv2;
        client.call(srv2);
    
        // Start running the command queue
        client = n.serviceClient<dobot::SetQueuedCmdStartExec>("/DobotServer/SetQueuedCmdStartExec");
        dobot::SetQueuedCmdStartExec srv3;
        client.call(srv3);
    
        // Get device version information
        client = n.serviceClient<dobot::GetDeviceVersion>("/DobotServer/GetDeviceVersion");
        dobot::GetDeviceVersion srv4;
        client.call(srv4);
        if (srv4.response.result == 0) {
            ROS_INFO("Device version:%d.%d.%d", srv4.response.majorVersion, srv4.response.minorVersion, srv4.response.revision);
        } else {
            ROS_ERROR("Failed to get device version information!");
        }
    
        // Set PTP joint parameters
        do {
            client = n.serviceClient<dobot::SetPTPJointParams>("/DobotServer/SetPTPJointParams");
            dobot::SetPTPJointParams srv;
    
            for (int i = 0; i < 4; i++) {
                srv.request.velocity.push_back(100);
            }
            for (int i = 0; i < 4; i++) {
                srv.request.acceleration.push_back(100);
            }
            client.call(srv);
        } while (0);
    
        // Set PTP coordinate parameters
        do {
            client = n.serviceClient<dobot::SetPTPCoordinateParams>("/DobotServer/SetPTPCoordinateParams");
            dobot::SetPTPCoordinateParams srv;
    
            srv.request.xyzVelocity = 100;
            srv.request.xyzAcceleration = 100;
            srv.request.rVelocity = 100;
            srv.request.rAcceleration = 100;
            client.call(srv);
        } while (0);
    
        // Set PTP jump parameters
        do {
            client = n.serviceClient<dobot::SetPTPJumpParams>("/DobotServer/SetPTPJumpParams");
            dobot::SetPTPJumpParams srv;
    
            srv.request.jumpHeight = 20;
            srv.request.zLimit = 200;
            client.call(srv);
        } while (0);
    
        // Set PTP common parameters
        do {
            client = n.serviceClient<dobot::SetPTPCommonParams>("/DobotServer/SetPTPCommonParams");
            dobot::SetPTPCommonParams srv;
    
            srv.request.velocityRatio = 50;
            srv.request.accelerationRatio = 50;
            client.call(srv);
        } while (0);
    
    
    	//运行到拍照点位PTP
    	client = n.serviceClient<dobot::SetPTPCmd>("/DobotServer/SetPTPCmd");
    	setPTP(0 ,picture_x ,picture_y ,picture_z ,0 , client);
    	//运行到抓取点位PTP
    	clientPTP = n.serviceClient<dobot::SetPTPCmd>("/DobotServer/SetPTPCmd");
    	//开启气泵setIO	
    	clientIO = n.serviceClient<dobot::SetIODO>("/DobotServer/SetIODO");
    
    
    	cout<<"机械臂准备完成请按下空格键开始检测"<<endl;
    	getchar();
    
    	//矩阵变换函数
    	solve_equation(A, B);
    	cout<<"sub"<<endl;
    
    
    ///导航开始部分
     	ROS_INFO("Waiting for move_base action server...");
      	//等待60秒以使操作服务器可用
      	if(!ac.waitForServer(ros::Duration(60)))
      	{
       	 	ROS_INFO("Can't connected to move base server");
    		exit(-1);
     	 }
     	 ROS_INFO("Connected to move base server");
     	 ROS_INFO("Starting navigation test");
    
             //初始化航点目标 去抓取点
             move_base_msgs::MoveBaseGoal goal1;
    
             //使用地图框定义目标姿势
             goal1.target_pose.header.frame_id = "map";
    
             //将时间戳设置为“now”
             goal1.target_pose.header.stamp = ros::Time::now();
    
            //将目标姿势设置为第i个航点
            goal1.target_pose.pose = pose_list1;
    
            //让机器人向目标移动
            //将目标姿势发送到MoveBaseAction服务器
            ac.sendGoal(goal1);
    
            //等3分钟到达那里
            bool finished_within_time1 = ac.waitForResult(ros::Duration(180));
    
            //如果我们没有及时赶到那里,就会中止目标
            if(!finished_within_time1)
            {
                ac.cancelGoal();
                ROS_INFO("Timed out achieving goal");
            }
    	else
            {
                //We made it!
                if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
                {
                    ROS_INFO("Goal A succeeded!");
    		ROS_INFO("send socket succeeded!");
    		sleep(3);
    		//订阅相机获取二维码的位置
    		ros::Subscriber sub = n.subscribe("/ar_pose_marker", 1, sub_ar_callback);
    		//调用拍照和机械臂抓取部分
    		cam_pick();
                }
                else
                {
                    ROS_INFO("The base failed for some reason");
                }
            }
    
    
            //初始化航点目标 去放置点
            move_base_msgs::MoveBaseGoal goal2;
    
            //使用地图框定义目标姿势
            goal2.target_pose.header.frame_id = "map";
    
            //将时间戳设置为“now”
            goal2.target_pose.header.stamp = ros::Time::now();
    
            //将目标姿势设置为第i个航点
            goal2.target_pose.pose = pose_list2;
    
            //让机器人向目标移动
            //将目标姿势发送到MoveBaseAction服务器
            ac.sendGoal(goal2);
    
            //等3分钟到达那里
            bool finished_within_time2 = ac.waitForResult(ros::Duration(180));
    
            //如果我们没有及时赶到那里,就会中止目标
            if(!finished_within_time2)
            {
                ac.cancelGoal();
                ROS_INFO("Timed out achieving goal");
            }
    	else
            {
                //We made it!
                if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
                {
                    ROS_INFO("Goal B succeeded!");
    		robot_place();
    		sleep(3);
                }
                else
                {
                    ROS_INFO("The base failed for some reason");
                }
            }
    
    
    	return 0;
    
    }

     

    展开全文
  • ROS包内容: 这篇日志的目的是快速项目实施,所以详细的部分会不断补充。 1、相机采集包(创建抓取图像服务,单张) Realsense Camera(微软深度摄像头,官方提供ros包) Pylon Camera(basler相机,官方提供ros包...
    ROS包内容:代码暂不公开

    这篇日志的目的是快速项目实施,所以详细的部分会不断补充。举例如下:

    • 项目包1项目地址

    • Pylon Camera

    • Aruco_ros

    • AUBO Robot

    • 大寰机械手AG-95

    • 流程集成模块

    • 模块包

    • 相机采集包(创建抓取图像服务,单张)

      • Realsense Camera 模块地址(微软深度摄像头,官方提供ros包)
      • Pylon Camera 模块地址(basler相机,官方提供ros包)
    • 定位算法包(抓取图像,定位标志物)

      • Aruco_ros 模块地址 (二维码定位,官方提供ros包)
      • Apriltag 模块地址 (二维码定位,官方提供ros包)
      • shape_based_matching 模块地址(linemod,任意形状标志物,官方提供lib包)
    • 机械臂控制包(创建控制机械臂服务)

      • UR Robot 模块地址(UR协作机械臂,官方提供ros包)
      • Aubo Robot 模块地址(国产傲博机械臂,官方提供ros包,需自行完善)
    • 机械手模块(创建机械手服务)

    • 流程集成模块(集成以上模块完成视觉定位、机械臂抓取任务)

      • 相机与机械臂坐标系转换(也可以称为标定,2D和3D略有不同),后面单独来说
      • 工作流程状态机
    • 网络IO模块(modbus协议)

    • 光源控制模块–可选模块 模块地址(创建光源控制服务)

    • 手眼标定模块–可选模块 模块地址(用于相机与机械臂外参的计算)

    相机与机械臂坐标系转换
    • 2D平面转换:满足2个条件,1-此时相机z轴与法兰旋转轴平行,2-同时使用时相机也是垂直与物体平面(固定一个轴的姿态信息已知,由于这种特殊姿态,这种情况下我们可以不用计算相机与机械臂的外参),这种情况下相机像素平面与机械臂XOY平面是平行的,这是通过机械安装的方式达到的,一般精度很高,可以认为两者是平行的。这种情况下,只要进行工业上熟悉的9点标定即可。标定时先旋转相机(目的是找到机械臂末端在相机图像坐标系中的位置,这样机械臂坐标就可以和相机图像坐标一一对应了,为后面9点标定做准备)再平移相机(9点标定)。对应的9点标定方法与使用注意事项也挺复杂。现记录如下:
      我们知道为了通过机械臂上的相机查看桌面上Mark来检测机器人此刻的位置。首先要确定一个机械臂的位姿,即机器人的初始姿态(需要标定时记录,在后期定位机器人位置时也要用,为什么?因为如果不确定一个位姿,那通过相机来确定机器人的相对位置就不可能了,假想相机固定在世界坐标系下不动,机械臂随便移动,那小车的位置就是不确定的了)。ok然后,有了初始位姿,机械臂相对小车的位置就不变了,这时候相机位置就固定了(重点!!!,我们可以想象相机脱离机械臂,固定在了机械臂的上空,就像相机和机械臂脱离模型的9点标定,后面我们做的9点标定和脱离模型一致,只是由于相机在机械臂上,有些数据需要我们自己转换,比如通过旋转末端法兰就可以知道以像素为单位的旋转半径,进而知道法兰末端的像素坐标,最后9点标定平移部分也有一点小坑,由于相机在机械臂上,所以你向左移动机械臂,而图像像素则向右移动,所以在一一对应时要记得反向,ok其他没有什么了)。后记其实相机在机械臂上的情况还是把它作为一种脱离模型在使用。
    • 3D平面转换:不满足2D平面转换的2个条件,即此时相机z轴与法兰旋转轴不平行,或者使用相机时,相机不垂直于物体平面(3个轴的姿态信息都不知道),机械臂任何姿态的变换对相机末端都会造成影响,这种糟糕的情况下我们一定要计算出相机与机械臂末端的外参。计算外参又叫做手眼标定。
    Pylon Camera
    • 驱动包下载并安装,见模块地址。
      驱动包安装:

      • Basler官网 - 产品中心 - 软件 - pylon for Linux x86 - 单击此处下载 - 选择版本
      • 压缩文件目录下对文件进行解压 cpp tar -xvf <file_name>
      • 打开INSTALL文件 按照步骤进行安装
    • 下载pylon camera ros包安装

      • 这个包使用action来请求一张图像,具体使用见项目包。
    • 配置相机IP和预览

      • /opt/pylon5/bin/IpConfigurator 来配置相机的静态ip
      • /opt/pylon5/bin/PylonViewerApp 来预览图像。
    • 可以使用ros包的action来抓取单张图像,这样就不需要时时通过topic来接受图像,这里注意的地方是,action的名字是 “/pylon_camera_node/grab_images_raw”。因为nh的初始化形式为nh("~")。

    Aruco_ros
    • 这里有篇文章是我第一次做时用到的,可以参考
      ArUco_ros使用
    • 注意第二次我使用了错误的aruco码,导致检测不到,我把这些也穿到云盘上文件夹。由于对aruco还不是很熟悉,默认要使用Original ArUco的模式才能识别。Marker ID和Marker size随意。
    Aubo Robot
    • 无驱动包,下载安装即可

    • 简单说明:配置好机械臂的ip地址(可以用示教器,不过有时会不成功,也可以进入电脑(傲博的控制器就是一个linux系统)中修改),在aubo_driver中param中配置好ip地址,安装运行即可。

    大寰机械手AG-95
    • 安装使用,详细说明见ros安装包的README.md

    • 常见问题1:使用USB模式,linux下没有找到ttyACM0?
      回答1:拔掉USB线,重启一下盒子的电源,然后再开启电源插上USB线,再看看。

    • 常见问题2:模式没有切换?
      回答2:是否有插着USB线拨码?USB会给盒子供电,这种时候不是完全断电,所以模式没有切换。

    流程集成模块
    • Yaml-cpp读写
      • 写yaml,注意头尾不要漏掉BeginSeq、EndSeq。
        std::map<int,tf::Transform>::iterator it_station_s;
        YAML::Emitter out_station_s;
        out_station_s << YAML::BeginSeq;
        i = 0;
    
        for(it_station_s = tf_targetfront_to_target_.begin(); it_station_s!=tf_targetfront_to_target_.end();++it_station_s)
        {
            //write tf
            tf::Quaternion q = (it_station_s->second).getRotation();
            tf::Vector3 orig = (it_station_s->second).getOrigin();
    
            std::map<std::string, double> map;
            map["id"]  = it_station_s->first;
            map["qw"]  = q.getW();
            map["qx"]  = q.getX();
            map["qy"]  = q.getY();
            map["qz"]  = q.getZ();
            map["x"]   = orig.getX();
            map["y"]   = orig.getY();
            map["z"]   = orig.getZ();
    
            std::string nameNode = "tf_targetfront_to_target_" + std::to_string(i);
    
            out_station_s << YAML::BeginMap;
            out_station_s << YAML::Key << nameNode;
            out_station_s << YAML::Value << YAML::Flow << map;
            out_station_s << YAML::EndMap;
    
            i++;
        }
    
        out_station_s << YAML::BeginMap;
        out_station_s << YAML::Key << "count";
        out_station_s << YAML::Value << tf_targetfront_to_target_.size();
        out_station_s << YAML::EndMap;
    
        package_path = ros::package::getPath("application_driver");
        yaml_path = package_path + "/param/calibration/tf_targetfront_to_target.yaml";
    
        out_station_s << YAML::EndSeq;
        std::ofstream fout_station_s(yaml_path);
        fout_station_s << out_station_s.c_str();
        fout_station_s.close();
    
    • 读yaml
        //read the mark_hole_tf
        yaml_path = package_path + "/param/calibration/tf_targetfront_to_target.yaml";
        config = YAML::LoadFile(yaml_path);
        count = config.size() - 1; //["count"].as<int>();
    
        tf_targetfront_to_target_.clear();
        for(int i=0; i<count; i++)
        {
            std::string name = "tf_targetfront_to_target_" + std::to_string(i);
    
            int id = config[i][name]["id"].as<int>();
            double qw = config[i][name]["qw"].as<double>();
            double qx = config[i][name]["qx"].as<double>();
            double qy = config[i][name]["qy"].as<double>();
            double qz = config[i][name]["qz"].as<double>();
    
            double x = config[i][name]["x"].as<double>();
            double y = config[i][name]["y"].as<double>();
            double z = config[i][name]["z"].as<double>();
    
            tf::Quaternion tf_q(qx, qy, qz, qw);
            tf::Vector3 tf_orig(x, y, z);
    
            tf::Transform tf_temp;
            tf_temp.setOrigin(tf_orig);
            tf_temp.setRotation(tf_q);
    
            tf_targetfront_to_target_.insert(std::pair<int, tf::Transform>(id,tf_temp));
        }
    
    
    展开全文
  • 通过ROS控制真实机械臂(15) --- 视觉抓取之手眼标定

    千次阅读 热门讨论 2019-12-28 15:01:18
    通过视觉传感器赋予机械臂“眼睛”的功能,配合ATI力和力矩传感器,就可以完成机械臂“手眼”结合的能力,完成视觉抓取过程。目前测试的视觉传感器为 ZED mini双目相机,配置安装过程...

    通过视觉传感器赋予机械臂“眼睛”的功能,配合ATI力和力矩传感器,就可以完成机械臂“手眼”结合的能力,完成视觉抓取过程。目前测试的视觉传感器为 ZED mini双目相机,配置安装过程 https://blog.csdn.net/qq_34935373/article/details/103481401 。

    1.手眼标定(内参)

    对于单目usb相机,可以通过ROS包usb_cam来启动相机,通过camera_calibration功能包http://wiki.ros.org/camera_calibration/完成相机内参的标定过程。本次使用的ZED双目相机,出厂的时候已经完成了内参的标定。如果需要手动重新标定,可以通过ZED自带软件完成标定,双目不仅需要单独标定每个摄像头得到两个摄像头各自的内参矩阵和畸变参数向量,还需要要计算目标点在左右两个视图上形成的视差,首先要把该点在左右视图上两个对应的像点匹配起来。然而,在二维空间上匹配对应点是非常耗时的,为了减少匹配搜索范围,我们可以利用极线约束使得对应点的匹配由二维搜索降为一维搜索。而双目校正的作用:把消除畸变后的两幅图像严格地行对应,使得两幅图像的对极线恰好在同一水平线上,这样一幅图像上任意一点与其在另一幅图像上的对应点就必然具有相同的行号,只需在该行进行一维搜索即可匹配到对应点。

    2.手眼标定(外参)

    内参的标定是确定摄像机从三维空间到二位图像的投影关系,而外参则是确定摄像机坐标与世界坐标系之间的相对位置关系。他们之间关系为 (详情请看 视觉SLAM十四讲第五讲 相机与图像):

    Pc = RPw + T   

    其中Pw为世界坐标,Pc是摄像机坐标,式中,T= (Tx,Ty,Tz),是平移向量,R = R(α,β,γ)是旋转矩阵,分别是绕摄像机坐标系z轴旋转角度为γ,绕y轴旋转角度为β,绕x轴旋转角度为α。6个参数组成(α,β,γ,Tx,Ty,Tz)为摄像机外参。

    3.手眼标定(调包)

    对于手眼外参标定,场景主要有以下两种,

    • eye in base,眼在手外,这种场景下我们已知机械臂终端end_link与base_link、相机camera_link与识别物体object_link之间的关系,需要求解camera_link与base_link之间的变换;

    • eye on hand,眼在手上,这种场景base_link和机械臂各关节joint_link、end_link已经通过URDF发布了,只需要求解camera_link与end_link之间的变换。

    1. ROS也为我们提供了功能包,visp_hand2eye_calibration和ros_easy_handeye。首先测试visp_hand2eye_calibration,这个包是用来标定eye in base 眼在手外的情形。

    # 安装功能包
    $ sudo apt-get install ros-indigo-visp-hand2eye-calibration
    
    # 启动测试样例
    $ rosrun visp_hand2eye_calibration visp_hand2eye_calibration_client
    
    # 启动 calibrator 节点
    $ rosrun visp_hand2eye_calibration visp_hand2eye_calibration_calibrator

    将会显示一些输出如下,表明安装成功,接下来就可以集成到自己的标定环境中了:

    [ INFO] [1329226083.184531090]: Waiting for topics...
    [ INFO] [1329226084.186233704]: 1) GROUND TRUTH:
    [ INFO] [1329226084.186327570]: hand to eye transformation: 
    translation: 
      x: 0.1
      y: 0.2
      z: 0.3
    rotation: 
      x: 0.96875
      y: 0.0863555
      z: -0.0863555
      w: 0.215889
    

    修改到自己的标定环境中:

    # 启动主节点
    $ roscore
    # 启动 calibrator 节点
    $ rosrun visp_hand2eye_calibration visp_hand2eye_calibration_calibrator
    
    # 终端输出提示如下:
     [ WARN] [1577429182.106793405]: The input topic '/camera_object' is not yet advertised
     [ WARN] [1577429182.106871954]: The input topic '/world_effector' is not yet advertised

    calibrator需要我们发布如下两个话题:

    world_effector (visp_hand2eye_calibration/TransformArray)

    • transformation between the world and the hand frame. The node expects to receive several of those transformations.

    camera_object (visp_hand2eye_calibration/TransformArray)

    • transformation between the camera and the object frame. The node expects to receive several of those transformations.

    calibrator发布如下服务:

    compute_effector_camera (visp_hand2eye_calibration/compute_effector_camera)

    • Returns the hand to camera transformation result after calibration based on the data published on the subscribed topics.

    compute_effector_camera_quick (visp_hand2eye_calibration/compute_effector_camera_quick)

    • Returns the hand to camera transformation result after calibration. This service is not based on the data published on the subscribed topics. Instead, the transformation are passed as service parameters.

    reset (visp_hand2eye_calibration/reset)

    • Reset all the data published on the subscribed topics. Only new publications (transformations) will be taken into account.

    总结来说就是移动机械臂采集多个点发送到:world_effector 和 camera_object 两个topic下,通过 compute_effector_camera 这个service得到变换矩阵。这位老哥写的挺好,https://blog.csdn.net/MzXuan/article/details/79177747


    2. 第一种方法用到人貌似比较少,使用场景也比较局限,第二种方法基于第一种方法,这个包可以标定eye-in-hand和eye-on-base两种场景,还提供了GUI界面预期的输入为TF中发布的坐标变换。此外,还提供了一种保存和发布标定结果的方法。如下图所示,该种方法可以完成两种类型的标定。值得一提的是作者还提供了一个基于iiwa机械臂的使用例程,该例程可以在没有任何硬件的情况下使用,它使用RViz仿真的机械臂和虚拟发布的相机坐标系。

     

     

    # 进入工作目录
    $ cd catkin_ws/src
    # 安装例程依赖包
    $ git clone https://github.com/IFL-CAMP/iiwa_stack
    # 手眼标定功能包
    $ git clone https://github.com/IFL-CAMP/easy_handeye
    # 例程功能包
    $ git clone https://github.com/marcoesposito1988/easy_handeye_demo

    下载完成之后,编译iiwa包,提示CMake版本过低,但由于我们只是简单的使用一下iiwa作为仿真对象,只需要修改一下CMakeLists.txt,将cmake_minimum_required(VERSION 3.5)修改成cmake_minimum_required(VERSION 2.8.3)即可。有些包编译缺少依赖或者不通过也不太影响。启动launch文件查看是否编译成功,打开TF观察发布的关节坐标系。

    如上图所示,iiwa机械臂的机器人坐标系为iiwa_link_0和世界坐标系world重合,而末端执行器为iiwa_link_ee,iiwa_link_7坐标系就是安装标定板的位置,所以我们后面只需要修改launch文件中的坐标系名称为自己的机器人坐标系即可将手眼标定包集成到自己的项目当中。

    easy_handeye_demo包中还有一个check_calibration.launch,其功能是检测标定板相对与末端执行器(或者机器人基坐标系)是否处于固定位置,以便于后面的手眼标定过程。

    # 编译例程包
    $ catkin_make -DCATKIN_WHITELIST_PACKAGES="easy_handeye_demo"
    
    # 启动eye_in_base标定
    $ roslaunch easy_handeye_demo calibrate.launch 
    # 启动eye_on_hand标定
    $ roslaunch easy_handeye_demo calibrate.launch eye_on_hand:=true
    

     

     

    上图分别对应eye_on_hand和eye_in_base两种情况,其中tracking_origin表示的是相机坐标系,而tracking_marker则表示标定板的位置。因此通过矩阵计算,就可以获得相机坐标系到机器人坐标系的变换矩阵。

    由于没有硬件,所以tracking_marker和tracking_origin的位置是通过手动发布的静态坐标变化得到的。可以在launch文件中看到:

    <param name="eye_on_hand" value="$(arg eye_on_hand)" />
    <!-- transformations for the eye-on-base case -->
    <param unless="$(arg eye_on_hand)" name="ground_truth_calibration_transformation" value="1 0 0.5 0 0 0 1" />
    <param unless="$(arg eye_on_hand)" name="arbitrary_marker_placement_transformation" value="0.12 0.21 0.137 0 0 0 1" />
    <!-- transformations for the eye-on-hand case -->
    <param if="$(arg eye_on_hand)" name="ground_truth_calibration_transformation" value="0.12 0.21 0.137 0 0 0 1" />
    <param if="$(arg eye_on_hand)" name="arbitrary_marker_placement_transformation" value="1 0 0.5 0 0 0 1" />
    

    当想要修改该demo包用于自己的仿真机器人的时候,修改launch的如下位置中的value即可:

    <arg name="robot_base_frame" value="iiwa_link_0" />
    <arg name="robot_effector_frame" value="iiwa_link_ee" />
    <arg name="tracking_base_frame" value="tracking_origin" />
    <arg name="tracking_marker_frame" value="tracking_marker" />

     


    当有硬件的时候,上面的demo中发布静态坐标的方式显然就不合理了,为此我们需要使用真正的easy_handeye完成标定过程了。为此,作者也为我们提供了一个基于真实机械臂UR5和Kinect2相机的例程。

    如下所示,首先需要启动kinect和ArUco,aruco是用来识别特定图案的。用aruco_ros识别末端上的标志物, 得到camera_link到marker_link的转换. 之后按照GUI控制机械臂在相机视野内产生17个姿态, 每次都把样本记录下来.  最后点击求解, easy_handeye会调用visp的代码得到标定结果. 然后点save, 标定结果会被保存在~/.ros/easy_handeye/---.yaml. 之后就可以关掉标定程序,再运行publish.launch即可发布base_link到camera_link的转换.参考链接:https://zhuanlan.zhihu.com/p/33441113

    1. aruco_ros需要配置两个参数. 首先是相机和机器人的参考坐标系:

    • tracking_base_frame就是相机的参考坐标系
    • tracking_marker_frame是标志物的参考坐标系
    • robot_base_frame就是机械臂参考坐标系
    • robot_effector_frame是末端执行器参考坐标系

    2. 第二个参数是需要知道aruco的ID跟边长. 通过网站http://chev.me/arucogen/可以生成这种图案.(选择参数为:original 50 100)

    # 安装aruco_ros
    $ cd ~/catkin_ws/src
    $ git clone https://github.com/pal-robotics/aruco_ros.git
    
    # 如果编译aruco不通过,提示缺少OpenCV3依赖的话,如下操作
    # ros indigo版本需要手动安装opencv3
    $ sudo apt-get install ros-indigo-opencv3
    
    # 如果报错CMake Error in whycon/CMakeLists.txt: Imported target "opencv_xphoto" includes non-existent path  "/usr/include/opencv-3.1.0-dev/opencv"的话
    $ sudo vim /opt/ros/indigo/share/OpenCV-3.1.0-dev/OpenCVConfig.cmake +113    
    修改如下:
    113:get_filename_component(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH CACHE)
    改成
    113:get_filename_component(OpenCV_CONFIG_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH )
    
    
    # 启动标定
    $ roslaunch easy_handeye ur5_kinect_calibration.launch
    
    # 点GUI里的check, 初始化17个姿态
    
    # 然后next pose一下就记录一下sample
    
    # 计算, 保存, 关掉标定程序
    
    # 通过launch发布标定结果
    $ roslaunch easy_handeye publish.launch
    

     

    <launch>
        <arg name="namespace_prefix" default="ur5_kinect_handeyecalibration" />
    
        <arg name="robot_ip" doc="The IP address of the UR5 robot" />
    
        <arg name="marker_size" doc="Size of the ArUco marker used, in meters" />
        <arg name="marker_id" doc="The ID of the ArUco marker used" />
    
        <!-- start the Kinect -->
        <include file="$(find freenect_launch)/launch/freenect.launch" >
            <arg name="depth_registration" value="true" />
        </include>
    
        <!-- start ArUco -->
        <node name="aruco_tracker" pkg="aruco_ros" type="single">
            <remap from="/camera_info" to="/camera/rgb" />
            <remap from="/image" to="/camera/rgb/image_rect_color" />
            <param name="image_is_rectified" value="true"/>
            <param name="marker_size"        value="$(arg marker_size)"/>
            <param name="marker_id"          value="$(arg marker_id)"/>
            <param name="reference_frame"    value="camera_link"/>
            <param name="camera_frame"       value="camera_rgb_optical_frame"/>
            <param name="marker_frame"       value="camera_marker" />
        </node>
    
        <!-- start the robot -->
        <include file="$(find ur_bringup)/launch/ur5_bringup.launch">
            <arg name="limited" value="true" />
            <arg name="robot_ip" value="192.168.0.21" />
        </include>
        <include file="$(find ur5_moveit_config)/launch/ur5_moveit_planning_execution.launch">
            <arg name="limited" value="true" />
        </include>
    
        <!-- start easy_handeye -->
        <include file="$(find easy_handeye)/launch/calibrate.launch" >
            <arg name="namespace_prefix" value="$(arg namespace_prefix)" />
            <arg name="eye_on_hand" value="false" />
    
            <arg name="tracking_base_frame" value="camera_link" />
            <arg name="tracking_marker_frame" value="camera_marker" />
            <arg name="robot_base_frame" value="base_link" />
            <arg name="robot_effector_frame" value="wrist_3_link" />
    
            <arg name="freehand_robot_movement" value="false" />
            <arg name="robot_velocity_scaling" value="0.5" />
            <arg name="robot_acceleration_scaling" value="0.2" />
        </include>
    
    </launch>



    接下来是利用Realsense相机和UR5机器人完成标定的过程,原本包里面提供的easy_handeye_demo中的ur5标定使用的是ur_driver这个驱动,在一波更新之后,实验室使用的是Universal_Robots_ROS_Driver这个包,所以需要修改一些东西。

    如下所示,标记物的尺寸和ID以及机器人的ip地址需要修改,因为实验室使用的是realsense了,所以将freenect这部分修改成realsense的启动launch,同样的,对于相机和图像的坐标系,也要相应的改变,可以通过topic查看realsense的话题,修改成对应的(刚开始坐标系没有修改,启动之后一直有一些错误)。

    对于UR5的驱动部分,将原本的ur_driver变成Universal_Robots_ROS_Driver的启动,这里需要注意的是,要先启动launch文件,这样在示教器中才能运行URCap的external_control,具体参考Universal_Robots_ROS_Drive的使用方法:https://blog.csdn.net/qq_34935373/article/details/109238762

    <launch>
        <arg name="namespace_prefix" default="ur5_kinect_handeyecalibration" />
    
        <arg name="robot_ip" doc="The IP address of the UR5 robot" default="192.168.1.101"/>
    
        <arg name="marker_size" doc="Size of the ArUco marker used, in meters" default="0.1"/>
        <arg name="marker_id" doc="The ID of the ArUco marker used" default="50"/>
    
        <!-- start the Kinect -->
        <!-- <include file="$(find freenect_launch)/launch/freenect.launch" >
            <arg name="depth_registration" value="true" />
        </include> -->
    
        <include file="$(find realsense2_camera)/launch/rs_rgbd.launch" />
    
        <!-- start ArUco -->
        <node name="aruco_tracker" pkg="aruco_ros" type="single">
            <remap from="/camera_info" to="/camera/color/camera_info" />
            <remap from="/image" to="/camera/color/image_raw" />
            <param name="image_is_rectified" value="true"/>
            <param name="marker_size"        value="$(arg marker_size)"/>
            <param name="marker_id"          value="$(arg marker_id)"/>
            <param name="reference_frame"    value="camera_link"/>
            <param name="camera_frame"       value="camera_color_optical_frame"/>
            <param name="marker_frame"       value="camera_marker" />
        </node>
    
        <!-- start the robot -->
        <!-- <include file="$(find ur_bringup)/launch/ur5_bringup.launch"> -->
        <include file="$(find ur_robot_driver)/launch/ur5_bringup.launch">
            <!-- <arg name="limited" value="true" /> -->
            <arg name="robot_ip" value="192.168.1.101" />
        </include>
        <include file="$(find ur5_moveit_config)/launch/ur5_moveit_planning_execution.launch">
            <arg name="limited" value="true" />
        </include>
    
        <!-- start easy_handeye -->
        <include file="$(find easy_handeye)/launch/calibrate.launch" >
            <arg name="namespace_prefix" value="$(arg namespace_prefix)" />
            <arg name="eye_on_hand" value="false" />
    
            <arg name="tracking_base_frame" value="camera_link" />
            <arg name="tracking_marker_frame" value="camera_marker" />
            <arg name="robot_base_frame" value="base_link" />
            <arg name="robot_effector_frame" value="wrist_3_link" />
    
            <arg name="freehand_robot_movement" value="false" />
            <arg name="robot_velocity_scaling" value="0.5" />
            <arg name="robot_acceleration_scaling" value="0.2" />
        </include>
    
    </launch>

    启动之后,会出现如下三个界面:

    $ roslaunch easy_handeye_demo ur5_kinect_calibration.launch marker_size:=0.1 marker_id:=50

    第一个图中显示的是水平躺着的机械臂,而且TF坐标映射不完整,这个说明和真实的UR链接出现问题了,要不就是URCap程序没运行,要不就是通信没连接之类的,正确没问题的情况是TF完整,而且RVIZ中的机械臂和真实世界机械臂的状态是一致的,处在相同的关节位置。

     第二个界面初始化状态如下,需要全屏这个界面然后在左上角找出image view打开才能完成接下来的采样:

    打开界面之后,如图所示, 选择/aruco_ros/result话题,有可能会出现灰白界面没有图像,多重试几次,切换切换话题:

     第三个界面可以完成采样,选取位姿:

    最后按照界面的提示,next pose -> plan -> execute -> take sample -> ...  -> compute:

    可以在RViz中看到camera_link和camera_marker的坐标变换还是有错误的,我第一次完成的时候,还以为标定错了,但实际的坐标变换已经保存在~/.ros/easy_handeye下的yaml文件了,接下来通过在launch文件启动该坐标变换即可.

      <node pkg="tf" type="static_transform_publisher" name="ur5_realsense_calibration" args=" 0.854278519500625 1.209861820016321 0.19546056257158806 -0.11061812678943928 -0.040388645131856346 -0.8716081983804171 0.4758482277849228 base_link camera_link 100" />
    

    结合https://blog.csdn.net/qq_34935373/article/details/104794634 就可以在RViz中启动Octomap:

     

     

    展开全文
  • Cornell数据集训练结果三、机械臂抓取和放置实验1. 实验所需理论2. 机械臂抓取实验3. 机械臂放置实验结合语音识别的机器人抓取交互系统框图总结 前言 机器人感知环境通常依赖于各种接触型以及非接触型传感器,并...
  • #include "ros/ros.h" #include "ar_track_alvar_msgs/AlvarMarkers.h" #include "iostream" #include "stdio.h" #include "cv.h" #include "opencv2/opencv.hpp" #include "cv_bridge/cv_bridge.h" #include <u....
  • 视觉抓取中非常重要的一个部分就是对抓取物体的识别,无论是二维图像还是三维点云,在ROS中都可以找到对应的功能包,https://blog.csdn.net/qq_34935373/article/details/103757619该篇博客就基于模板匹配算法的find...
  • 视觉抓取中非常重要的一个部分就是对抓取物体的识别,无论是二维图像还是三维点云,在ROS中都可以找到对应的功能包,本次测试的是能对物体进行快速识别,甚至定位的find_object包,该功能包是基于模板匹配算法(包括...
  • 解决方法: 在ROS官网搜roboticsgroup_gazebo_plugins可以找打Gazebo>=8的版本,下载替换掉原来的文件即可。 直接用下面这个链接下载,替换掉之前的文件即可 ...
  • ROS Melodic连接UR5机械臂通讯详细步骤,亲测可行

    千次阅读 热门讨论 2020-12-31 11:22:17
    任务描述:机器人操作系统ros通过网线连接ur5,实现二者通信,在ros下控制ur5运动,为后续基于ros开发机械臂视觉抓取/避障等应用打下基础。 目录 1 ur5机器人端的设置 1.1 在ur5上安装urcap 1.2 编程序 1.3 ...
  • Mastering ROS 学习记录 使用3D视觉传感器 这是实现抓取任务的基础 注意!传感器可以由Gazebo模拟,也可以直接和物理设备相连传入Gazebo中 确认Gazebo插件正确工作 使用RViz查看Gazebo插件...
  • 在此问题的基础上,本课题提出一套基于ROS(机器人操作系统)视觉定位的机械臂智能抓取系统,使抓取目标的初始位姿和最终位姿被严格限定的问题得到解决。首先,采用张正友算法标定RGB-D相机,获取其内外参数;其次,采用...
  • ROS控制kinova jaco2机械臂

    千次阅读 热门讨论 2018-12-09 19:27:25
    JACO2 6自由度机械臂是加拿大KINOVA公司的一款产品,设计非常的精简紧凑,移动的精度很高,能在Windows和Linux下驱动,我想拿它验证一些控制算法,以及配合计算机视觉完成一些目标识别和抓取的工作。 一开始的...
  • 1、开机底盘、机械臂、运行视觉的小工控机 开启机械臂后需要在示教器上点击运行ROS1程序 2、第一个终端 ssh robint01@192.168.50.144 cd chassis_start ./ur_driver.sh 然后点击示教器的暂停按钮,启动机械臂。 3、...
  • 1,首推ROS 2,其他环境 三,理论学习 四,实物搭建 一,实物or仿真 我想这个问题是在开发之前最容易想清楚的,所以我先说! 1,实物或仿真的利弊 对于做出实物,要比仿真耗费更多的时间,精力,物力,财力...
  • 入门——古月居机械臂开发笔记(二)引言ROS机械臂开发_机器视觉与物体抓取1、ROS中的运动学插件2、Moveit!碰撞检测规划场景3、Pick and Place 引言 接上次笔记(一)Moveit!和机械臂控制,这一次主要为:ROS机械...
  • 首先表明目的,本款机器人希望它具有辨别使用者的功能,网上能够人脸...1,wiki.ros.org/face_recognition 2,其他资料 https://blog.csdn.net/weixin_40522162/article/details/79982386 这篇文章写的很棒,但是...
  • 对于机械臂导航来说,重要的内容还是逆运动学求解,包括后续的基于视觉实现对目标的抓取。我在做逆运动学求解时遇到很大的困难,我创建的3自由度的机械臂模型文件,求解不出逆运动学解。也参考了ros wiki 官网,也有...
  • ROS 总结报告

    2020-12-31 16:04:55
    文章目录ROS 总结报告小车建模小车本体建模基础知识萝卜机器人建模添加差速轮控制仿真插件添加摄像头仿真插件初探摄像头仿真插件发布两个摄像头话题3D 视觉摄像头标定深度图生成与摄像头话题进行通信获取话题数据...
  • ROS+Opencv ----- 读取图片并发布话题

    千次阅读 热门讨论 2020-01-09 15:59:39
    最近看完了Opencv By Example这本书,感觉里面的案例很不错,其中有个案例是通过背景差分识别桌子上的螺钉螺母等机械零件,这对后期的机械臂视觉抓取提供了视觉处理部分的方法论,虽然有很多现成的ROS库可用于视觉...
  • ROS kinetic 升级 PCL1.9.0 以安装gpd库和gpd_ros

    千次阅读 热门讨论 2020-03-28 14:11:23
    对于机械臂视觉抓取功能来说,比较传统的做法:由于之前的物体识别模块已经确定了这片点云对应的物体,如果我们有物体的3D模型,便可以直接用ICP算法将这片点云与物体的3D模型对齐。既然知道3D模型的位姿那就好办了...
  • ROS入门与实战

    2018-09-22 16:43:48
    ROS入门与实战》深入浅出地介绍了ROS的特点、基本使用方法以及实际应用,内容涉及移动机器人自主导航、视觉识别、机械臂运动规划等,可帮助不同领域的机器人开发人员了解并熟练使用ROS。  《ROS入门与实战》内容...
  • 目前一直在做视觉引导的机械臂目标抓取相关内容的研究。由于图像数据处理是在Window系统下进行的,而机械臂开发却是在ROS环境中开发,因此需要进行跨系统的信息通讯传输,将位姿信息传输给机械臂。 在进行该部分通讯...
  • ROS机器人程序设计

    2017-11-29 17:09:52
    ”包控制机械臂执行抓取任务。读完本书后,你会发现已经可以使用ROS机器人进行工作了,并理解其背后的原理。, 主要内容, 第1章介绍安装ROS系统最简单的方法,以及如何在不同平台上安装ROS,本书使用的版本是ROS ...
  • ”包控制机械臂执行抓取任务。读完本书后,你会发现已经可以使用ROS机器人进行工作了,并理解其背后的原理。 主要内容 第1章介绍安装ROS系统最简单的方法,以及如何在不同平台上安装ROS,本书使用的版本是ROS Hydro...
  • 机械臂末端位姿获取:  Baxter启动后会将自身各坐标系的变换关系发布到 '/tf' 话题中,我们只需要使用TF包(具体参考wiki)即可。定义的current_pose()函数是为了将矩阵转换为ROS的pose Message。 class tf_...

空空如也

空空如也

1 2
收藏数 33
精华内容 13
关键字:

ros机械臂视觉抓取