轨迹优化 | 基于边界值问题(BVP)的无约束路径平滑(附ROS C++/Python仿真)

发布于:2025-08-19 ⋅ 阅读:(13) ⋅ 点赞:(0)

0 专栏介绍

🔥课设、毕设、创新竞赛必备!🔥本专栏涉及更高阶的运动规划算法轨迹优化实战,包括:曲线生成、碰撞检测、安全走廊、优化建模(QP、SQP、NMPC、iLQR等)、轨迹优化(梯度法、曲线法等),每个算法都包含代码实现加深理解

🚀详情:运动规划实战进阶:轨迹优化篇


1 边界值问题建模

轨迹优化 | 基于边界中间值问题(BIVP)的路径平滑求解器(附C++/Python仿真)中,我们介绍过边界中间值问题(Boundary Intermediate Value Problem, BIVP)的形式:

min ⁡ ∫ t 0 t k v ( t ) T W v ( t ) + ρ ( t k − t 0 ) s.t.   z [ r i − 1 ] ( i − 1 ) ( t i ) = z ^ i ,   1 ⩽ i < k ,   r i ⩽ s   z [ s − 1 ] ( s − 1 ) ( t 0 ) = z ^ 0 ,   z [ s − 1 ] ( s − 1 ) ( t k ) = z ^ k \begin{aligned} \min & \int_{t_0}^{t_k} \boldsymbol{v}(t)^T \boldsymbol{W} \boldsymbol{v}(t) + \rho(t_k - t_0) \\ \text{s.t.} & \ z_{[r_i-1]}^{(i-1)}(t_i) = \widehat{z}_i, \ 1 \leqslant i < k, \ r_i \leqslant s \\ & \ z_{[s-1]}^{(s-1)}(t_0) = \widehat{z}_0, \ z_{[s-1]}^{(s-1)}(t_k) = \widehat{z}_k \end{aligned} mins.t.t0tkv(t)TWv(t)+ρ(tkt0) z[ri1](i1)(ti)=z i, 1i<k, ris z[s1](s1)(t0)=z 0, z[s1](s1)(tk)=z k

其中定义 z [ s − 1 ] ( t ) ≜ ( z T , z ˙ T , ⋯   , z ( s − 1 ) T ) T z^{[s-1]}(t) \triangleq (z^T, \dot{z}^T, \cdots, z^{(s-1)^T})^T z[s1](t)(zT,z˙T,,z(s1)T)T v ( t ) ≜ z ( s ) ( t ) \boldsymbol{v}(t) \triangleq z^{(s)}(t) v(t)z(s)(t)

将BIVP的中间值约束移除将得到更特殊的边界值问题(Boundary Value Problem, BVP):

min ⁡ z ( t ) , T ∫ t 0 T v ( t ) T W v ( t ) + ρ T    s . t . z [ s − 1 ] ( 0 ) = z ˉ 0 , z [ s − 1 ] ( T ) = z ˉ T \underset{\boldsymbol{z}\left( t \right) ,T}{\min}\int_{t_0}^T{\boldsymbol{v}\left( t \right) ^T\boldsymbol{Wv}\left( t \right)}+\rho T\,\,\\\mathrm{s}.\mathrm{t}. \boldsymbol{z}^{\left[ s-1 \right]}\left( 0 \right) =\boldsymbol{\bar{z}}_0, \boldsymbol{z}^{\left[ s-1 \right]}\left( T \right) =\boldsymbol{\bar{z}}_T z(t),Tmint0Tv(t)TWv(t)+ρTs.t.z[s1](0)=zˉ0,z[s1](T)=zˉT

其仍然满足BIVP的最优性原理,即最优解 z ∗ ( t ) : [ t 0 , t k ] → R n z^*(t): [t_0, t_k] \to \mathbb{R}^n z(t):[t0,tk]Rn的充要条件为:

  • z ∗ z^* z 的第 i i i段轨迹是 2 s − 1 2s - 1 2s1 次多项式;
  • 边界条件与中间点条件成立;
  • z ∗ z^* z t = t i t = t_i t=ti 处满足 r ˉ i − 1 \bar{r}_i - 1 rˉi1 次连续可微,其中 r ˉ i = 2 s − r i \bar{r}_i = 2s - r_i rˉi=2sri

所以最优解满足无中间值条件的约束方程

