rrt_exploration代码解析(三)—— filter.py

rrt_exploration代码解析(一)—— global_rrt_detector.cpp

rrt_exploration代码解析(二)—— local_rrt_detector.cpp

rrt_exploration代码解析(三)—— filter.py

rrt_exploration代码解析(四)—— assigner.py

filter.py

        第三个比较重要的文件是scripts文件夹下的filter.py,该文件的作用是过滤检测到的边界点,并将过滤后的边界点和边界点的聚类中心发布出来。

        回调函数,获取map地图数据、costmap全局代价地图数据、frontiers边界点数据。

def callBack(data, args):
    global frontiers, min_distance
    transformedPoint = args[0].transformPoint(args[1], data)
    x = [array([transformedPoint.point.x, transformedPoint.point.y])]
    if len(frontiers) > 0:
        frontiers = vstack((frontiers, x))
    else:
        frontiers = x


def mapCallBack(data):
    global mapData
    mapData = data


def globalMap(data):
    global global1, globalmaps, litraIndx, namespace_init_count, n_robots
    global1 = data
    if n_robots > 1:
        indx = int(data._connection_header['topic']
                   [litraIndx])-namespace_init_count
    elif n_robots == 1:
        indx = 0
    globalmaps[indx] = data

        节点函数node(),定义了过滤器的主节点。

        参数定义。

global frontiers, mapData, global1, global2, global3, globalmaps, litraIndx, n_robots, namespace_init_count
    rospy.init_node('filter', anonymous=False)

    # fetching all parameters
    map_topic = rospy.get_param('~map_topic', '/map')
    threshold = rospy.get_param('~costmap_clearing_threshold', 70)
    # this can be smaller than the laser scanner range, >> smaller >>less computation time>> too small is not good, info gain won't be accurate
    info_radius = rospy.get_param('~info_radius', 1.0)
    goals_topic = rospy.get_param('~goals_topic', '/detected_points')
    n_robots = rospy.get_param('~n_robots', 1)
    namespace = rospy.get_param('~namespace', '')
    namespace_init_count = rospy.get_param('namespace_init_count', 1)
    rateHz = rospy.get_param('~rate', 100)
    global_costmap_topic = rospy.get_param(
        '~global_costmap_topic', '/move_base_node/global_costmap/costmap')
    robot_frame = rospy.get_param('~robot_frame', 'base_link')

    litraIndx = len(namespace)
    rate = rospy.Rate(rateHz)

        订阅地图话题,获取地图信息。

rospy.Subscriber(map_topic, OccupancyGrid, mapCallBack)

        因为rrt是支持多机建图,因此在进行边界点过滤之前需要将各个robot的雷达数据进行凭借,同时订阅各个robot的globalcostmap数据。

    for i in range(0, n_robots):
        globalmaps.append(OccupancyGrid())

    if len(namespace) > 0:
        for i in range(0, n_robots):
            rospy.Subscriber(namespace+str(i+namespace_init_count) +
                             global_costmap_topic, OccupancyGrid, globalMap)
    elif len(namespace) == 0:
        rospy.Subscriber(global_costmap_topic, OccupancyGrid, globalMap)

        等待地图数据和各个robot的globalcostmap数据。

# wait if map is not received yet
    while (len(mapData.data) < 1):
        rospy.loginfo('Waiting for the map')
        rospy.sleep(0.1)
        pass
