示例#1
0
    def pf_planning(self, **param):
        ''' 人工势场法(potential field planning 算法)。
        
        本函数可对 self.map 进行人工势场法规划并绘制图像。
        
        Args:
            **param: 关键字参数,用以配置规划参数    
                     a: 引力增益,默认20。int
                     r: 斥力增益,默认20.0。float
                     d: 障碍物的作用范围,默认30.0。float
                     p: 绘制图像指令,缺省表示绘制,’None‘表示不绘制。string
        Return:
            本函数没有返回值,但会根据计算结果赋值(或定义)以下属性变量:
                self.img_potential: 势场图数据。numpy.mat
                self.point_road: 路径点数据。numpy.mat
        Raises:
            暂无明显的接口错误
        Example:
            mr = MotionRoadmap(img)
            mr.pf_planning(a=25, r=30, p='None')
        
        '''
        print('开始人工势场法路径规划,请等待...')
        ## 预处理
        # 关键字参数处理
        k_a = 50.0
        k_r = 50.0
        d_o = 3.0 
        limit_try = 1000
        if 'a' in param:
            step_size = param['a']
        if 'r' in param:
            threshold = param['r']
        if not ('p' in param):
            param['p'] = True
        # 地图灰度化
        image_gray = cv2.cvtColor(self.map, cv2.COLOR_BGR2GRAY)
        # 地图二值化
        ret,img_binary = cv2.threshold(image_gray, 127, 255, cv2.THRESH_BINARY)
        # 创建障碍物坐标集
        mat_img_binary = np.mat(img_binary)
        postion_obs = np.argwhere(mat_img_binary == [0])
        # 成功标识
        path_found = True
        
        ## 创建势场图
        img_potential = np.mat(img_binary) * 0.0
        for x in range(img_potential.shape[0]):
            for y in range(img_potential.shape[1]):
                # 目标点的引力场 ug
                ug = k_a * mpt.straight_distance(np.mat([x, y]), self.point_goal)[0, 0]
                # 障碍物的斥力场 uo
                # 最近障碍物的距离
                d_min = np.min(mpt.straight_distance(postion_obs, np.mat([x, y])), 0)
                if d_min < d_o:
                    if d_min <= 0.5:
                        d_min = 0.1 # 所有障碍物内部点都作为障碍物边缘点处理
                    uo = k_r * (1.0 / d_min - 1.0 / d_o)**2 * mpt.straight_distance(np.mat([x, y]), self.point_goal)[0, 0] ** 0.25
                else:
                    # 如果障碍物距离大于 d_o ,则不发生斥力作用
                    uo = 0.0
                img_potential[x, y] = ug + uo
        print("势场图创建完毕")
        self.img_potential = img_potential
        point_current = self.point_start
        potential_current = img_potential[point_current[0,0],point_current[0,1]]
        motion_direction = np.mat([[1, 0], [0,  1], [-1, 0], [0,  -1],
                                   [1, 1], [1, -1], [-1, 1], [-1, -1]])
        point_road = point_current
        num_try = 0
        while mpt.straight_distance(point_current, self.point_goal)[0, 0] > 0.0:
            if num_try < limit_try:

                potential_temp = potential_current
                point_temp = point_current
                for d in motion_direction:
                    local_tag = True
                    index_x = point_temp[0, 0] + d[0, 0]
                    index_y = point_temp[0, 1] + d[0, 1]
                    if ((index_x < 0) or (index_x >= img_potential.shape[0]) or 
                        (index_y < 0) or (index_y >= img_potential.shape[1])):
                        potential_next = float('inf')
                    else:
                        potential_next = img_potential[index_x, index_y]
                    if potential_current > potential_next:
                        potential_current = potential_next
                        point_current = np.mat([index_x, index_y])
                            
                point_road = np.vstack((point_road, point_current))
                num_try = num_try + 1
            else:
                path_found = False
                break
        self.point_road = point_road
        ## 根据关键字确定是否绘图
        if not(param['p'] == 'None'):
            if (path_found == True):
                print('找到解!')
                mpt.potential_plot(self.map, img_potential, point_road)
            else:
                print('陷入局部最优,没有找到解,无法绘图。')
                mpt.potential_plot(self.map, img_potential, point_road)
