单目纯视觉避障方案——2020中国机器人大赛FIRA避障仿真组决赛代码开源

单目纯视觉避障方案——2020中国机器人大赛FIRA避障仿真组决赛代码开源

特别鸣谢两位吴同学,董同学和曾同学为最终版代码做出的努力

比赛环境介绍

比赛仿真环境地址:https://github.com/zerowind168/SIMUROSOT-ROBOCHALLENGE

此为 2020 年 FIRA SIMUROSOT ROBO CHANLLENGE 中国赛区的比赛环境

操作系统: ubuntu 16.04

ROS版本: Kinectic

在这里插入图片描述

赛题要求

该比赛分为两个任务。简单来说,任务一提供了障碍物的位置信息,机器人可以通过一个单目摄像头返回的图像信息进行避障,最终到达对面的球门;任务二则只提供了视觉信息,最终目标仍然是到达对面的球门。

由于机器人采用双轮差动的方式行驶,给赛题的完成增加了不少难度。

在这里插入图片描述

比赛思路

最终版本代码的思路主要分为以下几个部分:

  1. 场地信息提取
  2. 通过计算图片的“质心”得到下一步的行驶方向
  3. 解算速度并发送至机器人驱动模块

该方案的出彩点

本方案的核心代码只有一行,且通过路径图像的质点实时导航的方式基本不需要过多的处理。

仍需优化的地方

  1. 通过路径图像的质点导航,可能被诱导向错误路径行驶或者导致机器人擦边障碍物;
  2. 检测球门的代码条件需要完全看不到视野内的障碍物,可能会导致看到蓝色球门时只能看到一根门柱,最终无法过门撞到柱子;
  3. 速度过慢,理论来讲增大速度的同时增加偏转幅度并不会导致避障效果的降低。

代码

# coding=utf-8
#四川大学ros避障代码,纯视觉算法
import rospy
import numpy as np
import math
import time
import cv2 as cv
from robot import Robot
from geometry_msgs.msg import Twist

#主要调整参数,调整转向幅度
k = -0.0086
#调整机器人速度,一般来说速度越快绝对值应该也增大,否则相当于一定程度减小转向幅度
v = 0.5
#erate,腐蚀系数,扩大障碍物及灰色背景的面积,一般来说腐蚀系数越大越安全,但太大可能导致可行的路径被遮挡
erate = 150
#背景灰度总和阀值,可调参数
gary_scale_value = 48000000
#向ros发布命令的周期与频率,rate=1/dt,一般需要和图像处理速度匹配
dt = 0.1
rate = 10

