RoboWaiter/robowaiter/algos/explore/pathsmoothing.py

133 lines
3.5 KiB
Python

"""
Path planning Sample Code with RRT with path smoothing
@author: AtsushiSakai(@Atsushi_twi)
"""
import math
import random
import matplotlib.pyplot as plt
import sys
import pathlib
sys.path.append(str(pathlib.Path(__file__).parent))
def get_path_length(path):
'''
计算路径长度
'''
le = 0
for i in range(len(path) - 1):
dx = path[i + 1][0] - path[i][0]
dy = path[i + 1][1] - path[i][1]
d = math.hypot(dx, dy)
le += d
return le
def get_target_point(path, targetL):
le = 0
ti = 0
lastPairLen = 0
for i in range(len(path) - 1):
dx = path[i + 1][0] - path[i][0]
dy = path[i + 1][1] - path[i][1]
d = math.hypot(dx, dy)
le += d
if le >= targetL:
ti = i - 1
lastPairLen = d
break
partRatio = (le - targetL) / lastPairLen
x = path[ti][0] + (path[ti + 1][0] - path[ti][0]) * partRatio
y = path[ti][1] + (path[ti + 1][1] - path[ti][1]) * partRatio
return [x, y, ti]
# def line_collision_check(first, second, map, path_resolution=25.0, robot_radius=5, scale_ratio=5):
# '''
# 检查first-second的直线是否穿过障碍物
# Args:
# path_resolution: 采样点分辨率
# '''
# x1 = first[0]
# y1 = first[1]
# x2 = second[0]
# y2 = second[1]
# path_x = [x1]
# path_y = [y1]
# # 计算距离和夹角
# dx = x2 - x1
# dy = y2 - y1
# d = math.hypot(dx, dy) # 欧式距离
# theta = math.atan2(dy, dx) # 夹角
#
# n_expand = math.floor(d / path_resolution) # first 和 second 之间的采样点数
# for _ in range(n_expand):
# x1 += path_resolution * math.cos(theta)
# y1 += path_resolution * math.sin(theta)
# path_x.append(x1)
# path_y.append(y1)
# if d <= path_resolution:
# path_x.append(x2)
# path_y.append(y2)
#
# for (x, y) in zip(path_x, path_y):
# (scale_x, scale_y) = (math.floor(x / scale_ratio), math.floor(y / scale_ratio)) # 向下取整
# if robot_radius > scale_ratio: # TODO: 根据robot_radius和scale_ratio选择不同的判断方式
# if map[scale_x, scale_y] or map[scale_x + 1, scale_y] or \
# map[scale_x, scale_y + 1] or map[scale_x + 1, scale_y + 1]: # 如果node周围的四个缩放坐标有障碍物
# return False
# return True
#
#
# def path_smoothing(path, map, max_iter=1000):
# '''
# 输入原路径,输出平滑后的路径
# Args:
# path: [(x,y),...]
# '''
# le = get_path_length(path)
#
# for i in range(max_iter):
# # Sample two points
# pickPoints = [random.uniform(0, le), random.uniform(0, le)] # 总路径长度中采样2个点
# pickPoints.sort()
# first = get_target_point(path, pickPoints[0])
# second = get_target_point(path, pickPoints[1])
#
# if first[2] <= 0 or second[2] <= 0:
# continue
#
# if (second[2] + 1) > len(path):
# continue
#
# if second[2] == first[2]:
# continue
#
# # collision check
# if not line_collision_check(first, second, map):
# continue
#
# # Create New path
# newPath = []
# newPath.extend(path[:first[2] + 1])
# newPath.append([first[0], first[1]])
# newPath.append([second[0], second[1]])
# newPath.extend(path[second[2] + 1:])
# path = newPath
# le = get_path_length(path)
#
# return path