示例#2
0
    def rrt_planning(self, **param):
        ''' 快速扩展随机树算法(RRT算法)。
        
        本函数可对 self.map 进行 RRT 规划并绘制图像。
        
        Args:
            **param: 关键字参数,用以配置规划参数    
                     s: 搜索步长,默认20。int
                     t: 判断阈值,默认20。float
                     l: 尝试次数。默认20000。int
                     p: 绘制图像指令,缺省表示绘制,’None‘表示不绘制。string
        Return:
            本函数没有返回值,但会根据计算结果赋值(或定义)以下属性变量:
                self.rrt_tree: 所生成的rrt树。numpy.mat
                    数据含义: [[横坐标, 纵坐标, 父节点索引]],其中第一个点为根,最后一个点为终点梢

        Raises:
            暂无明显的接口错误
        Example:
            mr = MotionRoadmap(img)
            mr.rrt_planning(s=25, t=30, l=15000, p='None')
        
        '''
        print('开始 RRT 路径规划,请等待...')
        # 关键字参数处理
        step_size = 20
        threshold = 20 # 距离阈值,小于此值将被视作同一个点,不可大于 step_size
        limit_try = 20000
        if 's' in param:
            step_size = param['s']
        if 't' in param:
            threshold = param['t']
        if 'l' in param:
            limit_try = param['l']
        if not ('p' in param):
            param['p'] = True
        # 地图灰度化
        image_gray = cv2.cvtColor(self.map, cv2.COLOR_BGR2GRAY)
        # 地图二值化
        ret,img_binary = cv2.threshold(image_gray, 127, 255, cv2.THRESH_BINARY) 
        # 初始化 RRT 树:[横坐标,纵坐标,父节点索引]
        rrt_tree = np.hstack((self.point_start, [[0]]))
        # 初始化尝试次数
        num_try = 0
        # 成功标识
        path_found = False
        
        while num_try <= limit_try:
          ## 随机生长采样点
          if np.random.rand() < 0.5:
              # 在地图范围内随机采样一个像素
              sample = np.mat(np.random.randint(0, img_binary.shape[0] - 1, (1, 2)))
          else:
              sample = self.point_goal
          
          ## 选择rrt树中离采样点最近的点
          # 计算各点与采样点的距离
          mat_distance = mpt.straight_distance(rrt_tree[:, 0 : 2], sample)
          # 距离最小点的索引
          index_close = np.argmin(mat_distance, 0)[0, 0] #末尾索引用以取数值,否则为矩阵
          point_close = rrt_tree[index_close, 0 : 2]

          ## 从距离最小点向采样点移动 step_size 距离,并进行碰撞检测
          theta_dir = math.atan2(sample[0, 0] - point_close[0, 0], sample[0, 1] - point_close[0, 1])
          point_new = point_close + step_size * np.mat([math.sin(theta_dir), math.cos(theta_dir)])
          # 将坐标化为整数
          point_new = np.around(point_new)
          if not mpt.check_path(point_close, point_new, img_binary):
              num_try = num_try + 1
              continue

          ## 成功检测
          if mpt.straight_distance(point_new, self.point_goal) < threshold:
              path_found = True
              # 加入到rrt树
              point_new = np.hstack((point_new, [[index_close]]))
              rrt_tree = np.vstack((rrt_tree, point_new))
              break
          
          ## 计算rrt树中各点与新点的距离,如果均大于 threshold 的,则添加新点到rrt树
          mat_distance = mpt.straight_distance(rrt_tree[:, 0 : 2], point_new)
          if np.min(mat_distance, 0) < threshold:
              num_try = num_try + 1
              continue
          # 为新点加入父节点索引
          point_new = np.hstack((point_new, [[index_close]]))
          rrt_tree = np.vstack((rrt_tree, point_new))

        if path_found == True:
            print('规划成功!')
            self.rrt_tree = rrt_tree
        else:
            print('没有找到解。')
        
        ## 根据关键字确定是否绘图
        if not(param['p'] == 'None'):
            if (path_found == True):
                self.rrt_tree
                mpt.tree_plot(self.map, self.rrt_tree)
            else:
                print('没有找到解,无法绘图。')
示例#3
0
 def prm_planning(self, **param):
     ''' 概率路线图算法(PRM算法)。
     
     本函数可对 self.map 进行 PRM 规划并绘制图像。
     
     Args:
         **param: 关键字参数,用以配置规划参数    
                  s: 采样点个数,默认100。int
                  n: 邻域距离,默认100。float
                  p: 绘制图像指令,缺省表示绘制,’None‘表示不绘制。string
     Return:
         本函数没有返回值,但会根据计算结果赋值(或定义)以下属性变量:
             self.vertex: 顶点集,随机采样所生成的顶点。numpy.mat
             self.adjacency_mat: 邻接矩阵,定义顶点之间的连接性。numpy.mat
             self.close_list: 闭集,A*算法所得到的闭集。numpy.mat
                              数据含义:[[节点索引,父节点索引,路径总代价]]
     Raises:
         暂无明显的接口错误
     Example:
         mr = MotionRoadmap(img)
         mr.prm_planning(s=50, n=150, p='None')
     '''
     print('开始 PRM 路径规划,请等待...')
     # 关键字参数处理
     num_sample = 100
     distance_neighbor = 200
     if 's' in param:
         num_sample = param['s']
     if 'n' in param:
         distance_neighbor = param['n']
     if not ('p' in param):
         param['p'] = True
     # 地图灰度化
     image_gray = cv2.cvtColor(self.map, cv2.COLOR_BGR2GRAY)
     # 地图二值化
     ret,img_binary = cv2.threshold(image_gray, 127, 255, cv2.THRESH_BINARY) 
     # 初始化顶点集
     vertex = np.vstack((self.point_start, self.point_goal))
     ## 构造地图
     # 采样并添加顶点
     while vertex.shape[0] < (num_sample + 2):
         # 随机采样
         x = np.mat(np.random.randint(0, img_binary.shape[0] - 1, (1, 2)))
         # 点碰撞检测,将合理点添加到顶点集
         if mpt.check_point(x[0, :], img_binary):
             vertex = np.vstack((vertex, x))
     ## 构造邻接矩阵
     adjacency_mat = np.zeros((num_sample + 2, num_sample + 2))
     for i in range(num_sample + 2):
         for j in range(num_sample + 2):
             # 如果距离小于 distance_neighbor 且路径不碰撞
             if ((mpt.straight_distance(vertex[i, :], vertex[j, :]) <= distance_neighbor) and 
                 (mpt.check_path(vertex[i, :], vertex[j, :], img_binary))):
                 adjacency_mat[i, j] = 1 # 邻接矩阵置为1
     ## A*算法搜索最佳路径
     self.vertex, self.adjacency_mat, self.close_list, find = mpt.A_star_algorithm(vertex, adjacency_mat, 0, 1)
     ## 根据关键字确定是否绘图
     if not(param['p'] == 'None'):
         if (find == True):
             mpt.A_star_plot(self.map, self.vertex, self.adjacency_mat, self.close_list)
         else:
             print('没有找到解,无法绘图!')