由于Chrono的官方教程在一些細節方面解釋的并不清楚,自己做了一些嘗試,做學習總結。
今天突發奇想,想試一下,是否可以實現兩個vehicle的碰撞?
1、兩輛vehicle的仿真
官方提供了demo_VEH_TwoCars
這個demo,用來參考兩個車的例子。
對于一個車而言,我們不需要專門制定Chrono的系統是什么,即只需要用Vehicle在創建時自動生成的system即可。
通過vehicle的底層代碼,可以看到構造函數有兩種,一種是不指定system,另一種是指定system的:
之前的例子,用的都是第一種初始化,這樣在實際使用時,如果涉及到地形模塊的交互,只需要在創建地形時,傳入vehicle綁定的系統即可,例如:
HMMWV_Full hmmwv;
RigidTerrain terrain(hmmwv.GetSystem());
但是,如果有兩個vehicle,再創建一個新的vehicle就會出現麻煩:他兩個處于不同的物理系統。
于是,我們參考官方的例子,首先創建一個物理系統,然后在創建vehicle時指定同一個system即可:
// 創建物理仿真系統,并指定一些參數。
ChSystemNSC sys;
sys.SetCollisionSystemType(ChCollisionSystem::Type::BULLET);
sys.Set_G_acc(ChVector<>(0, 0, -9.81));
sys.SetSolverType(ChSolver::Type::BARZILAIBORWEIN);
sys.SetSolverMaxIterations(150);
sys.SetMaxPenetrationRecoverySpeed(4.0);// 創建第1個vehicle
HMMWV_Reduced hmmwv_1(&sys);// 創建第2個vehicle
HMMWV_Reduced hmmwv_2(&sys);
接下來,在仿真循環中,我們需要對系統進行動力學仿真。調用:sys.DoStepDynamics(step)
。
hmmwv_1.Advance(step_size);
hmmwv_2.Advance(step_size);
terrain.Advance(step_size);
vis->Advance(step_size);
// Advance state of entire system (containing both vehicles)
sys.DoStepDynamics(step_size);
之前采用vehicle的方式寫代碼時,不需要寫出來這一句DoStepDynamics,因為在vehicle的Advance()
中,最終調用了vehicle自己system的DoStepDynamics
。如果這里我們忽略了最后這一句話,vehicle在仿真系統中是不會動的、但driver的控制量是已經給上了(這個bug卡了我半天,才想到去找demo,最后發現的問題)。
2、兩車的碰撞
2.1 車輛可碰撞的地方
我們知道,chrono里面,有這個東西、可以看到可視化、以及會發生碰撞,這幾件事情是沒有關系的。
那首先就要搞清楚,對于一個vehicle來說,哪些地方可以“碰撞”。
從官方介紹中,可以得知,任何vehicle都包括底盤,輪式車輛又包括:懸掛、轉向、傳動、輪胎模型。
經過測試,輪胎、底盤是可以發生碰撞的,實際碰撞的位置如下圖所示:
除了4個車輪、底盤圈出來的這部分,其他地方貌似是無法發生物理碰撞的。
2.2 碰撞設置
要想發生碰撞,需要對碰撞進行設置,包括:
- 設置system的碰撞
- 設置車輛的碰撞方法
- 設置車輛具體哪個地方可以碰撞
其中,system和車輛的碰撞設置,例如采用Bullet碰撞
// system碰撞設置
auto collision_type = ChCollisionSystem::Type::BULLET;
sys.SetCollisionSystemType(collision_type);// 車輛碰撞設置
car1.SetCollisionSystemType(collision_type);
但是,仍需要設置,車輛哪些地方的碰撞需要啟用?即需要使能。
翻閱官方文檔,共有三個函數相關,分別是:
SetChassisCollide
: Enable/disable collision for the chassis subsystem. This function controls contact of the chassis with all other collision shapes in the simulation.SetChassisVehicleCollide
: Enable/disable collision between the chassis and all other vehicle subsystems. Note that some of these collisions may be always disabled, as set by the particular derived vehicle class.SetWheelCollide
: Enable/disable collision for the wheel subsystems.
注意,前兩個是vehicle模塊都具備的函數,第三個是wheel類型的vehicle所特有的。
第一種和第二種的區別:第一個是底盤和所有物體的碰撞;第二個是底盤和vehicle本身發生碰撞。
官方建議,當chassis或wheel一個設置為true時,另一個設置為false,避免出現bug。
2.3 結果
輪胎的碰撞:
可以看到,當兩個車的輪胎碰上時,會發生碰撞,但車體之間可以相互“穿越”。
底盤碰撞:
可以看到,底盤碰撞時,輪胎可以重合,但是在底盤部分會發生碰撞,改變車的結構。
3、思考:車外殼碰撞
以上方法,只能夠實現部分體積的碰撞,但車體的“外殼”無法碰撞。
自己嘗試了一下,發現實現起來比較困難,原因如下:
雖然車體外殼的mesh是屬于chassis控制,但chassis的體積只有上述部分,外殼部分是沒有碰撞體積的;外殼碰撞時,并不會有外部的力影響車輛系統,因此,即使定義一個“無可視化”的ChBody與車體坐標系綁定,當ChBody間發生碰撞時,碰撞的力不知道怎么傳遞到車輛底盤,進而改變車體的各個子系統,即“碰撞”或許能看出來,但后續車輛的運動,不符合“車輛模型+控制量+碰撞”共同造成的影響。
希望有高手提供思路。