本篇將講解MiniCheetah中所使用的的足端軌跡方程-貝塞爾曲線方程。
貝塞爾曲線就是這樣的一條曲線,它是依據四個位置任意的點坐標繪製出的一條光滑曲線。
在歷史上,研究貝塞爾曲線的人最初是按照已知曲線參數方程來確定四個點的思路設計出這種矢量曲線繪製法。貝塞爾曲線的有趣之處更在於它的「皮筋效應」,也就是說,隨著點有規律地移動,曲線將產生皮筋伸引一樣的變換,帶來視覺上的衝擊。1962年,法國數學家Pierre Bézier第一個研究了這種矢量繪製曲線的方法,並給出了詳細的計算公式,因此按照這樣的公式繪製出來的曲線就用他的姓氏來命名是為貝塞爾曲線。
給定點P0、P1,線性貝茲曲線只是一條兩點之間的直線。這條線由下式給出:
取。可以從圖中看出,其效果等同於線性插值。
對於給定點P0=[0, 0]、P1=[0.5, 0.5]、P2=[1, 0],曲線的函數如下:
P0、P1、P2、P3四個點在平面或在三維空間中定義了三次方貝茲曲線。曲線起始於P0走向P1,並從P2的方向來到P3。一般不會經過P1或P2;這兩個點只是在那裡提供方向信息。P0和P1之間的間距,決定了曲線在轉而趨進P3之前,走向P2方向的「長度有多長」。函數形式如下:
這裡我們先著眼於位置,把源碼中的速度項,加速項去掉,對其進行分析。
軌跡生成函數調用:
template <typename T>void FootSwingTrajectory<T>::computeSwingTrajectoryBezier(T phase, T swingTime) { _p = Interpolate::cubicBezier<Vec3<T>>(_p0, _pf, phase); T zp, zv, za; if(phase < T(0.5)) { zp = Interpolate::cubicBezier<T>(_p0[2], _p0[2] + _height, phase * 2); } else { zp = Interpolate::cubicBezier<T>(_p0[2] + _height, _pf[2], phase * 2 - 1); } _p[2] = zp;}template <typename y_t, typename x_t>y_t cubicBezier(y_t y0, y_t yf, x_t x) { static_assert(std::is_floating_point<x_t>::value,"must use floating point value"); assert(x >= 0 && x <= 1); y_t yDiff = yf - y0; x_t bezier = x * x * x + x_t(3) * (x * x * (x_t(1) - x)); return y0 + bezier * yDiff;}1.2.1位置
規定以下符號
– 任意起始點
– 結束點
– 抬腿高度h。
將方法實現中的代碼轉換成數學表達式如下:
需要注意的是,該計算可針對一維變量(例如對Z軸坐標單獨計算),也可以是三維向量之間的運算(例如坐標點),對於三維點計算,其展開形式如下(實際上與上式無異):
下面結合圖像更加直觀地對其進行分析。先分析式1的圖像,在 t ∈ [0, 1] 的情況下,分別取兩組數據進行繪圖比較:
p0,pf的值互換:
可以看到如下圖像:
因此可以得出結論,源碼中,該部分定義了,擺動相上行與下行的軌跡:
if(phase < T(0.5)) { zp = Interpolate::cubicBezier<T>(_p0[2], _p0[2] + _height, phase * 2); } else { zp = Interpolate::cubicBezier<T>(_p0[2] + _height, _pf[2], phase * 2 - 1); }下面來看整體軌跡,設定以下數據:
– 起始點p0=[0, 0, 0.2]
– 結束點pf=[1.5, 1.5, 0]
– 抬腿高度h=0.5空間軌跡如下:
1.2.2速度
接下來看該軌跡的速度,對時間進行微分,得到:
1.2.3加速度
對1.2.2得到的速度公式微分,得到:
以上對MiniCheetah中所使用的的足端軌跡方程進行了位置,速度,加速度的分析,儘管該軌跡方程形式上非常簡潔易用,但是仍存在一定缺點,例如對地面衝擊較大,容易造成電機損壞以及姿態穩定上的問題,因此還有一定的提升空間,有興趣的小夥伴可以參考上一篇文章,將擺線運動軌跡融入到cheetah四足機器人的足端軌跡當中去,這裡暫時不展開細說。