运动规划与轨迹跟踪
本文档介绍机器人运动规划和轨迹跟踪的基础知识,重点关注 LeBot 轮腿混合机器人的应用。运动规划是机器人从起点运动到终点的路径生成过程,轨迹跟踪是让机器人沿着规划的轨迹运动。
1. 运动规划基础
1.1 什么是运动规划
运动规划(Motion Planning)是在给定的环境中,为机器人找到一条从初始配置到目标配置的可行路径,同时满足各种约束条件(如避免碰撞、限制速度等)。
运动规划的层次:
┌─────────────────────────────────────┐
│ 高层规划:全局路径规划 │
│ 输出:关键路径点序列 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 中层规划:轨迹生成 │
│ 输出:平滑连续的轨迹 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 低层规划:轨迹跟踪控制 │
│ 输出:电机指令 │
└─────────────────────────────────────┘1.2 运动规划的分类
按方法分类:
基于采样的方法:RRT、PRM
- 优点:计算效率高,易于处理高维问题
- 缺点:可能不是最优解
基于图搜索的方法:A*、Dijkstra
- 优点:保证最优性(栅格化)
- 缺点:计算复杂度高
基于势场的方法:势场法
- 优点:直观简单
- 缺点:容易陷入局部最小值
基于曲线的方法:Bezier 曲线、B 样条
- 优点:轨迹平滑
- 缺点:需要预先确定控制点
1.3 LeBot 的运动规划挑战
对于轮腿混合机器人 LeBot:
- 运动学约束:轮子和腿各有不同的运动学特性
- 动力学约束:需要考虑加速度、扭矩限制
- 地形适应:不规则地面需要腿部调整
- 实时性:需要在有限计算资源内完成规划
- 鲁棒性:需要对环境变化有容错能力
2. 栅格化路径规划
2.1 环境表示
第一步是将连续的环境离散化为栅格。
python
import numpy as np
from collections import deque
import heapq
class GridEnvironment:
"""栅格环境表示"""
def __init__(self, width, height, resolution=0.1):
"""
初始化栅格环境
参数:
width: 环境宽度 (m)
height: 环境高度 (m)
resolution: 栅格分辨率 (m)
"""
self.width = width
self.height = height
self.resolution = resolution
# 栅格数量
self.grid_width = int(width / resolution)
self.grid_height = int(height / resolution)
# 栅格地图 (0: 可通行, 1: 障碍)
self.grid = np.zeros((self.grid_height, self.grid_width), dtype=np.uint8)
def add_obstacle(self, x, y, size):
"""
添加矩形障碍
参数:
x, y: 障碍中心位置 (m)
size: 障碍大小 (m)
"""
# 转换为栅格坐标
grid_x = int(x / self.resolution)
grid_y = int(y / self.resolution)
grid_size = int(size / self.resolution)
x_min = max(0, grid_x - grid_size // 2)
x_max = min(self.grid_width, grid_x + grid_size // 2)
y_min = max(0, grid_y - grid_size // 2)
y_max = min(self.grid_height, grid_y + grid_size // 2)
self.grid[y_min:y_max, x_min:x_max] = 1
def is_free(self, x, y):
"""检查栅格是否可通行"""
grid_x = int(x / self.resolution)
grid_y = int(y / self.resolution)
if 0 <= grid_x < self.grid_width and 0 <= grid_y < self.grid_height:
return self.grid[grid_y, grid_x] == 0
return False
def get_neighbors(self, x, y):
"""获取相邻的可通行栅格"""
neighbors = []
# 8 邻接
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
if dx == 0 and dy == 0:
continue
nx, ny = x + dx, y + dy
if self.is_free(nx, ny):
# 计算欧氏距离作为权重
distance = np.sqrt(dx**2 + dy**2)
neighbors.append(((nx, ny), distance))
return neighbors2.2 A* 搜索算法
A* 是最常用的栅格路径规划算法。
python
class AStarPlanner:
"""A* 路径规划器"""
def __init__(self, environment):
"""
初始化 A* 规划器
参数:
environment: GridEnvironment 实例
"""
self.env = environment
def heuristic(self, pos, goal):
"""
启发函数:欧氏距离
参数:
pos: 当前位置 (x, y)
goal: 目标位置 (x, y)
返回:
估计的距离
"""
dx = pos[0] - goal[0]
dy = pos[1] - goal[1]
return np.sqrt(dx**2 + dy**2)
def plan(self, start, goal):
"""
规划路径
参数:
start: 起点 (x, y)
goal: 目标点 (x, y)
返回:
路径点列表,如果无法到达返回 None
"""
# 转换为栅格坐标
start_grid = (int(start[0] / self.env.resolution),
int(start[1] / self.env.resolution))
goal_grid = (int(goal[0] / self.env.resolution),
int(goal[1] / self.env.resolution))
# 检查起点和终点可通行
if not self.env.is_free(start_grid[0], start_grid[1]):
print("起点不可通行")
return None
if not self.env.is_free(goal_grid[0], goal_grid[1]):
print("终点不可通行")
return None
# 初始化
open_set = [(0, start_grid)]
came_from = {}
g_score = {start_grid: 0}
f_score = {start_grid: self.heuristic(start_grid, goal_grid)}
closed_set = set()
while open_set:
# 选择 f 值最小的节点
_, current = heapq.heappop(open_set)
if current in closed_set:
continue
closed_set.add(current)
# 到达目标
if current == goal_grid:
# 回溯路径
path = []
while current in came_from:
path.append(current)
current = came_from[current]
path.append(start_grid)
path.reverse()
# 转换回物理坐标
physical_path = [
(p[0] * self.env.resolution, p[1] * self.env.resolution)
for p in path
]
return physical_path
# 探索邻接节点
neighbors = self.env.get_neighbors(current[0], current[1])
for (nx, ny), distance in neighbors:
if (nx, ny) in closed_set:
continue
tentative_g = g_score[current] + distance
if (nx, ny) not in g_score or tentative_g < g_score[(nx, ny)]:
came_from[(nx, ny)] = current
g_score[(nx, ny)] = tentative_g
f_score[(nx, ny)] = tentative_g + self.heuristic((nx, ny), goal_grid)
heapq.heappush(open_set, (f_score[(nx, ny)], (nx, ny)))
print("无法找到路径")
return None
# 使用示例
env = GridEnvironment(10, 10, 0.1)
env.add_obstacle(5, 5, 2)
env.add_obstacle(3, 7, 1.5)
planner = AStarPlanner(env)
path = planner.plan((1, 1), (9, 9))
if path:
print("找到路径,点数:", len(path))
for i, p in enumerate(path):
print(f" 点 {i}: ({p[0]:.2f}, {p[1]:.2f})")2.3 Dijkstra 算法
Dijkstra 算法保证找到最短路径。
python
class DijkstraPlanner:
"""Dijkstra 路径规划器"""
def __init__(self, environment):
self.env = environment
def plan(self, start, goal):
"""
使用 Dijkstra 算法规划路径
参数:
start: 起点 (x, y)
goal: 目标点 (x, y)
返回:
路径点列表
"""
start_grid = (int(start[0] / self.env.resolution),
int(start[1] / self.env.resolution))
goal_grid = (int(goal[0] / self.env.resolution),
int(goal[1] / self.env.resolution))
# 初始化距离
distances = {}
distances[start_grid] = 0
previous = {}
unvisited = set()
# 添加所有可通行的栅格
for y in range(self.env.grid_height):
for x in range(self.env.grid_width):
if self.env.grid[y, x] == 0:
pos = (x, y)
if pos not in distances:
distances[pos] = float('inf')
unvisited.add(pos)
while unvisited:
# 选择距离最小的未访问节点
current = min(unvisited, key=lambda p: distances[p])
if distances[current] == float('inf'):
break
if current == goal_grid:
# 构建路径
path = []
while current in previous:
path.append(current)
current = previous[current]
path.append(start_grid)
path.reverse()
physical_path = [
(p[0] * self.env.resolution, p[1] * self.env.resolution)
for p in path
]
return physical_path
unvisited.remove(current)
# 更新邻接节点
neighbors = self.env.get_neighbors(current[0], current[1])
for (nx, ny), distance in neighbors:
if (nx, ny) in unvisited:
new_distance = distances[current] + distance
if new_distance < distances[(nx, ny)]:
distances[(nx, ny)] = new_distance
previous[(nx, ny)] = current
return None3. 采样基础的路径规划
3.1 RRT(快速随机树)
RRT 是一种高效的采样基础算法。
python
import random
import math
class RRTPlanner:
"""RRT 路径规划器"""
def __init__(self, environment, max_iterations=5000, step_size=0.5):
"""
初始化 RRT 规划器
参数:
environment: GridEnvironment 实例
max_iterations: 最大迭代次数
step_size: 单步大小 (m)
"""
self.env = environment
self.max_iterations = max_iterations
self.step_size = step_size
self.tree = None
self.parent = None
def distance(self, p1, p2):
"""计算两点之间的欧氏距离"""
return math.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)
def random_point(self):
"""生成随机点"""
x = random.uniform(0, self.env.width)
y = random.uniform(0, self.env.height)
return (x, y)
def nearest_node(self, point):
"""找到树中最近的节点"""
min_dist = float('inf')
nearest = None
for node in self.tree:
dist = self.distance(point, node)
if dist < min_dist:
min_dist = dist
nearest = node
return nearest, min_dist
def steer(self, from_point, to_point):
"""
从 from_point 向 to_point 方向走一步
参数:
from_point: 起点
to_point: 方向点
返回:
新点
"""
dist = self.distance(from_point, to_point)
if dist < self.step_size:
return to_point
# 计算方向
ratio = self.step_size / dist
new_x = from_point[0] + (to_point[0] - from_point[0]) * ratio
new_y = from_point[1] + (to_point[1] - from_point[1]) * ratio
return (new_x, new_y)
def is_collision_free(self, p1, p2):
"""
检查 p1 到 p2 的路径是否无碰撞
参数:
p1: 点 1
p2: 点 2
返回:
True 如果无碰撞
"""
# 分段检查
steps = int(self.distance(p1, p2) / (self.env.resolution * 0.5)) + 1
for i in range(steps + 1):
t = i / (steps + 1) if steps > 0 else 0
x = p1[0] + (p2[0] - p1[0]) * t
y = p1[1] + (p2[1] - p1[1]) * t
if not self.env.is_free(int(x / self.env.resolution),
int(y / self.env.resolution)):
return False
return True
def plan(self, start, goal, goal_threshold=0.5):
"""
规划路径
参数:
start: 起点 (x, y)
goal: 目标点 (x, y)
goal_threshold: 到达目标的距离阈值 (m)
返回:
路径点列表,如果无法规划返回 None
"""
# 初始化树
self.tree = [start]
self.parent = {start: None}
for iteration in range(self.max_iterations):
# 生成随机点(有概率选择目标)
if random.random() < 0.1: # 10% 概率选择目标
rand_point = goal
else:
rand_point = self.random_point()
# 找最近节点
nearest, _ = self.nearest_node(rand_point)
# 向随机点方向走一步
new_point = self.steer(nearest, rand_point)
# 检查碰撞
if self.is_collision_free(nearest, new_point):
self.tree.append(new_point)
self.parent[new_point] = nearest
# 检查是否到达目标
if self.distance(new_point, goal) < goal_threshold:
self.parent[goal] = new_point
# 构建路径
path = []
current = goal
while current is not None:
path.append(current)
current = self.parent[current]
path.reverse()
print(f"RRT 在 {iteration} 次迭代后找到路径")
return path
print("RRT 无法找到路径")
return None
# 使用示例
env = GridEnvironment(10, 10, 0.1)
env.add_obstacle(4, 5, 3)
env.add_obstacle(7, 3, 2)
planner = RRTPlanner(env, max_iterations=5000, step_size=0.3)
path = planner.plan((1, 1), (9, 9))
if path:
print(f"找到 RRT 路径,点数: {len(path)}")4. 轨迹生成
4.1 轨迹平滑
路径规划得到的是离散的路径点,需要平滑处理。
python
import numpy as np
from scipy.interpolate import CubicSpline
class TrajectoryGenerator:
"""轨迹生成器"""
def __init__(self, path, velocity=1.0):
"""
初始化轨迹生成器
参数:
path: 路径点列表
velocity: 期望速度 (m/s)
"""
self.path = path
self.velocity = velocity
self.trajectory = None
self.timestamps = None
def linear_interpolation(self, num_points):
"""
线性插值:连接路径点
参数:
num_points: 插值点数
返回:
插值后的轨迹
"""
trajectory = []
for i in range(len(self.path) - 1):
p1 = np.array(self.path[i])
p2 = np.array(self.path[i + 1])
for t in np.linspace(0, 1, num_points):
point = p1 + t * (p2 - p1)
trajectory.append(tuple(point))
self.trajectory = trajectory
self._generate_timestamps()
return trajectory
def spline_interpolation(self, num_points=100):
"""
样条插值:平滑曲线
参数:
num_points: 插值点数
返回:
平滑的轨迹
"""
path_array = np.array(self.path)
# 计算路径的参数 t
t = np.linspace(0, len(self.path) - 1, len(self.path))
# 对 x 和 y 分别进行样条插值
cs_x = CubicSpline(t, path_array[:, 0])
cs_y = CubicSpline(t, path_array[:, 1])
# 生成平滑轨迹
t_smooth = np.linspace(0, len(self.path) - 1, num_points)
x_smooth = cs_x(t_smooth)
y_smooth = cs_y(t_smooth)
self.trajectory = list(zip(x_smooth, y_smooth))
self._generate_timestamps()
return self.trajectory
def _generate_timestamps(self):
"""生成时间戳"""
if self.trajectory is None:
return
self.timestamps = [0.0]
for i in range(1, len(self.trajectory)):
p1 = np.array(self.trajectory[i - 1])
p2 = np.array(self.trajectory[i])
distance = np.linalg.norm(p2 - p1)
time_interval = distance / self.velocity
self.timestamps.append(self.timestamps[-1] + time_interval)
def get_point_at_time(self, t):
"""
获取指定时间的轨迹点
参数:
t: 时间 (s)
返回:
轨迹点 (x, y)
"""
if self.timestamps is None:
return None
# 找到对应的时间段
for i in range(len(self.timestamps) - 1):
if self.timestamps[i] <= t <= self.timestamps[i + 1]:
# 线性插值
ratio = (t - self.timestamps[i]) / (self.timestamps[i + 1] - self.timestamps[i])
p1 = np.array(self.trajectory[i])
p2 = np.array(self.trajectory[i + 1])
point = p1 + ratio * (p2 - p1)
return tuple(point)
# 超出时间范围,返回最后一点
if t >= self.timestamps[-1]:
return self.trajectory[-1]
return self.trajectory[0]
# 使用示例
path = [(0, 0), (2, 1), (4, 3), (6, 2), (8, 4)]
gen = TrajectoryGenerator(path, velocity=2.0)
# 线性插值
linear_traj = gen.linear_interpolation(10)
print(f"线性插值: {len(linear_traj)} 个点")
# 样条插值(更平滑)
spline_traj = gen.spline_interpolation(100)
print(f"样条插值: {len(spline_traj)} 个点")
# 获取特定时间的点
for t in [0, 0.5, 1.0, 1.5]:
point = gen.get_point_at_time(t)
print(f"t={t}s: {point}")4.2 速度规划
规划沿轨迹的速度分布。
python
class VelocityProfile:
"""速度规划"""
def __init__(self, trajectory_length, max_velocity, max_acceleration):
"""
初始化速度规划
参数:
trajectory_length: 轨迹总长度 (m)
max_velocity: 最大速度 (m/s)
max_acceleration: 最大加速度 (m/s²)
"""
self.length = trajectory_length
self.v_max = max_velocity
self.a_max = max_acceleration
def trapezoidal_profile(self):
"""
梯形速度分布
返回:
(加速阶段长度, 匀速阶段长度, 减速阶段长度)
"""
# 加速和减速的距离
accel_distance = self.v_max**2 / (2 * self.a_max)
decel_distance = accel_distance # 对称
if 2 * accel_distance > self.length:
# 无法达到最大速度,三角形分布
accel_distance = self.length / 2
decel_distance = self.length / 2
const_distance = 0
else:
# 有匀速阶段
const_distance = self.length - 2 * accel_distance
return accel_distance, const_distance, decel_distance
def get_velocity_at_distance(self, distance):
"""
获取指定距离处的速度
参数:
distance: 沿轨迹的距离 (m)
返回:
速度 (m/s)
"""
accel_dist, const_dist, decel_dist = self.trapezoidal_profile()
if distance < accel_dist:
# 加速阶段
v = np.sqrt(2 * self.a_max * distance)
elif distance < accel_dist + const_dist:
# 匀速阶段
v = self.v_max
else:
# 减速阶段
remaining = self.length - distance
v = np.sqrt(2 * self.a_max * remaining)
return v
# 使用示例
vp = VelocityProfile(10.0, 2.0, 1.0)
print("速度分布:")
for dist in np.linspace(0, 10, 11):
v = vp.get_velocity_at_distance(dist)
print(f"距离 {dist:.1f}m: 速度 {v:.2f} m/s")5. 轨迹跟踪控制
5.1 Pure Pursuit 控制
Pure Pursuit 是一种常见的轨迹跟踪算法。
python
import math
class PurePursuitController:
"""Pure Pursuit 轨迹跟踪控制器"""
def __init__(self, lookahead_distance=1.0):
"""
初始化 Pure Pursuit 控制器
参数:
lookahead_distance: 前向距离 (m)
"""
self.lookahead_distance = lookahead_distance
def compute_steering_angle(self, robot_position, robot_heading, trajectory):
"""
计算转向角度
参数:
robot_position: 机器人位置 (x, y)
robot_heading: 机器人朝向角 (rad)
trajectory: 目标轨迹点列表
返回:
转向角度 (rad)
"""
# 找到前向距离内的目标点
target_point = None
for point in trajectory:
dx = point[0] - robot_position[0]
dy = point[1] - robot_position[1]
distance = np.sqrt(dx**2 + dy**2)
if distance >= self.lookahead_distance:
target_point = point
break
if target_point is None:
# 如果没找到,使用最后一点
target_point = trajectory[-1]
# 计算目标方向
dx = target_point[0] - robot_position[0]
dy = target_point[1] - robot_position[1]
target_heading = math.atan2(dy, dx)
# 计算航向误差
heading_error = target_heading - robot_heading
# 归一化到 [-π, π]
while heading_error > math.pi:
heading_error -= 2 * math.pi
while heading_error < -math.pi:
heading_error += 2 * math.pi
# 计算转向角度
distance_to_target = np.sqrt(dx**2 + dy**2)
steering_angle = math.atan2(2 * math.sin(heading_error), distance_to_target)
return steering_angle
def update(self, robot_position, robot_heading, velocity, trajectory, dt):
"""
执行一步控制更新
参数:
robot_position: 机器人位置
robot_heading: 机器人朝向
velocity: 前进速度 (m/s)
trajectory: 目标轨迹
dt: 时间步长 (s)
返回:
(新位置, 新朝向, 转向角度)
"""
# 计算转向角度
steering_angle = self.compute_steering_angle(
robot_position, robot_heading, trajectory
)
# 使用自行车模型更新位置
L = 0.5 # 轴距 (m),根据实际 LeBot 调整
new_x = robot_position[0] + velocity * math.cos(robot_heading) * dt
new_y = robot_position[1] + velocity * math.sin(robot_heading) * dt
new_heading = robot_heading + (velocity / L) * math.tan(steering_angle) * dt
return (new_x, new_y), new_heading, steering_angle
# 使用示例
controller = PurePursuitController(lookahead_distance=2.0)
# 模拟轨迹
trajectory = [(i*0.5, math.sin(i*0.3)) for i in range(20)]
robot_pos = (0, 0)
robot_heading = 0
velocity = 1.0
dt = 0.1
print("Pure Pursuit 跟踪:")
for _ in range(50):
new_pos, new_heading, steering = controller.update(
robot_pos, robot_heading, velocity, trajectory, dt
)
print(f"位置: ({new_pos[0]:.2f}, {new_pos[1]:.2f}), 朝向: {new_heading:.3f}")
robot_pos = new_pos
robot_heading = new_heading5.2 LQR 轨迹跟踪
使用 LQR(线性二次调节器)进行精确的轨迹跟踪。
python
from scipy import linalg
class LQRTrajectoryTracker:
"""LQR 轨迹跟踪控制器"""
def __init__(self, Q, R, dt=0.01):
"""
初始化 LQR 跟踪器
参数:
Q: 状态权重矩阵
R: 控制权重矩阵
dt: 采样时间
"""
self.Q = Q # 4x4 矩阵,权重状态误差
self.R = R # 2x2 矩阵,权重控制输入
self.dt = dt
def compute_optimal_gain(self, A, B):
"""
计算 LQR 增益
参数:
A: 状态转移矩阵 (4x4)
B: 控制矩阵 (4x2)
返回:
增益矩阵 K (2x4)
"""
# 求解代数Riccati方程
P = linalg.solve_continuous_are(A, B, self.Q, self.R)
# 计算增益 K = R^(-1) * B^T * P
K = np.linalg.inv(self.R) @ B.T @ P
return K
def update(self, state_error, A, B):
"""
计算控制输入
参数:
state_error: 状态误差向量 [x_err, y_err, theta_err, v_err]
A: 状态转移矩阵
B: 控制矩阵
返回:
控制输入 [v, omega]
"""
# 计算最优增益
K = self.compute_optimal_gain(A, B)
# 计算控制输入
u = -K @ state_error
return u
# 使用示例
# 定义 LeBot 的状态空间模型
# 状态: [x, y, theta, v]
# 控制: [v, omega]
Q = np.diag([10, 10, 5, 1]) # 位置和方向权重较高
R = np.diag([0.1, 0.1])
# 离散化模型
dt = 0.01
A = np.eye(4) # 简化的状态转移矩阵
B = np.array([[dt, 0],
[0, dt],
[0, dt],
[dt, 0]])
tracker = LQRTrajectoryTracker(Q, R, dt)6. LeBot 完整运动规划系统
python
class LeBotMotionPlanner:
"""LeBot 完整运动规划系统"""
def __init__(self, env_width=20, env_height=20):
self.env = GridEnvironment(env_width, env_height, 0.2)
self.astar_planner = AStarPlanner(self.env)
self.trajectory_gen = None
self.controller = PurePursuitController(lookahead_distance=1.0)
def add_obstacle(self, x, y, size):
"""添加障碍"""
self.env.add_obstacle(x, y, size)
def plan_mission(self, start, goal, velocity=1.0):
"""
规划完整的运动任务
参数:
start: 起点
goal: 目标点
velocity: 期望速度
返回:
(路径, 轨迹)
"""
# 第一步:路径规划
path = self.astar_planner.plan(start, goal)
if path is None:
print("无法规划路径")
return None, None
# 第二步:轨迹平滑
self.trajectory_gen = TrajectoryGenerator(path, velocity)
trajectory = self.trajectory_gen.spline_interpolation(100)
return path, trajectory
def execute_trajectory(self, trajectory, max_steps=1000):
"""
执行轨迹跟踪
参数:
trajectory: 轨迹点列表
max_steps: 最大步数
返回:
执行结果
"""
robot_pos = trajectory[0]
robot_heading = 0
velocity = 1.0
positions = [robot_pos]
for step in range(max_steps):
new_pos, new_heading, steering = self.controller.update(
robot_pos, robot_heading, velocity, trajectory, 0.01
)
positions.append(new_pos)
robot_pos = new_pos
robot_heading = new_heading
# 检查是否到达目标
dist_to_goal = np.sqrt((trajectory[-1][0] - new_pos[0])**2 +
(trajectory[-1][1] - new_pos[1])**2)
if dist_to_goal < 0.1:
print(f"到达目标,用时 {step} 步")
break
return positions
# 使用示例
planner = LeBotMotionPlanner()
planner.add_obstacle(5, 5, 2)
planner.add_obstacle(10, 8, 2)
path, trajectory = planner.plan_mission((1, 1), (18, 18), velocity=1.5)
if trajectory:
print(f"规划完成: 路径点 {len(path)}, 轨迹点 {len(trajectory)}")
positions = planner.execute_trajectory(trajectory)
print(f"执行完成: 记录 {len(positions)} 个位置点")7. 参数调整与优化
7.1 路径规划参数
| 参数 | 影响 | 推荐值 |
|---|---|---|
| 栅格分辨率 | 分辨率越高越精确,但计算量增加 | 0.1-0.5 m |
| 前向距离(Pure Pursuit) | 越大响应越平缓,越小响应越灵敏 | 1.0-3.0 m |
| 最大速度 | 限制机器人速度 | 1.0-2.0 m/s |
| 最大加速度 | 限制加速能力 | 0.5-1.0 m/s² |
7.2 调参流程
- 初始设置:使用推荐值
- 测试路径规划:简单环境下测试
- 调整轨迹参数:根据执行效果调整
- 测试跟踪控制:在实际机器人上测试
- 优化参数:根据性能指标持续改进
参考资源
- Lavalle, S. M. "Planning Algorithms". Cambridge University Press, 2006.
- Paden, B., et al. "A Survey of Motion Planning and Control Techniques for Self-driving Urban Vehicles". IEEE Transactions on Intelligent Vehicles, 2016.
- Thrun, S., Burgard, W., & Fox, D. "Probabilistic Robotics". MIT Press, 2005.
- ROS Navigation Stack: http://wiki.ros.org/navigation/
- OpenPlanner: https://github.com/autowarefoundation/core_planning/