悉灵杯”课题研究进展(四)RGB-D相机引导机械臂分拣物料
本文主要介绍研究进展(三)中积木分拣项目的QT上位机部分程序及上位机与机器人通信的相关内容

一. 环境介绍

(一)积木分拣

1、pcl 1.11.1

2、OpenCV 

3、Visual Studio 2019

4、VTK 8.2

5、QT 5.13.2

二. 积木分拣

本文主要介绍研究进展(三)中积木分拣项目的QT上位机部分程序及上位机与机器人通信的相关内容

HK_Robot_Materials_Sorting.h

class HK_Robot_Materials_Sorting : public QWidget
{
    Q_OBJECT

public:

    SOCKET robot_socket; 
    HK_Robot_Materials_Sorting(QWidget *parent = nullptr);
    ~HK_Robot_Materials_Sorting();
    unsigned int nDevNum = 0;
    Mv3dRgbdDeviceType device_type;
    std::vector<MV3D_RGBD_DEVICE_INFO> devs;//设备列表
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer1;
    pcl::PointCloud<pcl::PointXYZRGB> cloud;
    typedef pcl::PointXYZRGB PointT;
    typedef pcl::PointCloud<PointT>PointCloud;
    PointCloud::Ptr cloudRGB;
private slots:
    void on_btnFinddevice_clicked();
    void on_btnOpenDevice_clicked();
    void on_btngrap_clicked();
    void on_btnSelectBegin_clicked();
    void on_pushButton_2_clicked();
    void on_btn_stop_clicked();
    void on_btn_auto_clicked();
    void onServerStatusChanged(const QString& statusMessage);
public:
    void grap_show(void * handle );
    void grap_show_auto(void* handle);
    void* handle = NULL;
    unsigned char* g_pRgbData = NULL;
    bool ConvertRGB8Planner2BGR8Packed(const unsigned char* pSrcData, int nWidth,int nHeight,unsigned char* pDstData);
    void VTK_Init();
    MV3D_RGBD_IMAGE_DATA imgCloud;
    void color_selece();
    Eigen::Matrix4f Matrix_A;
    Eigen::Matrix4f Matrix_B;
    bool robotflag;
    MyRobot* robot;

private:
    Ui::HK_Robot_Materials_SortingClass ui;
};

该部分主要为上位机与机器人通信的相关程序

MyRobot.h

class MyRobot :
    public QObject
{
    Q_OBJECT
signals:
    void serverStatusChanged(const QString& statusMessage);

public:
    explicit MyRobot(QObject* parent = nullptr);
    void startServer();
    void sendDataToClient(int clientIndex, const QString& message);
    void Send(QTcpSocket* socket, const QString& message);
private slots:
    void onNewConnection();
    void onSocketReadyRead();

private:
    QTcpServer* m_server;
    QList<QTcpSocket*> m_clients;
    QTcpSocket* client;

};

MyRobot.cpp

#include "MyRobot.h"
#include <qtextbrowser.h>

MyRobot::MyRobot(QObject* parent) : QObject(parent),
m_server(new QTcpServer(this))
{
    connect(m_server,&QTcpServer::newConnection, this,&MyRobot::onNewConnection);
}

void MyRobot::startServer()
{
    if (m_server->listen(QHostAddress("192.168.1.200"), 6000))
    {
        emit serverStatusChanged(u8"服务器创建成功\n");
    }
    else
    {
        emit serverStatusChanged(u8"请检查robot的IP和端口\n");
    }
}
void MyRobot::onNewConnection()
{
    QTcpSocket* client = m_server->nextPendingConnection();
    m_clients.append(client);
    connect(client, &QTcpSocket::readyRead, this, &MyRobot::onSocketReadyRead);
    emit serverStatusChanged(u8"有客户端接入\n");
}

