任意弧度修正到[-pi, pi]

一、代碼示例

    def fix_range(x):
        if x == 0:
            return x
        x %= 2*np.pi*x/abs(x) 
        x -= 2*np.pi*x/abs(x) if abs(x)>np.pi else 0
        return x

二、推理過程:

我這里將轉換過程分為了兩步:

  1. 先轉到[-2pi, 2pi]

如果原弧度是正,則轉到[0,2*pi]:

if x>=0:
    x = x%(2*np.pi)

如果是負,轉到[0,-2*pi]:

if x<0:
    x = x%(-2*np.pi)

當x!=0, 則可以用*x/abs(x)表示x的正負。
合并后可去掉條件判斷:x %= 2*np.pi*x/abs(x)

  1. 再從[-2pi, 2pi] 到 [-pi, pi]
    如果x>pi,那么它應該被修正到x-2pi;
    如果x<-pi,應該修正到x+2pi。
    依然是用*x/abs(x)影響式子的正負, 且用 x的絕對值跟pi比較來合并上述兩個條件。
    合并后得到:x -= 2*np.pi*x/abs(x) if abs(x)>np.pi else 0

三、問題擴展

3.1 引入

上述問題其實是一個簡單問題。
我最初的想法其實是對任意兩個yaw角插值:
用線性插值就是:

  1. 求兩個yaw的差值delta_yaw, 和兩個yaw的時間差delta_t;
  2. yaw_rate = delta_yaw/delta_t;
  3. result = yaw1 + yaw_rate*(result_time-t1)

在駕駛場景,目標的yaw角取值范圍是[-pi, pi], 作為一個圓, -pi和pi其實一樣的,而且在此處取值連續(xù);但是在數(shù)值上,-pi和pi差了2pi。
這會造成一個問題:對于面對我們的目標,它的yaw角接近pi,如果前后的yaw角一個是接近pi的正數(shù),一個是接近-pi的負數(shù),我們期望的線性插值結果應該也是pi附近,但是如果直接用上述方法插值,會得到一個接近0的結果,相當于目標調了個頭。

3.2 一個可行解法

一個想法是先轉成四元數(shù),然后求delta_yaw:

rot_1 = Quaternion(axis=(0.0, 0.0, 1.0), radians=yaw_1).rotation_matrix
rot_2 = Quaternion(axis=(0.0, 0.0, 1.0), radians=yaw_2).rotation_matrix
delta_rot = rot_2 @ np.linalg.inv(rot_1)
yaw, _, _ = Quaternion(matrix=delta_rot).yaw_pitch_roll

但這樣做總覺得舍近求遠。

3.3 簡單解法

于是分情況討論:

  1. 出現(xiàn)上述情況其實主要是面對我們的目標,它們的yaw角以pi為中心左右擺動;
  2. 這種情況下,delta_yaw的絕對值接近2pi,假設把條件再放寬,可得到 abs(delta_yaw)>pi。

例如,yaw_1 = 170° , yaw_2 = -175° (用角度表示利于理解)。
delta_yaw = yaw_2 - yaw_1 = 345°, 但實際它應該是 15° (逆時針為正)。
其實就是: 360-abs(yaw_2-yaw_1)。
考慮反過來的情況,yaw_1 = -170° , yaw_2 = 175°, 差值應該是-15°。
其實就是:abs(yaw_2-yaw_1)-360.
以上,我們可以用代碼表示為:

    delta_yaw = yaw_2 - yaw_1
    if abs(delta_yaw)>np.pi:
        delta_yaw = (abs(delta_yaw)-2*np.pi)*(delta_yaw/abs(delta_yaw))

式子右邊整理得到:

delta_yaw  = delta_yaw-2*np.pi*delta_yaw/abs(delta_yaw)
即:
if abs(delta_yaw)>np.pi:
    delta_yaw -= 2*np.pi*delta_yaw/abs(delta_yaw)

該表達式即上述的fix_range函數(shù)第二步的表達式。而delta_yaw本來就滿足第一步處理過后的條件。
也就是說,兩個yaw角的差值,也可以用上述fix_range函數(shù)修正為我們期望的值。
最后,經(jīng)過實驗,我發(fā)現(xiàn)兩個yaw角即使不滿足在[-pi, pi]取值,任意取值,他們的差值也能通過上述函數(shù)得到期望差值。

3.4 結論

對任意兩個yaw角插值問題,首先在第一步求delta_yaw時調用fix_range函數(shù),最終在正常差值得到y(tǒng)aw角之后,再調用一次fix_range函數(shù)對結果進行取值范圍修正即可。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容