概要
ロボットシミュレータのWebotsで,みんな大好きTrack(履帯,いわゆるキャタピラ)を使うロボットを作ろうとしたところ,
参考文献がほぼ英語の公式ドキュメントしかなく,わからん過ぎて苦労しました.ので,備忘録を兼ねて記事にまとめます.
※公式ドキュメント等
Track - Webots Reference Manual
TrackWheel - Webots Reference Manual
track.wbt - cyberbotics/webots github
この記事では,以下のような簡単な仕様のTrack付きロボットを作ることをゴールとします.
- 直方体の本体と,二つのTrack(履帯)からなるロボットを作る
- ロボットの持つTrackは,同じ大きさのTrackWheelを二つと,LinearMotorを持つ
- Geometries Animationを使って履帯の動きを表現する
なお,本記事作成で用いた環境は以下のものです.
- Windows 10
- Webots R2021a
- Controllerの実装: C++
- ノートPC(ThinkPad X13 Gen1, AMD RYZEN Pro 7, 16GB RAM)
作業手順
ワールドの作成
今回は履帯付きのロボットを走らせることが目的なので,ワールドはウィザードを使ってサクッと作ってしまいます.
Webots上部メニューのWizards > New Project Directory... から,ある程度の環境がそろったワールドを手軽に作成できます.
名称以外基本デフォルトで大丈夫ですが,途中チェック項目が並ぶところで Add a rectangle arenaにチェックを入れると最初から床面が生成されてさらに楽です.
プロジェクトを作成すると,図のように床面のある環境が表示されます.

筐体の作成
本体の作成
履帯の動きを見たいので,本体は適当に作ります.
- Webots左側のメニュー(Scene Tree)内の適当な項目をクリックしてScene Treeを選択する.
- 右クリック >
Add new...でBase Nodes>Robotを選択し,ロボットノードを追加. - ちょっと持ち上げていたいので,Robotの
transitionを(0, 0.05, 0)に指定 - 作成したRobotのchildreをダブルクリックし,Shapeを指定して追加
- 当たり判定のboundingObjectをShapeと同じにしたいので,Shapeをクリックして表示される
DEF入力欄に任意の名前を入れ,Shapeに名前を付ける.
(本記事ではDEFを"BOX"に指定します) - ShapeのgeometryをダブルクリックしてBox型を指定する.本記事では大きさを
(0.2, 0.05, 0.1)とした. - (オプショナル)さすがにさみしいので見た目をマシにするために立体表面の描画情報を追加する.
ShapeのappearanceをダブルクリックしてAppearanceを指定 →AppearanceのmaterialをダブルクリックしてMaterialを指定 - Robotの
boundingObjectをダブルクリックしUSE> Shapeにつけた名前(ここではBOX)を指定し,当たり判定を付加する - Robotのphysicsをダブルクリックし,Physicsを指定する
ここまで同じ手順を行うと,下図のように少しだけ宙に浮いたボックスが表示されます.
また,この状態を保存したうえでシミュレーションを実行すると,箱が落下して床の上に落ちる様子が見られます.

履帯の作成
履帯をくっつける本体ができたので,次は履帯を作ります.
Robotのchildrenを右クリックしてAdd newを押し, Base nodes > Track を追加します.
これだけでは何も表示されないので,適切なパーツを追加していきます.
TrackWheelの追加
TrackWheelは履帯の内外に設置され,ベルトを動かしたり形作ったりする車輪です.
実際の履帯ではその役割によって駆動輪や転輪など複数種類があるのですが,Webotsではこれらの区別はなくすべてTrackWheelとして扱われます.
今回は先述のとおり,二つのTrackWheelを一つの履帯の中で使用します.
- Trackのchildrenをダブルクリックし,
BaseNode>TrackWheelを追加します. -
TrackWheelのpositionを(0.1, 0)に(Trackの制約上TrackWheelは二方向にしか位置調整できません),radiusを0.03に指定します. - このままだと
TrackWheelは何も描画されないので,その位置や回転がわかるようにします.
TrackWheelは見た目によらず円柱の車輪系になるため,見た目は回転していることがわかりやすいようboxを指定します.
TankWheelのchildrenにShapeを追加し,geometryを(0.035, 0.035, 0.03)サイズのBoxにしますappearanceも同様にApparance>Materialまで指定します. -
TrackWheelを複製します.コピーし,Trackのchildrenにペーストします. - 二つある
TrackWheelのうちどちらかのTransitionを(-0.1, 0)に指定し,筐体後部に移します.
ここまでできると,下図のようによくわからない状態になっているはずです.

ベルトの追加
Webotsに用意されるGeometry Animationを使えば,配置したTrackWheel間をつなぐように設置され,回転するベルトを簡単に作ることができます.
-
TrackのanimatedGeometryに,ベルトとしてTrackWheelを取り囲む図形を指定します.ここでは,geometryに(0.02, 0.003, 0.03)サイズのboxを,appearanceにdiffuseColorが(0.1, 0.1, 0.1)のMaterialを持つAppearanceを指定します. -
TrackのgeometriesCountには,1.で指定した図形がいくつ用いられるかの数を思惟します.ここでは20に指定します.
ここまで操作すると,下図のようになります.ベルトらしきものが描画され,それっぽくなってきました.
なお,このベルトの立体は見た目だけのものであり,実際の履帯の振る舞い・物理シミュレーション結果には関係ないことにご注意ください.