void MyRobot::onSocketReadyRead()
{
    QTcpSocket* client = qobject_cast<QTcpSocket*>(sender());
    if (client)
    {
        QByteArray data = client->readAll();
        QString str = QString::fromUtf8(data);
        if (str == "6")
        {
            emit serverStatusChanged(u8"6");
     
        }
    }
}
void MyRobot::Send(QTcpSocket* socket, const QString& message)
{
    socket->write(message.toUtf8());
    socket->waitForBytesWritten();
}
void MyRobot::sendDataToClient(int clientIndex, const QString& message)
{
    if (clientIndex >= 0 && clientIndex < m_clients.size())
    {
        Send(m_clients.at(clientIndex), message);
    }
}

与研究进展(二)使用winform编写的鞋底分拣上位机程序一样,这里同样采用机械臂作为客户端,上位机作为服务器,当用户点击自动运行按钮后,相机会进行拍照并通过PCL进行点云处理,并将得到的抓取坐标发送给机械臂,第一次抓拍之后的所有拍照操作由客户端控制,当机械臂第一次获取的所有坐标全部抓取完毕后,机械臂运动到最后一个物料的放料区域的同时会向上位机发送一个数字6,上位机接收到数字6会触发信号serverStatusChanged,并去执行对应的槽函数 抓拍点云数据并进行点云处理,将得到的抓取坐标发送给客户端,客户端会解析数据,引导机械臂进行抓取。

void  HK_Robot_Materials_Sorting::on_btn_auto_clicked()
{
	ca_fl == true;
	btn_flag = true;
      if ((firstcamera == true &&  btn_flag == true))
	{
		firstcamera = false;
		grap_show_auto(handle);
	}
}
void HK_Robot_Materials_Sorting::onServerStatusChanged(const QString& statusMessage)
{ if (statusMessage == "6"&& firstcamera == false && btn_flag == true&& ca_fl == true)
	{	       ui.textBrowser_3->insertPlainText(u8"success");
		grap_show_auto(handle);
	}

}