[ F 0 E k ] P 1 = [ D 0 D k ] \left[ \begin{array}{c} \boldsymbol{F}_0\\ \boldsymbol{E}_k\\\end{array} \right] \boldsymbol{P}_1=\left[ \begin{array}{c} \boldsymbol{D}_0\\ \boldsymbol{D}_k\\\end{array} \right] [F0Ek]P1=[D0Dk]

对于BVP问题来说,可以更进一步写出矩阵的结构。对于单个微分平坦维度有

d = A F ( T ) p \boldsymbol{d}=\boldsymbol{A}_F\left( T \right) \boldsymbol{p} d=AF(T)p

其中 p = [ p 0 p 1 ⋯ p n ] T ∈ R 2 s \boldsymbol{p}=\left[ \begin{matrix} p_0& p_1& \cdots& p_n\\\end{matrix} \right] ^T\in \mathbb{R} ^{2s} p=[p0p1pn]TR2s d = [ z 0 ⋯ z 0 ( s − 1 ) z T ⋯ z T ( s − 1 ) ] ∈ R 2 s \boldsymbol{d}=\left[ \begin{matrix} z_0& \cdots& z_{0}^{\left( s-1 \right)}& z_T& \cdots& z_{T}^{\left( s-1 \right)}\\\end{matrix} \right] \in \mathbb{R} ^{2s} d=[z0z0(s1)zTzT(s1)]R2s

A F ( t ) = [ E O F ( t ) G ( t ) ] \boldsymbol{A}_F\left( t \right) =\left[ \begin{matrix} \boldsymbol{E}& \boldsymbol{O}\\ \boldsymbol{F}\left( t \right)& \boldsymbol{G}\left( t \right)\\\end{matrix} \right] AF(t)=[EF(t)OG(t)]

各分块矩阵形式为

