Rust for Robotics

# はじめに

Rustコミュニティーのみなさんこんにちは。

私はRobotの専門家であるRoboticistの @OTL です。この記事ではみなさんにRust x Roboticsの世界の一端を感じていただければと思います。

# Rust is for Robotics

## 言語としてのRustとRoboticsの相性

Rustを知ったのはおおよそ半年前という新参なのですが、RustはRoboticsに向いた言語であると思っています。
詳しくは↓に書きました。

http://ros-robot.blogspot.jp/2017/05/rust.html

要約すると

* Roboticsでは実行時間=性能であるため、**性能重視** される。そのためC++が基本的に使わている。（性能いらないところはPythonなどが使われている）
* ロボットはテストを書くのがしんどい（実際にロボットを動かすか、重いシミュレータを起動するか）ので、**なるべくテスト書きたくない**。Rustはコンパイル大変だからテストはゆるくても良さそうに感じる
* C++の重いTry-catchか返り値での**エラーハンドリング**に比べてRustのそれはエレガント。ロボットの世界では失敗というのは物理的に不可能な場合など本質的によく発生し、そのハンドリングはロボットの安全性確保にとって致命的だったりする（止まったら困ったりする）。
* ロボットでは複数のセンサや処理が同時に走るので**並列性**重要なのでRustと相性良さそう。ただ、Rustの並列性はあまり複数スレッドがずっと走るというイメージではない気がする。
* GCがないということは、実時間制御(**1msec周期で絶対に動く**ことを保証する必要があったりする）で使える可能性がある。Roboticsは低レベルから高レベルまで様々なドメインのプログラムを必要とするが、低レベルな制御にも使えそうだし、同時に抽象度も高いので、Roboticsのあらゆる分野で統一的に使えそう。現状のように、低レイヤーはC++で上位はPythonなどわけなくて良さそう。

## RustとRoboticsの現状

言語としては理想的かと思ったのですが、やはり実務で使うにはライブラリやエコシステムが重要です。

他の分野でもそうだと思いますが、Rustは圧倒的に必要なライブラリが足りません。とはいえ、ロボットの世界でコードがオープンになりだしたのはここ数年での出来事なので絶対的に遅れているというわけではないと思います。数年本気出せば追いつけるかも？

例えば、C++には以下のような重要なライブラリがあります。

* [PCL](http://pointclouds.org): Kinectなどで取得する点群処理ライブラリ
*  [OpenCV](https://opencv.org): 画像処理ライブラリ
* [MoveIt](http://moveit.ros.org/): モーションプランニングフレームワーク

ロボットのライブラリは基本的にC++なので、bindgenの改善によってはこれらと連携しながらRustでロボットプログラミングが出来るようになるかもしれません。

# 作ったもの

というわけで少しはエコシステムに貢献しようということで、まだRust初心者ですが、いくつか作ってみました。

## 自作のモーションプランニングライブラリ： `gear`

### 概要

先程挙げたMoveItの置き換えを目指してモーションプランニングのライブラリを作りました。（MoveItは大きなフレームワークなので当然現状では置き換えられるレベルではありません）

https://github.com/OTL/gear

ロボットの手を指定した位置に動かす、という人間にとっては簡単だけど、ロボットにとっては古典的な問題であるこの問題を解くライブラリです。

Rustはサビるものをライブラリにつけるようなので、その中でもロボットに関係ありそうな、`gear` という名前にしました。(`gears`というプロジェクトがあるので、`rivet`とか`bolt`とか考えたのですが、全部名前だけ取られていたので、紛らわしいの覚悟して`gear`にしました）

動作する様子は↓のような感じ。手を指定した場所に伸ばしたり、障害物を避けながら手を指定した場所に持っていったり出来ます。手をちょっと動かすだけでも結構大変なんです。

[![Video](https://j.gifs.com/kZZyJK.gif)](http://www.youtube.com/watch?v=jEu3EfpVAI8)
[![Sawyer movie](https://j.gifs.com/ZVVqDw.gif)](https://www.youtube.com/watch?v=0YujRKUto-4)

まだまだ完成度は低いですが、一応最低限の機能を持ったロボティクスのフレームワークとして使えるものではあると思います。

### コードサンプル

可視化を除けば大体以下のようなコードで先程の動作が出来ます。

```rust
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](https://github.com/OTL/k): Kinematics Library (１文字crateを取って見ました）
* [urdf-rs](https://github.com/OTL/urdf-rs): URDFというロボットモデルの記述形式のパーサー ([serde](https://serde.rs/)を利用)
* [urdf-viz](https://github.com/OTL/urdf-viz): ロボット用 3D Visualizer
* [rrt](https://github.com/OTL/rrt): Robotでは定番の高次元でのPath Planningアルゴリズム

当たり前ですがRoboticsに関係ない人には有用でないライブラリばかりです。(rrtは使いようがあると思います）
他にも色々必要なライブラリがあったのですが、すでにRoboticsとの親和性の高いライブラリがいくつもあったので、簡単につくれました。

## robotics.rs

RustのRobotics関連情報を集めて整理しようと思って、サイトを作りました。`gear`を始め、上記ライブラリを作るのに使ったライブラリと、水増しするために私のライブラリを載せてあります。

http://robotics.rs

ドメイン取得のためのレジストラは日本のものは高いので、
https://www.istanco.com/
を使いました。安くていいです。

いいRustのRoboticsライブラリをご存知でしたらPRで教えてください。

## ROSについて

Robotics分野ではROS (Robot Operating System) というオープンソースのミドルウェアがデファクトスタンダードとして使われています。これのRustクライアントもすでに有りました。

[rosrust](https://github.com/adnanademovic/rosrust)

ROSについては、英語分かる方は[公式Wiki](http://wiki.ros.org/)を読めば十分です。

ROSがあれば、ネットワークを通じて多言語との連携が簡単にできるので、Rustで書いたライブラリが既存のライブラリと連携出来ます。Rustでロボットプログラミングも怖くないです。

# まとめ

Roboticistから見てRustは魅力的です。今後Robotics分野で使われる言語になったらいいと思っていますし、そのために必死に貢献してみました。

ただ、Roboticistが貴重な存在であり、Rustプログラマもまだまだ人口少なさそうなので、その両方を兼ね揃えるというと本当に数が限られる（世界に数人かと）ので、そこをなんとか突破して幸せな世界を作りたいと思っています。