点云处理程序之前已经进行了介绍这里不在详细介绍


	ui.textBrowser->clear();
	pcl::PassThrough<pcl::PointXYZRGB> pass;//设置滤波器对象
	pass.setInputCloud(cloudRGB);
	pass.setFilterFieldName("z");//设置滤波方向
	pass.setFilterLimits(500, 750);
	pass.setFilterLimitsNegative(false);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZRGB>());
	pass.filter(*cloud_out);
	pass.setInputCloud(cloud_out);
	pass.setFilterFieldName("x"); 
	pass.setFilterLimits(-330,70); 
	pass.filter(*cloud_out);
	pass.setInputCloud(cloud_out);
	pass.setFilterFieldName("y");
	pass.setFilterLimits(-400, 100);
	pass.filter(*cloud_out); // 执行过滤操作
	pcl::io::savePCDFileASCII("xx.pcd", *cloud_out);
	 //统计滤波
	pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> outrem;//创建统计滤波对象
	outrem.setInputCloud(cloud_out);
	outrem.setMeanK(800);//附近邻近点数
	outrem.setStddevMulThresh(1);//标准差系数
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_out1(new pcl::PointCloud<pcl::PointXYZRGB>);
	outrem.filter(*cloud_out1);

	std::vector<float> vecX;
	std::vector<float> vecY;
	std::vector<float> vecZ;
	std::vector<char> vecflag;

	pcl::PointCloud<pcl::PointXYZRGB>::Ptr redfilteredCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr greenfilteredCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr bluefilteredCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr orginfilteredCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr allpointcloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	std::vector<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> cloudList;
	Eigen::Vector4f centroid;	
	string  color_flag;
	pcl::PointXYZ center;
	for (size_t i = 0; i < cloud_out1->points.size(); ++i) {
		const pcl::PointXYZRGB& point = cloud_out1->points[i];
		if (point.r >= 200 && point.r <= 255 && point.g >=60 && point.g <= 100 && point.b >= 10 && point.b <= 60) 
		{
			redfilteredCloud->points.push_back(point);
			allpointcloud->points.push_back(point);
		}
	}

	for (size_t i = 0; i < cloud_out1->points.size(); ++i) {
		const pcl::PointXYZRGB& point = cloud_out1->points[i];
		if (point.r >= 140 && point.r <= 190 && point.g >= 210 && point.g <= 255 && point.b >= 80 && point.b <= 130) {
			greenfilteredCloud->points.push_back(point);
			allpointcloud->points.push_back(point);
		}
	}

	for (size_t i = 0; i < cloud_out1->points.size(); ++i) {
		const pcl::PointXYZRGB& point = cloud_out1->points[i];
		if (point.r >= 80 && point.r <= 120 && point.g >= 180 && point.g <= 210 && point.b >= 230) {
			bluefilteredCloud->points.push_back(point);
			allpointcloud->points.push_back(point);
		}
	}

	for (size_t i = 0; i < cloud_out1->points.size(); ++i) {
		const pcl::PointXYZRGB& point = cloud_out1->points[i];
		if (point.r >= 230 && point.g >= 160 && point.g <= 190 && point.b >= 60 && point.b <= 100) {
			orginfilteredCloud->points.push_back(point);
			allpointcloud->points.push_back(point);
		}
	}	allpointcloud->width = allpointcloud->points.size();
	allpointcloud->height = 1;

	redfilteredCloud->width = redfilteredCloud->points.size();
	redfilteredCloud->height = 1;

	greenfilteredCloud->width = greenfilteredCloud->points.size();
	greenfilteredCloud->height = 1;

	bluefilteredCloud->width = bluefilteredCloud->points.size();
	bluefilteredCloud->height = 1;

	orginfilteredCloud->width = orginfilteredCloud->points.size();
	orginfilteredCloud->height = 1;
	cloudList.push_back(redfilteredCloud);
	cloudList.push_back(greenfilteredCloud);
	cloudList.push_back(bluefilteredCloud);
	cloudList.push_back(orginfilteredCloud);

	for (size_t k = 0; k < cloudList.size(); ++k) {

		if(900<cloudList[k]->points.size()<=1400)
		{
			pcl::compute3DCentroid(*cloudList[k], centroid);	
			vecX.push_back(centroid(0));
			vecY.push_back(centroid(1));
			vecZ.push_back(centroid(2));
			if (k == 0)
			{
				vecflag.push_back('R');
			}
			else if (k == 1)
			{
				vecflag.push_back('G');
			}
			else if (k == 2)
			{
				vecflag.push_back('B');
			}
			else if (k == 3)
			{
				vecflag.push_back('O');
			}
		}
		else if(cloudList[k]->points.size()>1400)
		{
			pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>);
			tree->setInputCloud(cloud_out);
			std::vector<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> result;
			std::vector<pcl::PointIndices> cluster_indices;
			pcl::EuclideanClusterExtraction<pcl::PointXYZRGB> ec;
			ec.setClusterTolerance(1.4); 
			ec.setMinClusterSize(650);    
			ec.setMaxClusterSize(2000);  
			ec.setSearchMethod(tree);     
			ec.setInputCloud(cloud_out); 
			ec.extract(cluster_indices);  
			std::vector<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> Eucluextra; 

	for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it)
	{
		pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_cluster1(new pcl::PointCloud<pcl::PointXYZRGB>);
		for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); pit++)
			cloud_cluster1->points.push_back(cloud_out->points[*pit]);
			cloud_cluster1->width = cloud_cluster1->points.size();
			cloud_cluster1->height = 1;
			cloud_cluster1->is_dense = true;
			Eucluextra.push_back(cloud_cluster1);
	}

	for (int t = 0; t < Eucluextra.size(); t++)
	{
		pcl::compute3DCentroid(*Eucluextra[t], centroid);	
		vecX.push_back(centroid(0));
		vecY.push_back(centroid(1));
		vecZ.push_back(centroid(2));
	}
	if (k == 0)
	{
		vecflag.push_back('R');
	}
	else if (k == 1)
	{
		vecflag.push_back('G');
	}
	else if (k == 2)
	{
		vecflag.push_back('B');
	}
	else if (k == 3)
	{
		vecflag.push_back('O');
	}
			
		}
		
	}

	for (size_t i = 0; i < vecX.size(); ++i) {
		char color =vecflag[i];
		QString colorchinese;
		if (color == 'R')
		{
			colorchinese = u8"红色";
		}
		else if (color == 'G')
		{
			colorchinese = u8"绿色";
		}
		else if (color == 'B')
		{
			colorchinese = u8"蓝色";
		}
		else if (color == 'O')
		{
			colorchinese = u8"橙色";
		}
		pcl::PointXYZ o;
		 o.x = vecX[i];
		 o.y = vecY[i];
		 o.z = vecZ[i];
		viewer1->addSphere(o, 3, 255, 255, 101, std::to_string(i*3), 0);
		Eigen::Vector4f eigen_vector(vecX[i], vecY[i], vecZ[i], 0);
		Eigen::Vector4f resulat = Matrix_A* eigen_vector;
		Eigen::Vector4f resultS = Matrix_B * resulat;
		float jx = 744.50;
		float jy = 304.77;
		float jz = -38.90;
		float cx = 105.976;
		float cy = 6.337556;
		float cz = 4.744299;
		float px = jx - cx;
		float py = jy - cy;
		float pz = jz - cz;
		float x = resultS[0] + px;
	       float y= resultS[1] + py;
		float z = resultS[2] + pz;             //由于积木为正方形  所以每次以固定姿态抓取即可,所以这里没有计算姿态,以固定姿态进行抓取
	       QString canshu = QString(u8"颜色:""%1""   X:""%2""   Y:""%3""   Z:""%4\n").arg(colorchinese).arg(x).arg(y).arg(z);
		QString txt = "("+QString::number(color) + QString::number(x) + "," + QString::number(y) + "," + QString::number(z) + ")";
		robot->sendDataToClient(0,txt);
	       ui.textBrowser->insertPlainText(canshu);
	pcl::io::savePCDFile<pcl::PointXYZRGB>("filtered_point_cloud.pcd", *redfilteredCloud);
	pcl::io::savePCDFile<pcl::PointXYZRGB>("greenfilteredCloud.pcd", *greenfilteredCloud);
	pcl::io::savePCDFile<pcl::PointXYZRGB>("bluefilteredCloud.pcd", *bluefilteredCloud);
	pcl::io::savePCDFile<pcl::PointXYZRGB>("orginfilteredCloud.pcd", *orginfilteredCloud);
	viewer1->addPointCloud(allpointcloud, std::to_string(8));
	viewer1->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, std::to_string(8));
	ui.qvtkWidget_2->update();
	


