はじめに
Rustコミュニティーのみなさんこんにちは。
私はRobotの専門家であるRoboticistの @OTL です。この記事ではみなさんにRust x Roboticsの世界の一端を感じていただければと思います。
Rust is for Robotics
言語としてのRustとRoboticsの相性
Rustを知ったのはおおよそ半年前という新参なのですが、RustはRoboticsに向いた言語であると思っています。
詳しくは↓に書きました。
要約すると
- Roboticsでは実行時間=性能であるため、性能重視 される。そのためC++が基本的に使わている。(性能いらないところはPythonなどが使われている)
- ロボットはテストを書くのがしんどい(実際にロボットを動かすか、重いシミュレータを起動するか)ので、なるべくテスト書きたくない。Rustはコンパイル大変だからテストはゆるくても良さそうに感じる
- C++の重いTry-catchか返り値でのエラーハンドリングに比べてRustのそれはエレガント。ロボットの世界では失敗というのは物理的に不可能な場合など本質的によく発生し、そのハンドリングはロボットの安全性確保にとって致命的だったりする(止まったら困ったりする)。
- ロボットでは複数のセンサや処理が同時に走るので並列性重要なのでRustと相性良さそう。ただ、Rustの並列性はあまり複数スレッドがずっと走るというイメージではない気がする。
- GCがないということは、実時間制御(1msec周期で絶対に動くことを保証する必要があったりする)で使える可能性がある。Roboticsは低レベルから高レベルまで様々なドメインのプログラムを必要とするが、低レベルな制御にも使えそうだし、同時に抽象度も高いので、Roboticsのあらゆる分野で統一的に使えそう。現状のように、低レイヤーはC++で上位はPythonなどわけなくて良さそう。
RustとRoboticsの現状
言語としては理想的かと思ったのですが、やはり実務で使うにはライブラリやエコシステムが重要です。
他の分野でもそうだと思いますが、Rustは圧倒的に必要なライブラリが足りません。とはいえ、ロボットの世界でコードがオープンになりだしたのはここ数年での出来事なので絶対的に遅れているというわけではないと思います。数年本気出せば追いつけるかも?
例えば、C++には以下のような重要なライブラリがあります。
ロボットのライブラリは基本的にC++なので、bindgenの改善によってはこれらと連携しながらRustでロボットプログラミングが出来るようになるかもしれません。
作ったもの
というわけで少しはエコシステムに貢献しようということで、まだRust初心者ですが、いくつか作ってみました。
自作のモーションプランニングライブラリ: gear
概要
先程挙げたMoveItの置き換えを目指してモーションプランニングのライブラリを作りました。(MoveItは大きなフレームワークなので当然現状では置き換えられるレベルではありません)
ロボットの手を指定した位置に動かす、という人間にとっては簡単だけど、ロボットにとっては古典的な問題であるこの問題を解くライブラリです。
Rustはサビるものをライブラリにつけるようなので、その中でもロボットに関係ありそうな、gear
という名前にしました。(gears
というプロジェクトがあるので、rivet
とかbolt
とか考えたのですが、全部名前だけ取られていたので、紛らわしいの覚悟してgear
にしました)
動作する様子は↓のような感じ。手を指定した場所に伸ばしたり、障害物を避けながら手を指定した場所に持っていったり出来ます。手をちょっと動かすだけでも結構大変なんです。
まだまだ完成度は低いですが、一応最低限の機能を持ったロボティクスのフレームワークとして使えるものではあると思います。
コードサンプル
可視化を除けば大体以下のようなコードで先程の動作が出来ます。
extern crate gear;
extern crate nalgebra as na;
fn main() {
// Create path planner with loading urdf file and set end link name
let planner = gear::JointPathPlannerBuilder::try_from_urdf_file("sample.urdf", "l_wrist2")
.expect("failed to create planner from urdf file")
.collision_check_margin(0.01)
.finalize();
// Create inverse kinematics solver
let solver = gear::JacobianIKSolverBuilder::<f64>::new()
.num_max_try(1000)
.allowable_target_distance(0.01)
.move_epsilon(0.0001)
.finalize();
let solver = gear::RandomInitializeIKSolver::new(solver, 100);
// Create path planner with IK solver
let mut planner = gear::JointPathPlannerWithIK::new(planner, solver);
// Create obstacles
let obstacles =
gear::create_compound_from_urdf("obstacles.urdf").expect("obstacle file not found");
// Set IK target transformation
let mut ik_target_pose = na::Isometry3::from_parts(
na::Translation3::new(0.40, 0.20, 0.3),
na::UnitQuaternion::from_euler_angles(0.0, -0.1, 0.0),
);
// Plan the path, path is the vector of joint angles for root to "l_wrist2"
let plan1 = planner.plan_with_ik(&ik_target_pose, &obstacles).unwrap();
println!("plan1 = {:?}", plan1);
ik_target_pose.translation.vector[2] += 0.50;
// plan the path from previous result
let plan2 = planner.plan_with_ik(&ik_target_pose, &obstacles).unwrap();
println!("plan2 = {:?}", plan2);
}
gear
を作るために作ったもの
Rustは細かくライブラリ(crate)を分けるので、gear
のために必要なライブラリ群もcrateとしてreleaseしています。
こっちのほうが多くの人に有用でしょう。
- k: Kinematics Library (1文字crateを取って見ました)
- urdf-rs: URDFというロボットモデルの記述形式のパーサー (serdeを利用)
- urdf-viz: ロボット用 3D Visualizer
- rrt: Robotでは定番の高次元でのPath Planningアルゴリズム
当たり前ですがRoboticsに関係ない人には有用でないライブラリばかりです。(rrtは使いようがあると思います)
他にも色々必要なライブラリがあったのですが、すでにRoboticsとの親和性の高いライブラリがいくつもあったので、簡単につくれました。
robotics.rs
RustのRobotics関連情報を集めて整理しようと思って、サイトを作りました。gear
を始め、上記ライブラリを作るのに使ったライブラリと、水増しするために私のライブラリを載せてあります。
ドメイン取得のためのレジストラは日本のものは高いので、
https://www.istanco.com/
を使いました。安くていいです。
いいRustのRoboticsライブラリをご存知でしたらPRで教えてください。
ROSについて
Robotics分野ではROS (Robot Operating System) というオープンソースのミドルウェアがデファクトスタンダードとして使われています。これのRustクライアントもすでに有りました。
ROSについては、英語分かる方は公式Wikiを読めば十分です。
ROSがあれば、ネットワークを通じて多言語との連携が簡単にできるので、Rustで書いたライブラリが既存のライブラリと連携出来ます。Rustでロボットプログラミングも怖くないです。
まとめ
Roboticistから見てRustは魅力的です。今後Robotics分野で使われる言語になったらいいと思っていますし、そのために必死に貢献してみました。
ただ、Roboticistが貴重な存在であり、Rustプログラマもまだまだ人口少なさそうなので、その両方を兼ね揃えるというと本当に数が限られる(世界に数人かと)ので、そこをなんとか突破して幸せな世界を作りたいと思っています。