E i j = { ( i − 1 ) !      i f i = j 0        i f i ≠ j , F i j ( t ) = { ( j − 1 ) ! ( j − i ) ! t j − i          i f   i ⩽ j 0       i f   i > j , G i j ( t ) = ( s + j − 1 ) ! ( s + j − i ) ! t s + j − i \begin{aligned}\boldsymbol{E}_{ij}&=\begin{cases} \left( i-1 \right) ! \ \ \ \ \mathrm{if} i=j\\ 0 \ \ \ \ \ \ \mathrm{if} i\ne j\\\end{cases}, \\ \boldsymbol{F}_{ij}\left( t \right) &=\begin{cases} \frac{\left( j-1 \right) !}{\left( j-i \right) !}t^{j-i}\,\,\ \ \ \ \ \mathrm{if}\ i\leqslant j\\ 0 \ \ \ \ \ \mathrm{if}\ i>j\\\end{cases}, \\\boldsymbol{G}_{ij}\left( t \right) &=\frac{\left( s+j-1 \right) !}{\left( s+j-i \right) !}t^{s+j-i}\end{aligned} EijFij(t)Gij(t)={(i1)!    ifi=j0      ifi=j,={(ji)!(j1)!tji     if ij0     if i>j,=(s+ji)!(s+j1)!ts+ji

为了避免大规模矩阵求逆,在应用中也可以直接采用逆矩阵版本

p = A B ( T ) d \boldsymbol{p}=\boldsymbol{A}_B\left( T \right) \boldsymbol{d} p=AB(T)d

其中

A B ( t ) = [ U O V ( t ) W ( t ) ] \boldsymbol{A}_B\left( t \right) =\left[ \begin{matrix} \boldsymbol{U}& \boldsymbol{O}\\ \boldsymbol{V}\left( t \right)& \boldsymbol{W}\left( t \right)\\\end{matrix} \right] AB(t)=[UV(t)OW(t)]

各分块矩阵形式为

U i j = { 1 ( i − 1 ) !    i f i = j 0 i f i ≠ j , V i j ( t ) = ∑ k = 0 s − max ⁡ { i , j } ( − 1 ) k ( s i + k ) ( 2 s − j − k − 1 s − 1 ) ( j − 1 ) ! ( − 1 ) i t s + i − j W i j ( t ) = ∑ k = 0 s − max ⁡ { i , j } ( s − k − 1 i − 1 ) ( 2 s − j − k − 1 s − 1 ) ( j − 1 ) ! ( − 1 ) i + j t s + i − j \begin{aligned}\boldsymbol{U}_{ij}&=\begin{cases} \frac{1}{\left( i-1 \right) !}\,\, \mathrm{if} i=j\\ 0 \mathrm{if} i\ne j\\\end{cases}, \\\boldsymbol{V}_{ij}\left( t \right) &=\frac{\sum_{k=0}^{s-\max \left\{ i,j \right\}}{\left( -1 \right) ^k\left( \begin{array}{c} s\\ i+k\\\end{array} \right) \left( \begin{array}{c} 2s-j-k-1\\ s-1\\\end{array} \right)}}{\left( j-1 \right) !\left( -1 \right) ^it^{s+i-j}}\\\\\boldsymbol{W}_{ij}\left( t \right) &=\frac{\sum_{k=0}^{s-\max \left\{ i,j \right\}}{\left( \begin{array}{c} s-k-1\\ i-1\\\end{array} \right) \left( \begin{array}{c} 2s-j-k-1\\ s-1\\\end{array} \right)}}{\left( j-1 \right) !\left( -1 \right) ^{i+j}t^{s+i-j}}\end{aligned} UijVij(t)Wij(t)={(i1)!1ifi=j0ifi=j,=(j1)!(1)its+ijk=0smax{i,j}(1)k(si+k)(2sjk1s1)=(j1)!(1)i+jts+ijk=0smax{i,j}(sk1i1)(2sjk1s1)

对平坦变量的各个维度应用上述公式即可求解BVP最优轨迹

2 算法仿真

2.1 ROS C++仿真

参考轨迹优化 | 基于边界中间值问题(BIVP)的路径平滑求解器(附C++/Python仿真)特化一个用于路径平滑的BIVP求解器

struct WaypointProblem
{
  static constexpr size_t problem_dim = 2;         // x, y
  static constexpr size_t boundary_order = 2;      // position, velocity, accleration
  static constexpr size_t intermediate_order = 0;  // position
};

template <>
struct rmp::common::math::ProblemTraits<WaypointProblem>
{
  static constexpr size_t problem_dim = WaypointProblem::problem_dim;
  static constexpr size_t boundary_order = WaypointProblem::boundary_order;
  static constexpr size_t intermediate_order = WaypointProblem::intermediate_order;
};

using Solver = rmp::common::math::BIVPSolver<WaypointProblem>;

接着根据路径点约束设置求解器参数并求解即可

bool BIVPOptimizer::optimize(const Points3d& waypoints)
{
  solver_->reset();
  setBoundaryConstraints(waypoints.front(), waypoints.back());
  setIntermediateConstraints(waypoints);
  setTimeAllocation(waypoints);
  solution_ = std::move(solver_->solve());
  return true;
}

请添加图片描述

2.2 Python仿真

核心代码如下所示:

def optimize(self, waypoints: List[Point3d]) -> None:
	solver_params = SolverParameters(
	    problem_dim=2,  # x, y
	    boundary_constraint_order=2,  # position, velocity, accleration
	    intermediate_constraint_order=0,  # position
	)
	self.solver = BIVPSolver(solver_params)
	
	# boundary
	start_boundary = [
	    SecondOrderBVPState(x=waypoints[0].x(), dx=0.0, ddx=0.0),  # x
	    SecondOrderBVPState(x=waypoints[0].y(), dx=0.0, ddx=0.0),  # y
	]
	goal_boundary = [
	    SecondOrderBVPState(x=waypoints[-1].x(), dx=0.0, ddx=0.0),  # x
	    SecondOrderBVPState(x=waypoints[-1].y(), dx=0.0, ddx=0.0),  # y
	]
	self.solver.setBoundaryConstraints(start_boundary, goal_boundary)
	
	# intermediate
	intermediate_constraints = []
	for i in range(1, len(waypoints) - 1):
	    constraints = [ZeroOrderBVPState(x=waypoints[i].x()), ZeroOrderBVPState(x=waypoints[i].y())]  # position
	    intermediate_constraints.append(constraints)
	self.solver.setIntermediateConstraints(intermediate_constraints)
	
	# time allocation
	time_allocation = [self.duration_per_segment] * (len(waypoints) - 1)
	self.solver.setTimeAllocation(time_allocation)
	
	# solve
	self.solution = self.solver.solve()

在这里插入图片描述

完整工程代码请联系下方博主名片获取


🔥 更多精彩专栏


👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

网站公告

今日签到

点亮在社区的每一天
去签到