附件:
版权声明:本文为V社区用户原创内容,转载时必须标注文章的来源(V社区),文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:v-club@hikrobotics.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
上一篇

悉灵杯”课题研究进展(三)RGB-D相机引导机械臂分拣物料

下一篇

”悉灵杯”课题研究报告-基于RGB-D相机的机械臂物料分拣系统研究

评论请先登录 登录
全部评论 2

有点意思,过程很顺畅

2023-09-07 10:10:48 浙江省
回复

哇噻,视频看着好丝滑!〜〜〜〜

2023-08-31 10:21:47 浙江省
回复
  • 1
Lv.0
0
关注
7
粉丝
5
创作
57
获赞
所属专题
  • 使用3D相机MV-EB435i基于OpenCV的客流检测与异常识别的实现
  • 悉灵杯”课题研究进展(一)通过海康RGB-D相机获取带RGB信息的点云
  • “悉灵杯”课题研究-基于RGB_D相机的物品位置计算
  • “悉灵杯”课题研究-对RGB_D相机采集的三维点云处理
  • “悉灵杯”课题研究-RGB_D相机SDK集成及Open3d点云基本处理
  • “悉灵杯”课题研究-集成RGB_D相机SDK的Open3d点云可视化
  • “悉灵杯”课题研究-集成RGB_D相机SDK的Open3d点云功能UI项目开发(项目demo)
  • “悉灵杯”课题研究-RGB_D相机SDK三维点云存储
  • “悉灵杯”课题研究-OpenNI集成及示例代码开发
  • 悉灵杯”课题研究-MV-EB435i立体相机基于opencv图像处理使用yolov5的物体识别
  • “悉灵杯”课题研究-基于opecv的集成RGB_D相机SDK的基础小样物品颜色检测及人脸识别
  • OpenCV中利用knn进行数字(0-9)识别--RGB-D相机采集
  • “悉灵杯”课题研究-基于MV-EB435i的落差边缘检测算法开发记录
  • 悉灵杯”课题研究-LabVIEW集成及示例代码开发
  • “悉灵杯”课题研究-MV-EB435i立体相机集成Apriltags发布相机位姿
  • “悉灵杯”课题研究-MV-EB435i立体相机图像处理UI界面开发
  • “悉灵杯”课题研究-基于ROS1的RGB-D相机SDK集成及示例代码开发
  • 第二届“悉灵杯”课题移动机器人感知研究进展
  • “悉灵杯”课题研究—手眼标定方案
  • 第二届“悉灵杯”课题研究-基于RGB_D相机的室内环境建模
  • 悉灵杯”课题研究进展(二)-基于三维模型/场景点云的虚拟仿真数据生成
  • 悉灵杯”课题研究进展(一)-实例分割网络模型搭建与实验场景介绍
  • “悉灵杯”课题研究报告-基于RGB-D相机的2D和3D抓取定位方案研究
  • “悉灵杯”课题研究-基于点云配准算法GICP的3D抓取方案研究
  • “悉灵杯”课题研究-基于YOLO和GGCNN的物品平面抓取方案研究
  • 动态手势控制音频播放器-成果物
  • 第二届“悉灵杯”课题研究报告-动态手势控制音频播放器设计
  • 动态手势控制音频播放器(五)动态手势控制音频播放器exe
  • 动态手势控制音频播放器(四)动态手势识别系统的设计
  • 动态手势控制音频播放器(三)音频播放器设计
  • 动态手势控制音频播放器(二)动态手势识别系统的设计
  • 动态手势控制音频播放器(一)总体方案设计
  • 悉灵杯”课题研究进展(四)RGB-D相机引导机械臂分拣物料
  • 悉灵杯”课题研究进展(三)RGB-D相机引导机械臂分拣物料
  • 悉灵杯”课题研究进展(二)RGB-D相机引导机械臂分拣物料
  • ”悉灵杯”课题研究报告-基于RGB-D相机的机械臂物料分拣系统研究
  • 悉灵杯”课题研究报告-基于深度学习方法和虚拟仿真数据的机械臂引导方案
  • 第二届“悉灵杯”课题研究机械臂引导研究报告
  • 第二届“悉灵杯”课题研究机械臂引导研究进展(二)
  • 第二届“悉灵杯”课题研究机械臂引导研究进展(一)
相关阅读
  • usb共享网络更改路由
    2024-09-24 浏览 0
  • usb共享网络更改路由
    2024-09-24 浏览 0
  • 第三届“悉灵杯”基于MV-DT01SDU相机识别果蔬等数据集
    2024-10-14 浏览 0
  • 第三届“悉灵杯”基于MV-DT01SDU相机识别果蔬等数据集
    2024-10-14 浏览 0
  • 【保姆级教程】算法模块封装详解
    2024-10-17 浏览 0

请升级浏览器版本

您正在使用的浏览器版本过低,请升级最新版本以获得更好的体验。

推荐使用以下浏览器