在ROS中基于颜色做简单的物体识别

2023-05-16

ROS无法直接进行图像处理,需要借助于opencv,要使用cv_bridge把ROS 的图像数据格式转为Opencv可以使用的数据格式。即是一个提供ROS和OpenCV库提供之间的接口的开发包。然后可以将opencv处理好的图像再转换回ros中的数据格式。

包含的头文件如下:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"

#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <image_transport/image_transport.h>

从主函数开始:

int main(int argc, char** argv ) 
{
    //初始化节点
  	ros::init(argc, argv, "simple_grasping_vision_detection");
    //创建节点句柄
  	ros::NodeHandle n_;

    //输出等待2s..
  	ROS_INFO_STREAM("Waiting for two seconds..");
  	ros::WallDuration(2.0).sleep();

	float length = 0.3;
	float breadth = 0.3;

    //创建一个VisionManager类的对象
	VisionManager vm(n_, length, breadth);

	while (ros::ok())
	{
		// Process image callback
		ros::spinOnce();

		ros::WallDuration(2.0).sleep();
	}
	return 0;
}

首先初始化节点,节点名为simple_grasping_vision_detection,创建一个VisionManager类的对象vm,然后再循环中不断的进行处理。

看一下类的构造函数:

VisionManager::VisionManager(ros::NodeHandle n_, float length, float breadth) : it_(n_)
{
	this->table_length = length;
	this->table_breadth = breadth;

  	// Subscribe to input video feed and publish object location
  	image_sub_  = it_.subscribe("/probot_anno/camera/image_raw", 1, &VisionManager::imageCb, this);
	image1_pub_ = it_.advertise("/table_detect", 1);
	image2_pub_ = it_.advertise("/object_detect", 1);
}

构造函数输入有三个形参,VisionManager::VisionManager(ros::NodeHandle n_, float length, float breadth):

  • ros::NodeHandle n_  是节点句柄;
  • float length    是
  • float breadth  是

然后订阅了摄像头发布信息的话题,image_sub_  = it_.subscribe("/probot_anno/camera/image_raw", 1, &VisionManager::imageCb, this);

发布两个话题,一个是检测到的桌面,image1_pub_ = it_.advertise("/table_detect", 1);另外一个是检测到的物体,image2_pub_ = it_.advertise("/object_detect", 1);

当订阅者接收到图像之后就会进入到回调函数当中:

void VisionManager::imageCb(const sensor_msgs::ImageConstPtr &msg)
{
    ROS_INFO_STREAM("Processing the Image to locate the Object...");

    // ROS_INFO("Image Message Received");
    float obj_x, obj_y;
    get2DLocation(msg, obj_x, obj_y);

    // Temporary Debugging
    std::cout<< " X-Co-ordinate in Camera Frame :" << obj_x << std::endl;
    std::cout<< " Y-Co-ordinate in Camera Frame :" << obj_y << std::endl;
}

回调函数中先打印一条信息显示要开始识别,然后调用另外一个函数 get2DLocation进行识别,最后将识别的结果输出。obj_x, obj_y为最终目标的具体位置。

看一下get2DLocation函数的识别过程:

void VisionManager::get2DLocation(const sensor_msgs::ImageConstPtr &msg, float &x, float &y)
{
	cv::Rect tablePos;
	detectTable(msg, tablePos);

	detect2DObject(msg, x, y, tablePos);
	convertToMM(x, y);
}

在这个函数当中,首先使用detectTable(msg, tablePos)函数去识别table,函数的形参分别为输入的图像msg和table的位置tablePos。然后再使用detect2DObject(msg, x, y, tablePos)函数识别目标,该函数识别目标的范围是只在前一个函数检测到桌面的范围内识别。最后使用convertToMM(x, y)函数将检测到目标的像素位置转换成实际的位置。所以识别桌子有两个目的,第一个是为了所以识别目标的范围,第二个是为了从桌子识别的尺寸来确定目标真实目标的大小与像素大小的对应关系。

这函数真实一环一环又一环,一套一套又一套。

桌面识别:

下面看一下桌面识别:

void VisionManager::detectTable(const sensor_msgs::ImageConstPtr &msg, cv::Rect &tablePos)
{
	// Extract Table from the image and assign values to pixel_per_mm fields
        //从图像中提取表并将值赋给pixel_per_mm字段
	cv::Mat BGR[3];
    
    try
    {
      cv_ptr_ = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
    }
    catch (cv_bridge::Exception &e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }

	cv::Mat &image = cv_ptr_->image;

	split(image, BGR);
	cv::Mat gray_image_red = BGR[2];
	cv::Mat gray_image_green = BGR[1];
	cv::Mat denoiseImage;
	cv::medianBlur(gray_image_red, denoiseImage, 3);

	// Threshold the Image
	cv::Mat binaryImage = denoiseImage;
	for (int i = 0; i < binaryImage.rows; i++)
	{
		for (int j = 0; j < binaryImage.cols; j++)
		{
			int editValue = binaryImage.at<uchar>(i, j);
			int editValue2 = gray_image_green.at<uchar>(i, j);

			if ((editValue >= 0) && (editValue < 20) && (editValue2 >= 0) && (editValue2 < 20))
			{ // check whether value is within range.
				binaryImage.at<uchar>(i, j) = 255;
			}
			else
			{
				binaryImage.at<uchar>(i, j) = 0;
			}
		}
	}
	dilate(binaryImage, binaryImage, cv::Mat());

	// Get the centroid of the of the blob
	std::vector<cv::Point> nonZeroPoints;
	cv::findNonZero(binaryImage, nonZeroPoints);
	cv::Rect bbox = cv::boundingRect(nonZeroPoints);
	cv::Point pt;
	pt.x = bbox.x + bbox.width / 2;
	pt.y = bbox.y + bbox.height / 2;
	cv::circle(image, pt, 4, cv::Scalar(0, 0, 255), -1, 8);

	// Update pixels_per_mm fields
	pixels_permm_y = bbox.height / table_length;
	pixels_permm_x = bbox.width  / table_breadth;

        tablePos = bbox;

	// Test the conversion values
	std::cout << "Pixels in y" << pixels_permm_y << std::endl;
	std::cout << "Pixels in x" << pixels_permm_x << std::endl;

	// Draw Contours - For Debugging
	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;

	cv::findContours(binaryImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
	for (int i = 0; i < contours.size(); i++)
	{
		cv::Scalar color = cv::Scalar(255, 0, 0);
		cv::drawContours(image, contours, i, color, 3, 8, hierarchy, 0, cv::Point());
	}

	// Output modified video stream
 	image1_pub_.publish(cv_ptr_->toImageMsg());
}

使用try...catch函数将ros中的图像数据通过cv_bridge转化成opencv格式的数据,主要的语句为:cv_ptr_ = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);

接下来将RGB图像的红色和绿色两个通道分离出来:

    cv::Mat gray_image_red = BGR[2];
    cv::Mat gray_image_green = BGR[1];

medianBlur函数为进行中值滤波。

下面的for循环是为了在红色和绿色两个通道中确认黑色桌子的位置,然后将桌子位置的点像素值设置为255,其他地方位置的像素值设置为0。

	for (int i = 0; i < binaryImage.rows; i++)
	{
		for (int j = 0; j < binaryImage.cols; j++)
		{
			int editValue = binaryImage.at<uchar>(i, j);
			int editValue2 = gray_image_green.at<uchar>(i, j);

            //如果像素点在红色通道中的阈值在0-20之间并且在绿色通道中阈值也在0-20之间,那么就判断为黑色
			if ((editValue >= 0) && (editValue < 20) && (editValue2 >= 0) && (editValue2 < 20))
			{ // check whether value is within range.
				binaryImage.at<uchar>(i, j) = 255;
			}
			else
			{
				binaryImage.at<uchar>(i, j) = 0;
			}
		}
	}

接下来找桌面的中心位置,只需要先找像素值非零的位置:cv::findNonZero(binaryImage, nonZeroPoints);

再通过boundingRect函数计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的。

然后根据框的位置计算出桌面的中心点位置:

cv::Point pt;
pt.x = bbox.x + bbox.width / 2;
pt.y = bbox.y + bbox.height / 2;
//在中心点画一个红色的圈圈
cv::circle(image, pt, 4, cv::Scalar(0, 0, 255), -1, 8);

计算桌子的实际尺寸与像素尺寸的对应比例关系:

//table_length是桌子实际的长,bbox.height是像素长度
pixels_permm_y = bbox.height / table_length;

//table_length是桌子实际的宽,bbox.height是像素宽度
pixels_permm_x = bbox.width  / table_breadth;

画一个蓝色的框框出桌子的轮廓:

// Draw Contours - For Debugging
	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;

	cv::findContours(binaryImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
	for (int i = 0; i < contours.size(); i++)
	{
		cv::Scalar color = cv::Scalar(255, 0, 0);
		cv::drawContours(image, contours, i, color, 3, 8, hierarchy, 0, cv::Point());
	}

最后将识别到的结果先变为ROS中的图像格式,然后发布出去:

image1_pub_.publish(cv_ptr_->toImageMsg());

物体识别:

在绿色通道中对阈值进行识别,可以很容易的识别出绿色的易拉罐位置:

void VisionManager::detect2DObject(const sensor_msgs::ImageConstPtr &msg, float &pixel_x, float &pixel_y, cv::Rect &tablePos)
{
	// Implement Color Thresholding and contour findings to get the location of object to be grasped in 2D
	cv::Mat gray_image_green;
	cv::Mat BGR[3];
    
	try
    {
      cv_ptr_ = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
    }
    catch (cv_bridge::Exception &e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }

	cv::Mat &image = cv_ptr_->image;

	cv::split(image, BGR);

	gray_image_green = BGR[1];

	// Denoise the Image
	cv::Mat denoiseImage;
	cv::medianBlur(gray_image_green, denoiseImage, 3);

	// Threshold the Image
	cv::Mat binaryImage = denoiseImage;
	for (int i = 0; i < binaryImage.rows; i++)
	{
		for (int j = 0; j < binaryImage.cols; j++)
		{
			if((j<tablePos.x+3) || j>(tablePos.x+tablePos.width-3) || (i<tablePos.y+3) || i>(tablePos.y + tablePos.height-3))
			{
				binaryImage.at<uchar>(i, j) = 0;
			}
			else
			{
				int editValue = binaryImage.at<uchar>(i, j);

				if ((editValue > 100) && (editValue <= 255))
				{ // check whether value is within range.
					binaryImage.at<uchar>(i, j) = 255;
				}
				else
				{
					binaryImage.at<uchar>(i, j) = 0;
				}
			}
		}
	}
	dilate(binaryImage, binaryImage, cv::Mat());

	// Get the centroid of the of the blob
	std::vector<cv::Point> nonZeroPoints;
	cv::findNonZero(binaryImage, nonZeroPoints);
	cv::Rect bbox = cv::boundingRect(nonZeroPoints);
	cv::Point pt;
	pixel_x = bbox.x + bbox.width / 2;
	pixel_y = bbox.y + bbox.height / 2;

	// Test the conversion values
	std::cout << "pixel_x" << pixel_x << std::endl;
	std::cout << "pixel_y" << pixel_y << std::endl;

	// For Drawing
	pt.x = bbox.x + bbox.width / 2;
	pt.y = bbox.y + bbox.height / 2;
	cv::circle(image, pt, 4, cv::Scalar(0, 0, 255), -1, 8);

	// Draw Contours
	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;

	cv::findContours(binaryImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
	for (int i = 0; i < contours.size(); i++)
	{
		cv::Scalar color = cv::Scalar(255, 0, 0);
		cv::drawContours(image, contours, i, color, 3, 8, hierarchy, 0, cv::Point());
	}

	// Output modified video stream
 	image2_pub_.publish(cv_ptr_->toImageMsg());
}

计算目标中心位置

将物体的中心点位置进行变换,计算出中心位置相对于摄像头采集到图像的中心位置的左标(以中心点为(0,0)坐标原点)

void VisionManager::convertToMM(float &x, float &y)
{
	img_centre_x_ = 640 / 2;
	img_centre_y_ = 480 / 2;

	// Convert from pixel to world co-ordinates in the camera frame
	x = (x - img_centre_x_) / pixels_permm_x;
	y = (y - img_centre_y_) / pixels_permm_y;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在ROS中基于颜色做简单的物体识别 的相关文章

  • ros 样例代码和教程

    中国大学MOOC 机器人操作系统入门 课程代码示例 代码 https github com DroidAITech ROS Academy for Beginners 书 https legacy gitbook com book sych
  • 思岚RPLIDAR A2 在ubuntu 16.04上的测试

    1 下载雷达ROS包 首先在github上下载rplidar的ros包 下载指令为 默认安装了git git clone https github com Slamtec rplidar ros git 在ubuntu上创建工作空间 并将该
  • V-REP安装

    小知识 是当前目录 是父级目录 是根目录 1 下载V REP 官网地址 http www v rep eu downloads html 我用ubuntu16 04下载V REP PRO EDU V3 5 0 Linux tar 2 解压安
  • GG-CNN代码学习

    文章目录 1 源码网址 https github com dougsm ggcnn 2 数据集格式转化 下载后的康奈尔数据集 解压完之后里面的格式 里面的 tiff图像通过 txt文件转化得到 python m utils dataset
  • Ubuntu16.04安装ROS Kinetic详细步骤

    文章目录 ROS安装 配置Ubuntu软件仓库 设置sources list 设置密钥 更新Debian软件包索引 安装ROS 初始化 rosdep 环境配置 构建工厂依赖 测试安装 开发环境 ROS安装 ROS Kinetic只支持Wil
  • Raspberry Pi 上 ROS 服务器/客户端通过GPIO 驱动硬件

    ROS 服务 现在 想象一下你在你的电脑后面 你想从这个服务中获取天气 你 在你身边 被认为是客户端 在线天气服务是服务器 您将能够通过带有 URL 的 HTTP 请求访问服务器 将 HTTP URL 视为 ROS 服务 首先 您的计算机将
  • ROS 第四天 ROS中的关键组件

    1 Launch文件 通过XML文件实现多节点的配置和启动 可自动启动ROS Master
  • Ubuntu16.04及ROS Kinetic环境下安装使用RealSense SR300

    Ubuntu16 04及ROS Kinetic环境下安装使用RealSense SR300 1 准备条件 需要安装Ubuntu16 04及ROS Kinetic 2 安装驱动 安装realsense的驱动流程可以根据Github上的官方推荐
  • 局域网下ROS多机通信的网络连接配置

    1 在路由器设置中固定各机器IP地址 在浏览器中输入路由器的IP地址 例如TP LINK路由器的IP为 192 168 1 1 进入登录页面后 输入用户名和密码登录 用户名一般为admin 密码为自定义 在 基本设置 gt LAN设置 gt
  • 程序“catkin_init_workspace”尚未安装。 您可以使用以下命令安装: sudo apt install catkin

    程序 catkin init workspace 尚未安装 您可以使用以下命令安装 sudo apt install catkin 问题如图 先贴上解决后的效果 运行环境 ubuntu 16 04 ros版本 kinetic 问题解释 这个
  • 在 CLion 中设置 ROS 包

    我正在使用 CLion C IDE 来编辑 ROS 包 我可以通过打开CMakeLists txt文件 但是 我收到一个错误 FATAL ERROR find package catkin 失败 在工作区和 CMAKE PREFIX PAT
  • 无法加载 LZ4 支持的 Python 扩展。 LZ4 压缩将不可用

    我是 ROS 新手 我刚刚打开终端并输入roscore和另一个终端并键入rostopic node我收到这个错误 上面写着 无法加载 LZ4 支持的 Python 扩展 LZ4 压缩将不可用 我搜索并去了https pypi org pro
  • 不使用ros编译roscpp(使用g++)

    我正在尝试在不使用ROS其余部分的情况下编译roscpp 我只需要订阅一个节点 但该节点拥有使用旧版本ROS的节点 并且由于编译问题 我无法将我的程序与他的程序集成 我从git下载了源代码 https github com ros ros
  • 我的代码的 Boost 更新问题

    我最近将 boost 更新到 1 59 并安装在 usr local 中 我的系统默认安装在 usr 并且是1 46 我使用的是ubuntu 12 04 我的代码库使用 ROS Hydro 机器人操作系统 我有一个相当大的代码库 在更新之前
  • 如何访问 Heroku 中的 docker 容器?

    我已按照此处构建图像的说明进行操作 https devcenter heroku com articles container registry and runtime getting started https devcenter her
  • catkin_make 编译报错 Unable to find either executable ‘empy‘ or Python module ‘em‘...

    文章目录 写在前面 一 问题描述 二 解决方法 参考链接 写在前面 自己的测试环境 Ubuntu20 04 一 问题描述 自己安装完 anaconda 后 再次执行 catkin make 遇到如下问题 CMake Error at opt
  • 如何订阅“/scan”主题、修改消息并发布到新主题?

    我想通过订阅message ranges来改进turtlebot3的LDS 01传感器 通过应用一些算法修改messange ranges并将其发布到新主题 如下所示 但是当我运行编码时出现错误 错误是 遇到溢出的情况 错误是 运行时警告
  • 使用 CMake 链接 .s 文件

    我有一个我想使用的 c 函数 但它是用Intel编译器而不是gnu C编译器 我在用着cmake构建程序 我实际上正在使用ROS因此rosmake但基础是cmake所以我认为这更多是一个 cmake 问题而不是ROS问题 假设使用构建的文件
  • ROS中spin和rate.sleep的区别

    我是 ROS 新手 正在尝试了解这个强大的工具 我很困惑spin and rate sleep功能 谁能帮助我了解这两个功能之间的区别以及何时使用每个功能 ros spin and ros spinOnce 负责处理通信事件 例如到达的消息
  • 如何在Windows上安装机器人操作系统ROSJava?

    ROS 的文档很糟糕 一个很大的讽刺是 ROS 的 Groovy 和 ROSJava 版本的创建是为了让 Windows 等平台上的开发人员能够利用出色的机器人 SDK 而所有安装说明仍然面向 Linux ubuntu 用户 The ROS

随机推荐

  • 快速搭建samba 简单samba服务

    基于RedHat service smb restart etc init d smb start 1 安装samba包 yum install samba 2 修改相关配置文件 vim etc samba smb conf 3 添加相关s
  • 程序员=加班??掌握时间才能掌握人生

    总是有些人一生中有无数作为 xff0c 而更多的人耗费一生的时间最终换来了不过四个字 死因不详 序言 近几年 xff0c 读了比较多的书 xff0c 涉猎也比较广泛 xff0c 经管 xff0c 哲学 xff0c 心理学 xff0c 成功学
  • Presto集群Web UI界面详解

    Presto Web UI 可以用来检查和监控Presto集群 xff0c 以及运行的查询 他所提供的关于查询的详细信息可以更好的理解以及调整整个集群和单个查询 Presto Web UI所展示的信息都来自于Presto系统表 当你进入Pr
  • 【好书推荐】《华为数据之道》

    数据技术要产生实际价值 xff0c 需要良好的数据治理体系保驾护航 最近华为出版了 华为数据之道 一书 xff0c 给出了非数字原生企业在数据管理方面的实战经验 xff0c 特别适合于面临数字化转型的企业管理者 数据从业者 一 整体框架 华
  • 【好书推荐】《Python编程:从入门到实践(第2版)》

    第二版是2020年底发布的 xff0c 第二版相比较第一版更新了不少新东西 不错的python入门书 xff0c 第一部分讲基础知识 xff0c 第二部分讲了三个实际的项目 xff1a 一个小游戏 xff0c 一个数据可视化程序 xff0c
  • 【小技巧】Navicat查看数据库密码

    一 导出链接 二 导出的时候一定要勾选导出密码 三 导出文件用notepad 打开 四 打开网址 将如下代码复制进去 打开这个网址 https tool lu coderunner 将如下PHP代码复制进去 span class token
  • 看《狂飙》读人生,致敬2023!

    作为2023年的第一篇博文 xff0c 我不想写代码 xff0c 我想谈谈最近看的 狂飙 xff0c 总结了十条哲理 xff0c 共勉 希望我们的2023 xff0c 未来的人生会更加出彩 01 你以为很好的关系 xff0c 其实也就那么回
  • MySQL生成排序序号RN

    有时因为业务的需求 我们需要在查询出的数据中加上排序序号 例 span class token keyword SQL span span class token keyword select span a span class token
  • MySQL实现row_number排序功能(不用函数)

    MySQL ROW NUMBER 函数为结果集中的每一行生成序列号 MySQL ROW NUMBER 从8 0版开始引入了功能 在使用8 0版之前的数据库时 往往也会用到排序逻辑 那我们如何在不使用ROW NUMBER 函数的情况下来实现排
  • 一文读懂【数据埋点】

    数据埋点是数据采集领域 xff08 尤其是用户行为数据采集领域 xff09 的术语 xff0c 指的是针对特定用户行为或事件进行捕获 处理和发送的相关技术及其实施过程 比如用户某个icon点击次数 观看某个视频的时长等等 数据分析是我们获得
  • Hive几个常用数学函数

    span class token number 1 span span class token punctuation span span class token comment round 四舍五入 span span class tok
  • ubuntu解决中文乱码

    1 查看当前系统使用的字符编码 locale LANG 61 en US LANGUAGE 61 en US LC CTYPE 61 34 en US 34 LC NUMERIC 61 34 en US 34 LC TIME 61 34 e
  • Python 中使用 Azure Blob 存储

    本文介绍如何使用适用于 Python 的 Azure 存储客户端库来上传 blob 你可以上传 blob xff0c 打开 blob 流并写入流 xff0c 或者上传带有索引标记的 blob Azure 存储中的 Blob 已组织成容器 必
  • 视频加速播放插件-Global Speed

    有时候我们觉得看视频的过程中视频播放的太慢了 xff0c 希望能够加快一点播放的速度 xff0c 谷歌浏览器里面有很多有意思的插件 例如Global Speed就可以控制视频播放的速度 1 打开谷歌浏览器 xff0c 输出商店扩展应用地址
  • 激光SLAM之图优化理论

    1 常用的两种优化方法介绍 SLAM问题的处理方法主要分为滤波和图优化两类 滤波的方法中常见的是扩展卡尔曼滤波 粒子滤波 信息滤波等 xff0c 熟悉滤波思想的同学应该容易知道这类SLAM问题是递增的 实时的处理数据并矫正机器人位姿 比如基
  • ROS常用命令合集

    一 创建 ROS 工作空间 1 启动 ROS roscore 2 创建工作环境 mkdir p catkin ws src cd catkin ws src catkin init workspace 3 编译 ROS 程序 cd catk
  • 嵌入式开发笔记——调试组件SEGGER_HardFaultHandle

    作者 xff1a zzssdd2E mail xff1a zzssdd2 64 foxmail com 一 前言 在使用Cortex M内核的MCU进行开发时 xff0c 有时候会因为对内存错误访问等原因造成程序产生异常从而进入HardFa
  • Oracle 知识篇+几种常见的关系型数据库产品发展史

    说明 xff1a 本文为几种常见的关系型数据库产品发展史的简要描述 xff0c 供RDBMS兴趣爱好者参考温馨提示 xff1a 如果本文有写的不对的地方或者需要改进的地方 xff0c 各位可以留言或私信我进行修改和升级哦 下表为几款RDBM
  • MoveIt编程实现机械臂自主避障运动

    Moveit在规划路径的时候考虑如何躲避障碍物的问题 xff0c Moveit可以实时的检测空间中的障碍物 xff0c 并规划处轨迹绕过障碍物 在场景中加入障碍物方式 在Moveit中 具有一个规划场景监听器的模块结构 xff0c 可以用来
  • 在ROS中基于颜色做简单的物体识别

    ROS无法直接进行图像处理 xff0c 需要借助于opencv xff0c 要使用cv bridge把ROS 的图像数据格式转为Opencv可以使用的数据格式 即是一个提供ROS和OpenCV库提供之间的接口的开发包 然后可以将opencv