def navigation(bgr_image):
    H, W, C = bgr_image.shape
    image = np.array(bgr_image, dtype= np.uint8)
    hsv_image = cv.cvtColor(image, cv.COLOR_BGR2HSV)
    hsv_image = cv.GaussianBlur(hsv_image, (5, 5),0)
    #场景中颜色hsv上下界值
    lower_hsv_gray = np.array([0,0,46])         #灰色下界
    upper_hsv_gray = np.array([180,43,220])     #灰色上界
    lower_hsv_blue = np.array([100,43,46])      #蓝色下界
    upper_hsv_blue = np.array([155,255,255])    #蓝色上界
    lower_hsv_white = np.array([0,0,221])       #白色下界
    upper_hsv_white = np.array([180,30,255])    #白色上界
    lower_hsv_black = np.array([0,0,0])         #黑色下界
    upper_hsv_black = np.array([180,255,46])    #黑色上界
    print("carema turned on")


    #vigation mask
    mask_gray = cv.inRange(hsv_image,lowerb=lower_hsv_gray,upperb=upper_hsv_gray)#Gray,场景外颜色
    mask_blue = cv.inRange(hsv_image,lowerb=lower_hsv_blue,upperb=upper_hsv_blue)#Blue,对面球门颜色
    mask_white = cv.inRange(hsv_image,lowerb=lower_hsv_white,upperb=upper_hsv_white)#White,白线颜色
    mask_black = cv.inRange(hsv_image,lowerb=lower_hsv_black,upperb=upper_hsv_black) #black,障碍物颜色

    #反色处理,障碍物为黑色,可行路径为白色
    mask_path = ~(mask_black + mask_gray + mask_blue + mask_white)

    #膨胀+腐蚀去除场景中白线,膨胀增加白色,腐蚀增加黑色
    kernel = np.ones((5,5),np.uint8)
    mask_path = cv.erode(mask_path,kernel)
    mask_path = cv.dilate(mask_path,kernel)
    kernel = np.ones((55,55),np.uint8)
    mask_path = cv.dilate(mask_path,kernel)
    mask_path = cv.erode(mask_path,kernel)

    #腐蚀,增加障碍物(黑色)的面积,通过erate调整
    kernel = np.ones ((erate, erate), np.uint8)
    mask_path = cv.erode (mask_path, kernel)

    #moments函数求矩,可供计算空间矩,中心矩,和中心归一化矩
    #求整个可行路径的矩,对于01二值化的图像,m00代表灰度的总和,白色灰度255,黑色灰度是0
    moments_path = cv.moments(mask_path)
    gray_scale_path = moments_path['m00']

    moments_gray = cv.moments(mask_gray)
    gray_scale_gray = moments_gray['m00']

    moments_black = cv.moments(mask_black)
    gray_scale_black = moments_black['m00']

    moments_blue = cv.moments(mask_blue)
    gray_scale_blue = moments_blue['m00']

    #当有可行路径mask_path总灰度>255时,计算可行路径mask_path的质心并解算出w角速度,否则flag_stop=1,trutlebot原地旋转
    flag_stop=0
    if(gray_scale_path > 200):
        #算路径质心的x坐标
        x = int(moments_path['m10']/moments_path['m00'])
        #算图像中心x坐标与路径质心x坐标差值offset
        offset = x-(W/2)
        #根据offset解算出角速度,调整k可以调整偏转程度
        w = k * offset
        print (w)
    else:
        w = math.radians (5)
        flag_stop=1

    #flag_rush用于标志是否能使用向球门冲的函数
    #设置条件可以理解为机器人看到的背景像素足够多,不能看到障碍物,可以看到蓝色球门
    flag_rush = 0
    if(gray_scale_gray>gary_scale_value and gray_scale_black<200 and gray_scale_blue>200):
        x = int (moments_blue['m10'] / moments_blue['m00'])
        # 算图像中心x坐标与球门质心坐标x坐标差值offset
        offset = x - (W / 2)
        # 根据offset解算出角速度,调整k可以调整偏转程度
        w = k * offset
        if (abs (w) < math.radians (1)) :
            flag_rush=1
            print("flag_rush")
    return w,flag_rush,flag_stop

#运动函数,v值自定,w值根据navigation()解算得出
def run(robot):
    rate_run = rospy.Rate (rate)
    twist = Twist ()
    for i in xrange(0, 9999):
        img = robot.get_image ()
        w, flag_rush, flag_stop = navigation (img)
        twist.linear.x = v
        twist.angular.z = w
        if flag_stop:
            twist.linear.x = 0
        if flag_rush:
            twist.linear.x = 0
            twist.angular.z = 0
            robot.publish_twist (twist)
            break
        robot.publish_twist(twist)
        rate_run.sleep()
    rushDoor(robot)

def rushDoor(robot):
    rate_run = rospy.Rate (rate)
    twist = Twist ()
    for i in xrange (0, 9999) :
        twist.linear.x = 0.5
        twist.angular.z = 0
        robot.publish_twist (twist)
        rate_run.sleep ()

if __name__ == '__main__':
    robot = Robot()
    run(robot)

效果展示

2020中国机器人大赛FIRA避障仿真组算法alpha版本效果展示

