參考資料
https://gamma.cs.unc.edu/ORCA/publications/ORCA.pdf
https://gamma.cs.unc.edu/RVO2/
數學知識
1.向量的點乘 dotProduct,計算方法:1. 2.,
作用:點積如果為負,則a,b形成的角為鈍角;如果為零,那麼a,b垂直;如果為正,那麼a,b形成的角為銳角
2.向量a,向量b,det(a,b)表示行列式的值,計算方法x1y2 - x2y1,同時也是叉乘的值
作用:1.以兩個向量為鄰邊的平行四邊形的有向面積,2.小於0表示b在a的順時針方向,大於0表示b在a逆時針方向,等於0表示a,b平行
下圖是碰撞需要修正,並且保證最短修正的兩種情況,
1) 將速度修正到切線上
2) 將速度修正到圓
1,
final double dotProduct1 = w.dotProduct(relativePosition);
dotProduct1 < 0.0 && dotProduct1 * dotProduct1 > combinedRadiusSq * wLengthSq
這個程式碼是為了判斷當前是哪種情況,
向量w = 相對速度 - 相對位置
dotProduct1小於0,表示向量w與相對位置的夾角為鈍角,即AE與AO的角為銳角(需要先判斷這個,只有銳角範圍內cos單調遞減)
dotProduct1 * dotProduct1 > combinedRadiusSq * wLengthSq,角OAE小於角OAD
推導:
cos在0-90單調遞減
角OAE < 角OAD
=> cosOAE > cosOAD
=> OA*cosOAE > OA*cosOAD (同時乘以OA)
=> OA*cosOAE > AD (OA*cosOAD = AD)
=> OA * AE * cosOAE > AE * AD (同時乘以AE)
=> dotProduct1 * dotProduct1 > combinedRadiusSq * wLengthSq
2
direction = new Vector2D(relativePosition.getX() * leg - relativePosition.getY() * combinedRadius, relativePosition.getX() * combinedRadius + relativePosition.getY() * leg)
這段程式碼為了計算第一情況,修正速度的落點,
leg為OD的長度,假設direction為line的方向,即向量OD的單位向量DIR(a, b)順時針的單位向量DIE (b, -a),A的座標(x, y)
向量OA 點乘 向量DIR = 向量OA的長度 * 1 * cosAOD
=> x*a + y*b = leg
向量OA 點乘 向量DIE = 向量OA的長度 * 1 * cosOAD
=>x*b - y*a = combinedRadius
結合這兩個式子就可以解a,b,
RVOMath.det(relativePosition, w) > 0.0
這個在判斷修正方向是在相對位置的左邊還是右邊
3
速度的可選區域為line方向的左側, linearProgram2 找到可行域的交集,即line的交集
3.1
RVOMath.det(lines.get(lineNo).direction, lines.get(lineNo).point.subtract(newVelocity)) > 0.0
大於0說明newVelocity在line的右側,不在line的可行域內,需要重新計算速度
3.2
如圖,綠色為line i, 黑色為line no
final double denominator = RVOMath.det(lines.get(lineNo).direction, lines.get(i).direction);
final double numerator = RVOMath.det(lines.get(i).direction, lines.get(lineNo).point.subtract(lines.get(i).point));
final double t = numerator / denominator;
denominator為BCED的面積 = 2個DBC的面積 = 2 * 1/2 * BP2 * 高
numerator為PGFP2的面積 = 2個GPP2 的面積 = 2個DBP2的面積 = 2 * 1/2 * BC * 高
t = numerator / denominator = BP2 / BC = BP2
t 為line i 和 line no 的交點 到 line point 的距離
4
linearProgram3
如果找不到line的交集,則執行linearProgram3,從上次失敗的line開始往後遍歷
將line i 之前的line做一個修正,修正的方法是:(1)將point修正到交點,(2)將方向修正到角平分線,靠近i的方向
RVOMath.det(lines.get(i).direction, lines.get(i).point.subtract(newVelocity)) > distance
這段程式碼用來判斷是否需要修正速度,如果修正後的速度與當前line的距離大於前一個line的距離大,那麼需要修正。
因為修正後速度將在角平分線上,一定距離當前line更近