# wait if any of robots' global costmap map is not received yet
    for i in range(0, n_robots):
        while (len(globalmaps[i].data) < 1):
            rospy.loginfo('Waiting for the global costmap')
            rospy.sleep(0.1)
            pass

        获取地图数据后进行tf转换。


    tfLisn = tf.TransformListener()
    if len(namespace) > 0:
        for i in range(0, n_robots):
            tfLisn.waitForTransform(global_frame[1:], namespace+str(
                i+namespace_init_count)+'/'+robot_frame, rospy.Time(0), rospy.Duration(10.0))
    elif len(namespace) == 0:
        tfLisn.waitForTransform(
            global_frame[1:], '/'+robot_frame, rospy.Time(0), rospy.Duration(10.0))

        定义话题发布方,边界点frontiers、聚类中心centroids用于在rviz上显示,过滤后的边界点filtered_points用于给规划器分配robot探索。

    pub = rospy.Publisher('frontiers', Marker, queue_size=10)
    pub2 = rospy.Publisher('centroids', Marker, queue_size=10)
    filterpub = rospy.Publisher('filtered_points', PointArray, queue_size=10)

        等待边界点数据。

    while len(frontiers) < 1:
        pass

        对rviz显示用的marker进行初始化。初始化完成后进入主循环,主循环首先利用meanshift方法对边界点进行聚类,得到各个类的中心centroids。当只有一个边界点时聚类中心即是边界点。

        centroids = []
        front = copy(frontiers)
        if len(front) > 1:
            ms = MeanShift(bandwidth=0.3)
            ms.fit(front)
            centroids = ms.cluster_centers_  # centroids array is the centers of each cluster

        # if there is only one frontier no need for clustering, i.e. centroids=frontiers
        if len(front) == 1:
            centroids = front
        frontiers = copy(centroids)

        清除旧的边界点,原因是上一次采样得到的边界点可能已经被探索到了,那么在这一次探索时就需要将之前的边界点清除。(gridValue(globalmaps[i], x) 获取聚类中心当前代价地图上的值(注:栅格地图数据存储的格式一般是 0:无障碍,100:有障碍,-1:未知)判断该边界点的聚类中心是否已经被探索,若被探索到则将其从centroids中删除。

        z = 0
        while z < len(centroids):
            cond = False
            temppoint.point.x = centroids[z][0]
            temppoint.point.y = centroids[z][1]

            for i in range(0, n_robots):

                transformedPoint = tfLisn.transformPoint(
                    globalmaps[i].header.frame_id, temppoint)
                x = array([transformedPoint.point.x, transformedPoint.point.y])
                cond = (gridValue(globalmaps[i], x) > threshold) or cond
            if (cond or (informationGain(mapData, [centroids[z][0], centroids[z][1]], info_radius*0.5)) < 0.2):
                centroids = delete(centroids, (z), axis=0)
                z = z-1
            z += 1

        处理完边界点后将边界点发布出去,第一个发布filterpub发布由下一篇文章所提到的节点接收,用于安排robot对边界进行探索,pub、pub2发布的点由rviz订阅用于显示边界点和聚类中心。

        arraypoints.points = []
        for i in centroids:
            tempPoint.x = i[0]
            tempPoint.y = i[1]
            arraypoints.points.append(copy(tempPoint))
        filterpub.publish(arraypoints)
        pp = []
        for q in range(0, len(frontiers)):
            p.x = frontiers[q][0]
            p.y = frontiers[q][1]
            pp.append(copy(p))
        points.points = pp
        pp = []
        for q in range(0, len(centroids)):
            p.x = centroids[q][0]
            p.y = centroids[q][1]
            pp.append(copy(p))
        points_clust.points = pp
        pub.publish(points)
        pub2.publish(points_clust)
        rate.sleep()

        整个filter.py文件同样只是对边界点和地图信息进行处理,并没有对robot进行控制,下一篇博客将介绍如何给各个robot分配需要探索的边界点。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
rrt_exploration是一种基于快速随机树(Rapidly-exploring Random Trees,简称RRT)算法的探索路径规划代码。RRT算法是一种高效的无人机航迹规划算法,常用于探索未知环境。 rrt_exploration代码的主要功能是在未知环境中生成一条接近最优的路径,使得无人机可以探索整个环境。代码的实现包含以下几个步骤: 1. 初始化:代码首先会获取环境地图和无人机初始位置信息。同时,会设置RRT算法的参数,如树的最大生长步长、最大迭代次数等。 2. 构建树:代码会根据无人机的初始位置作为树的起点,开始构建随机树。在每次迭代中,代码会生成一个随机点,并将该点与树上的最近节点进行连接,形成一条新的树枝。 3. 节点选择:代码会根据一定的策略,选择合适的节点进行生长。常用的策略有最近邻节点和最优路径代价节点选择。 4. 碰撞检测:在每次生成新节点时,代码会进行碰撞检测,确保新生成的路径不会与障碍物相交。 5. 收敛判断:当生成的树趋近于目标位置时,代码会判断是否达到收敛条件。如果达到收敛条件,则会停止迭代,树构建完成。 6. 最优路径回溯:在收敛时,代码会回溯树,找到从起点到目标位置的最优路径。最优路径一般是根据路径长度、代价函数等标准来评估的。 总的来说,rrt_exploration代码通过RRT算法在未知环境中生成一条最优路径,用于无人机的探索任务。通过树的构建和回溯,代码能够快速生成一条安全且高效的路径规划结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

libenfan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值