<think>好的,用户想了解如何搭建用于视觉割草机器人的仿真环境。首先,我需要明确用户的需求,他们可能需要一个详细的步骤指南,包括工具选择和具体实现方法。考虑到用户提到的“视觉”,这意味着仿真环境需要依赖摄像头数据,可能涉及SLAM、目标检测和路径规划等模块。 首先,我需要推荐合适的仿真平台。Gazebo和Unity是常见的选择,但Gazebo更偏向机器人仿真,支持ROS集成,而Unity可能在图形渲染和场景多样性上更有优势。用户可能需要ROS的支持,所以Gazebo可能更适合。不过,也可以提到其他工具如CARLA,虽然它主要用于自动驾驶,但也能处理视觉相关的仿真。 接下来是环境建模。用户需要创建草坪、障碍物、不同光照条件等。这里可能需要使用3D建模工具如Blender,或者直接利用Gazebo的模型库。动态元素如移动障碍物和天气变化也是需要考虑的,这对测试机器人的鲁棒性很重要。 视觉传感器模拟部分,需要配置摄像头参数,比如分辨率、视场角、噪声模型等。Gazebo的摄像头插件可以生成深度和RGB数据,这对训练视觉算法很有帮助。同时,合成数据生成工具如NVidia的Isaac Sim或Google的DeepMind Lab可能有用,但用户可能需要更基础的解决方案。 算法开发与测试方面,需要集成视觉处理算法,比如用OpenCV或深度学习框架处理图像数据。SLAM算法如ORB-SLAM3可能适合定位和地图构建,而目标检测可以用YOLO或Faster R-CNN。路径规划可能需要ROS的move_base或自定义算法。 数据集与测试场景的构建也很重要。用户需要多样化的场景来验证算法的有效性,包括不同地形和光照条件。公开数据集如KITTI或Cityscapes可能作为补充,但需要根据割草场景调整。 最后,仿真与实机迁移需要考虑传感器校准和物理引擎的差异,可能需要域适应技术。性能评估指标如定位精度和避障成功率也是必须的。 用户可能还关心具体步骤,比如如何一步步搭建环境,或者有没有现成的模板项目。此外,他们可能对工具的学习曲线和资源需求有疑问。需要确保推荐的工具是开源且社区支持良好的,以降低用户的学习成本。 可能还需要提到ROS2的支持,因为现在很多项目转向了ROS2,但Gazebo和Unity都有相应的集成方式。另外,硬件在环(HIL)测试可能也是一个高级步骤,但用户现阶段可能只需要仿真。 总结下来,回答需要分步骤,涵盖平台选择、环境建模、传感器模拟、算法集成、测试场景构建以及迁移到实机的方法。同时,生成的相关问题要引导用户深入每个环节,比如工具比较、算法优化等。</think>### 基于视觉的割草机器人仿真环境搭建方法 #### 1. 仿真工具选择 推荐使用 **Gazebo + ROS** 或 **Unity + ROS** 合: - **Gazebo** 支持物理引擎和传感器高精度模拟,可通过插件模拟相机畸变、噪声等特性[^2] - **Unity** 提供更逼真的图形渲染,配合ROS#插件实现与ROS通信 ```bash # Gazebo安装示例 sudo apt-get install ros-noetic-gazebo-ros-pkgs ``` #### 2. 环境建模 构建典型割草场景需包含: - 草坪区域(使用不同高度/颜色的网格模拟) - 障碍物(随机分布的石头、玩具等3D模型) - 光照变化系统(模拟昼夜/多云环境) - 动态元素(移动的宠物/儿童模型) $$ \text{场景复杂度} = \sum_{i=1}^{n}(w_i \cdot o_i) $$ 其中$o_i$表示第$i$类物体数量,$w_i$为权重系数 #### 3. 视觉传感器模拟 配置双目/单目相机参数: ```xml <!-- Gazebo相机插件示例 --> <sensor type="camera" name="rgb_cam"> <update_rate>30</update_rate> <camera> <horizontal_fov>1.047</horizontal_fov> <image> <width>640</width> <height>480</height> </image> </camera> </sensor> ``` #### 4. 算法开发与测试 关键算法集成框架: 1. **视觉SLAM**:ORB-SLAM3[^3] 2. **语义分割**:DeepLabv3+(PyTorch实现) 3. **路径规划**:改进A*算法 ```python def improved_a_star(start, goal): open_set = PriorityQueue() open_set.put((heuristic(start, goal), start)) while not open_set.empty(): current = open_set.get()[1] if current == goal: return reconstruct_path() for neighbor in get_neighbors(current): tentative_g = g_score[current] + distance(current, neighbor) if tentative_g < g_score[neighbor]: came_from[neighbor] = current g_score[neighbor] = tentative_g f_score = tentative_g + heuristic(neighbor, goal) open_set.put((f_score, neighbor)) return failure ``` #### 5. 仿真-实机迁移 建议采用域随机化(domain randomization)技术: - 随机纹理贴图 - 动态光照变化(500-2000 lux) - 噪声注入(椒盐噪声、高斯噪声) - 相机参数扰动(±10%焦距变化)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值