履帯の当たり判定を設定
地面に動力を伝える,当たり判定の部分を`boundingObjectとして追加し設定します.
履帯の形に合わせる必要はないのですが,今回はCylinder2つとBox1つを使い,履帯と同じ形のboundingObjectを作ります.
-
View>Optional Rendering>Show All Bounding Objectsを押し,boundingObjectsが見えるようにします. - Trackの
boundingObjectに,Groupを指定します. -
Groupのchildrenに,(0.2, 0.06, 0.03)サイズのboxを追加します. -
Groupのchildrenに,Transformを追加し,transitionを(0.1, 0, 0)に,rotationを(1, 0, 0, -1.5708)にします. -
Transformのchildrenに,heightが0.03,radiusが0.03のCylinderを追加します. -
Transformを複製して,transitionを(-0.1, 0, 0)にします.なお複製の際にCylinderが消えてしまうので,これもコピペなどで追加します -
TrackのphysicsにPhysicsを指定します.
1.Trackを複製します.片方のtransitionを(0, 0, -0.05)に,もう片方を(0, 0, 0.05)にし,車体の両側に設置してやります.
ここまでやると,下図のようになるはずです.また保存してからシミュレーションを実行すると,履帯で接地する様子が見られます.
もう完成は目前です.

挙動の設定
モータの回転を設定
あとは履帯が回転するようにしてやればおkです.
本当はもう1ステップありますが,とりあえずこれをやってやると本体が動くようになります.
- モータを追加します.
TrackのdeviceにLinearMotorを指定し,nameに適当な名前を入れます.
これをもう片方の履帯にもやってやります.なお,nameはController作成時に使うので左右のモータで違う名前になる様にしてやってください.
本記事では,leftMotorおよびrightMotorとしました. - コントローラを作成します.
Wizards>New Robot Controller...から,お好みの言語と名前を指定します.
本記事ではC++を用い,trackController.cppという名前のファイルを作成します.
作成したコントローラは,Robotのcontrollerで指定して本体と紐づけてやります. - コントローラを実装します.大体以下のようにしてやるとよいです.
//L10
# include <webots/Robot.hpp>
# include <webots/Motor.hpp> //追加
//L25付近
Robot *robot = new Robot();
//以下を追加
Motor *leftMotor, *rightMotor;
leftMotor = robot->getMotor("leftMotor");
rightMotor = robot->getMotor("rightMotor");
leftMotor->setPosition(INFINITY);
rightMotor->setPosition(INFINITY);
leftMotor->setVelocity(0.1);
rightMotor->setVelocity(0.1);
//以上を追加
あとはワールドを保存して,ビルド,実行します.
(Webotsの動画書き出し機能で出力したので,実際よりだいぶなめらかな映像になってます)

いいですね,僕は履帯が好きなのでめっちゃテンション上がります
摩擦の設定
一見ここまでで完成したように思えますが,この段階では履帯の摩擦の設定ができておらず,両モータの出力値の値が同じ場合のみ正しく動くようになっています.
試しに,片方のモータ値にマイナスをつけ,その場で旋回(超信地旋回)させようとするとうまく動かないことがわかると思います.
ですので,正しく旋回ができるよう,最後に履帯ー地面間の摩擦を設定してやります.
webotsでは,摩擦の設定は
- 摩擦の設定をしたい物体に素材名をつける
-
WorldInfoから素材名を二つ指定し,その素材名を持つ物体間の摩擦係数を設定する
という手順で行います.ですので,ここで行う作業は以下のようになります.
-
TrackのcontactMaterialに適当な素材名を指定します.ここでは"trackMaterial"とします.これを両方の履帯について行います. -
WorldInfoのcontactPropertiesに,ContactPropertiesを追加します. - 追加した
ContactPropertiesの`material2に先ほど指定した素材名(ここでは"trackMaterial")を指定します. -
ContactPropertiesのcoulombFrictionを500に,forceDependentSlipを1に指定します.
ここまで完了したら,左右モータに正負逆の値を入れてやると超信地旋回をするようになります.

お疲れさまでした!
おわりに
車輪とかと同様にサクッとつけられるかなと思っていたんですが,結構いろいろやることがあって大変でした.
忘れんうちに記事にまとめられてよかったなという感じがします.
なお,最後に指定したパラメータの値ですが,動いたのでオッケーって感じで正直最適な値をいくらにすればいいのかわかってません.
特にforceDependentSlipに関しては,ほかのworldだと0のまんまでも超信地旋回できたりするので・・・・謎です
できたやつもそもそも履帯の回転量に対して旋回量少ない気がするし・・・・
もう少し調べてみて,わかったら追記などしていこうと思います.
※本記事で作成したコードをgithubに公開しました
https://github.com/ken551/webots_track_test/tree/main