#はじめに
国際宇宙ステーション(ISS)の中を自由に飛び回り、宇宙飛行士のお手伝いをする可愛いロボット「astrobee」。
その動きをシミュレーションできるアプリがNASAから提供されています。その使用方法を書きます。
astrobeeそのものの説明については公式の紹介をご覧ください。
What is Astrobee?
https://www.nasa.gov/astrobee
NASA / astrobee
https://github.com/nasa/astrobee
#システム要件
##Ubuntuを用意しよう
INSTALL.mdに書いてある通り、Ubuntu 16.04が必要になります。
クリーンインストールしたMacBookAir(型番よくわかんない)が手に入ったので、そのマシンにUbuntuをインストールすることにしました。
##Ubuntuをインストールしよう
インストール手順は下記の記事を参考にしました。
【Tips】MacBookにUbuntuを入れてデュアルブート環境を構築する方法
インストールするUbuntuはこちらのページからダウンロードしました。
Ubuntu 16.04 LTS 日本語 Remix リリース
なんかバージョンのところにLTSってくっついてるの何だ……?と思いましたが、サポート期間が通常よりも長いバージョンというだけみたいなので、LTSをインストールすることにしました。
Ubuntu LTSとは何か、Server版やMATE版のLTSはあるの?
上記記事では、パーティション分割をするとリカバリモードで起動を試みるとカーネルパニックが発生するようになってしまう……という不具合が報告されていますが、私の環境ではカーネルパニックを起こしませんでした。
スワップパーティションも特に作成しませんでした。
Wi-Fiはインストール時のデフォルト状態で既に繋がってくれたので問題ありませんでした。
rEFIndはインストールしませんでした。当面の間Ubuntuばかり使う予定だったからです。あとから必要になったら入れようと思います。
キーボード識別で少しハマりました。
表示されているキーを入力していって(あるいはそのキーは存在しないと答えていって)結果的にどんな種類のキーボードかUbuntuに識別してもらうという機能が入っていました。
しかしいくらやっても完全に合致するキーボードの種類がなく(主要なキーは印字どおりに入力してくれる)、[
キーを押したら@
が入力されるという形のまま進めることになりました。
Ubuntuのキーボード設定をMac向けにカスタマイズするという内容の記事もネットにたくさんあるみたいなので、この差が気になり始めたらあとからカスタマイズすることにします。
#astrobeeのインストール
公式リポジトリの手順に沿っていけば起動できるのですが、ハマってしまうと永遠にインストールできないためポイントに注意して解説していきます。
なお、本インストール手順はクリーンインストール直後のキレイな環境を想定しています。
既に色々なライブラリが入った環境でインストールしようとしたところ、私の場合は上手くいきませんでした。ご注意ください。
公式のインストール手順はこちらになります。基本的にはこちらを参照しながら進めてください。
Usage instructions for non-NASA users
https://github.com/nasa/astrobee/blob/master/INSTALL.md
まずはコードのビルドに必要なものをインストールします。
sudo apt-get install build-essential git
次に環境変数PATHを設定していきます。
これらはターミナル上で一時的に設定するものなので、ターミナルを開くたびに設定し直す必要があります。
設定ファイルに書き込んでしまう手もあると思うのですが、私は面倒だったのでやりませんでした。
ソースフォルダの名前および、後出するANDROID_PATHはデフォルト名のままで問題ありません。
export SOURCE_PATH=$HOME/freeflyer
リポジトリからコードをクローンしてきます。
git clone https://github.com/nasa/astrobee.git $SOURCE_PATH
私はNASA職員ではないので、インストール手順に従ってANDROID用のPATHとコードも用意しました。
export ANDROID_PATH="${SOURCE_PATH}_android"
git clone https://github.com/nasa/astrobee_android.git $ANDROID_PATH
astrobeeのリポジトリをクローンしたディレクトリに移動しておきます。
pushd $SOURCE_PATH
ここで公式の手順と違うステップを挟みます。
公式の手順だと、この後にadd_ros_repository.sh
というシェルスクリプトを使って依存環境などを整える処理が入ります。
しかし2019年9月現在、このコードの中にバグが含まれており、修正の必要が生じています。
修正は既に他の人がやってくれているので、そのコードを頂きましょう。
こちらのプルリクエストで当該の修正がなされています。
fixed (updated) ROS debian package repo GPG key #11
https://github.com/nasa/astrobee/pull/11
プルリクエストが出されたままマージされることなく放置されていますね。
しかし、マージされていないプルリクエストでも、その変更をローカルに取り込むことは可能です。
詳しくは公式のヘルプをご参照ください。
プルリクエストをローカルでチェックアウトする
https://help.github.com/ja/articles/checking-out-pull-requests-locally
プルリクエストをローカルリポジトリに適用していくのですが、現在チェックアウトしているブランチに変更を適用することはできません。
そのため、別のローカルブランチを作って、そちらにプルリクエストを適用させることにします。
ブランチ名は任意です。
git branch pr-11
これでチェックアウトしていないブランチが作れたため、プルリクエストをpr-11に適用できます。
git fetch origin pull/11/head:pr-11
適用できたらそちらのブランチをチェックアウトしましょう。
git checkout pr-11
プルリクエストを適用したことによってadd_ros_repository.sh
のバグが修正されたため、インストール作業を続けることができます。
ここまでで公式の手順と異なる処理は終わりです
バグを修正したスクリプトを使って依存関係を整えます。
cd scripts/setup
./add_ros_repository.sh
sudo apt-get update
cd debians
./build_install_debians.sh
cd ../
./install_desktop_16_04_packages.sh
依存関係のインストールが終わったので、rosdepコマンドが使えるようになります。
initのあとにupdateコマンドを使うように促されるので、公式の手順通りにupdateコマンドを実行すれば完了です。
sudo rosdep init
rosdep update
最後に元のディレクトリに戻しておきましょう。
popd
公式の手順ではこの後「これらのライブラリが無いという警告が出るかもしれないけど、実行には関係ないので無視しても良いです」という説明が入っています。
しかし、私の環境ではそのような警告は出ませんでした。
続けてコードのビルドを行なっていきましょう。
こちらも公式の手順通りです。
想定されているビルドPATHおよびインストールPATHを用意して進めるとスムーズみたいなので、次の2つのフォルダを作成しておきましょう。
$HOME/freeflyer_build/native
$HOME/freeflyer_install/native
これらは普通にエクスプローラーから新しいフォルダを作成しました。
PATHが用意できたところで、次のように環境変数パスを設定して作業を続けましょう。
export BUILD_PATH=$HOME/freeflyer_build/native
export INSTALL_PATH=$HOME/freeflyer_install/native
configure.sh -h
コマンドでビルドのオプションを確認することができるようですが、私は公式の手順通りで特に問題ありませんでした。
Issueによると[ビルドオプションを変更することで失敗したビルドが通る場合もある]
(https://github.com/nasa/astrobee/issues/2#issuecomment-389316663)みたいです。
もしビルドが失敗した場合は確認してみてください。
ビルドディレクトリ、およびインストールディレクトリを作成している場合は次のコマンドで進めることができます。
pushd $SOURCE_PATH
./scripts/configure.sh -l -F -D
popd
デフォルトで想定されているディレクトリとは違う階層にインストールしたい場合、次のコマンドでインストール先を指定してあげましょう。
./scripts/configure.sh -l -F -D -p $INSTALL_PATH -b $BUILD_PATH
ここまで済んだらmakeコマンドでビルド開始です。
10分〜20分?程度で終了します。私は問題なくビルドが終わったのでよかったです。
pushd $BUILD_PATH
make -j2
popd
ビルドが完了したら、シミュレータを起動できるかどうかも確認しておきましょう。
起動方法を含め、シミュレータの解説はこちらのページで確認できます。
Simulator usage instructions for non-NASA users
https://github.com/nasa/astrobee/blob/master/sim_overview.md
シミュレータを起動するまえに、ROSのセットアップを行います。
ここで使用する環境変数PATHは、シミュレータのインストール時に設定したものと同じ値を使用します。
pushd $BUILD_PATH
source devel/setup.bash
popd
このコマンドを実行したあとは、ros
コマンドがLinuxシステムに認識されて実行できるようになります。
ちなみに、上記のセットアップコマンドは毎回実行する必要があるみたいです。
シェルスクリプトを自作しておくと便利ですね。こんな感じ👇
#!/bin/bash
export BUILD_PATH=$HOME/freeflyer_build/native
pushd $BUILD_PATH
source devel/setup.bash
popd
roslaunch astrobee sim.launch dds:=false robot:=sim_pub rviz:=true
インストールが正しく完了していれば、次のコマンドを実行することでシミュレータが起動するはずです。
このコマンドでは、ISSの所定の位置にastrobeeがドッキングされた状態でシミュレーションがスタートします。
roslaunch astrobee sim.launch dds:=false robot:=sim_pub rviz:=true
— あつし🎮デジゲー博B-04a (@Anaakikutsushit) September 26, 2019上記の動画のようにシミュレータが起動すればオッケーです。
この次はシミュレータの使い方を書いていきます。
#シミュレータの使い方
逐次コマンド実行
シミュレータが起動したあとは、更にもう一つ別のターミナルを起動してコマンドを実行すればastrobeeを動かすことが出来ます。
ROSで言うところの「ノード」を新規に立てるイメージですね。
公式チュートリアルに書いてある各種コマンドを実行してみましょう。
デフォルトではastrobeeがドッキングされた状態でシミュレータが起動しますので、最初にUndock
コマンドを実行します。
rosrun executive teleop_tool -undock
意外とアンドック処理に時間がかかるので、ターミナルの進捗表示を見ながら気長に待ちましょう。
その後、Moveセクションにあるコマンド
rosrun executive teleop_tool -move -pos "10.34 -9.51 4.49" -att "-3.14 0 0 1"
を実行すると、10.34 -9.51 4.49
の座標まで動いていって-3.14 0 0 1
の姿勢で静止します。
姿勢を指定するパラメータはクォータニオンと呼ばれる表記方法のようです。私にはサッパリわかりません。
そのほかにもTeleoperation Tool Instructionsに掲載されている各種コマンドを実行すればastrobeeに様々なアクションを取らせることが出来ます。
スクリプト実行
コマンドを一つ一つターミナルに打ち込んで実行するという形式は実践的ではありません。
astrobeeの一連の動作をプログラミングするには、Androidシミュレータを使う方法があります。
(普通にJavaでプログラミングするだけでもいいらしい)
プログラミングしたastrobee用のスクリプトは「ゲストサイエンスアプリケーション」と呼ばれているみたいです。
androidシミュレータを利用するにあたって、astrobeeのシミュレータと一緒にインストールした下記リポジトリを使用していきます(ちゃんとインストールされてますよね?)。
https://github.com/nasa/astrobee_android
開発環境としてAndroid Studioをインストールするところからやっていきましょう。
インストールにあたってこちらの記事を参考にさせていただきました。
Ubuntu 16.04 に Android Studio をインストール
先にJavaをインストールしておきます
$ sudo apt install openjdk-8-jdk
Android Studioの配布ページに行って、Linux用のパッケージをダウンロードします。
UbuntuのOSからアクセスすればダウンロードリンクが自動的にLinux用になっていると思います。
ダウンロードしたパッケージを任意の場所に展開しておきます。
ここからはastrobeeのドキュメントに従います。
creating_gs_app.mdを参照しましょう。
上記ドキュメントの冒頭にもあるように、$BUILD_PATH
などの環境変数PATHが設定されている前提で進んでいきます。
前出しておりますが、設定が戻ってしまっていたらastrobee/INSTALL.mdに記載の通りに再度設定をしておきましょう。
Build the Astrobee APIのセクションの通りにコマンドを実行してAndroid Studioをビルドしていきます。
私はff_msgsに対するmakeコマンドの実行中に下記の警告が出ましたが、無視しました。
警告: [options] ブートストラップ・クラスパスが-source 1.7と一緒に設定されていま警告1個
Built target ff_msgs_generate_messages_java_gradle
たぶんこれでandroid studioを起動できるようになったと思います。
以降はandroid_studio/bin/studio.sh
を実行すればandroid studioが起動します。
続いてビルド自動化システムのgradleをビルドしていきます。(Letting Gradle access ARS messages)
ドキュメント記載通りのデフォルトのディレクトリ設定で進めていけば特に問題はなかったです。
building the JAR filesセクションの./Gradle buildを実行して、ターミナルにBUILD SUCCESSFULと表示されればオッケー。
私の場合は相変わらず前出と同じブートストラップ・クラスパスに関連する警告が表示されましたが無視しました。
ビルドが無事に通ったので、ドキュメントのandroidセクションに進みます。
Androidの開発にはAPIレベルという概念があるんですね。
ドキュメントによると、そのAPIレベルを25にしてねと書いてあります。なので設定しておきましょう。
android studio起動画面右下のConfigureプルダウンメニューからSettings画面を呼び出します。
左側メニューのSystemSettingsを展開してAndroidSDKを選択。
API Levelが25のAndroid7.1.1(Nougat)だけにチェックを入れてApplyをクリック。
コンポーネントが削除されるよって警告が出るのでOKをクリック。
その後、Nougatで開発するに当たっての利用規約が出てくるのでよく読んでAcceptをチェックしてNextをクリック。
SDKに対応するコンポーネントのインストールが始まるので、完了するまで待てばオッケー。
記事執筆時点では!!! DISCLAIMER !!! We are still working on a way to import the GS library without having to do the following. Sorry for any inconvenience.
とのことだったので、Building the Guest Science Libraryの部分をやっていきます。
AndroidStudioのスタート画面でOpen ...を選択し、astrobee_android
リポジトリの中のguest_science
フォルダを選択します。
たぶんデフォルトのとおりだとfreeflyer_android/guest_science
って感じに配置されてるんじゃないでしょうか。
私の場合はフォルダを開いたら自動でビルドが始まりました。
しかしエラー。Failed to find target with hash string 'android-26'
...だそうです。25だけじゃなくて26も必要だったのかな。
エラー文の直下にInstall missing platform(s) and sync project
ってリンクを出してくれてたので、そのままインストールしときました。
その後も、ビルドでエラーが出る→必要なものを追加でインストールする(あるいはリファクタリングしてねと表示が出るのでDo Refactor
ボタンをクリックする)、という手順を踏み、無事にguest_scienceのビルドが通りました。
ビルドが通ったらこんな感じになります。
ちなみにこの状態では後述するディレクトリが生成されていなかったので、リビルドしておくのをおすすめします。
ドキュメントを読み進めます。
ライブラリ名の重複を避けるためにリネームした方がいいっぽいです。しておきます。
you@machine:~$ cd $ANDROID_PATH/guest_science/library/build/outputs/aar
you@machine:guest_science/library/build/outputs/aar$ mv library-debug.aar guest_science_library.aar
ここでアクセスしているoutputs
ディレクトリ以下はリビルドして初めて生成されました。
ドキュメントのImporting the Astrobee APIセクションに進みます。
ここから先はようやく自分のゲストサイエンスアプリケーション用のプロジェクトを作成していきます。
PROJECT_ROOT
として自分のプロジェクト用のディレクトリを新規作成しましょう。
AndroidStudioを起動して、メニューバーのFileからNewを選択、AddNoActivityで新規プロジェクトを作成します。
プロジェクト名やパッケージ名は適当に設定して、SaveLocationが今後のPROJECT_ROOT
となります。
たぶんguest_science
と同じ階層に置いておいた方が良い気がしたので、私はfreeflyer_android
の直下に新規フォルダを作成しました。
開発言語はJavaとします。
MinimumAPILevelはたぶん25でよいでしょう。
FinishをクリックするとGitに追加するファイルを選択する画面になりますが、デフォルトのオールチェックのままAddします。
プロジェクトの生成が終わると自動でビルドが始まります。完了するまでしばし待ちましょう。
まずは無事にビルドが通りました。
PROJECT_ROOT
となるディレクトリの生成ができたので、PATHを通しておくとよいでしょう。
ドキュメントに戻って、PROJECT_ROOT
ディレクトリにAstrobeeのAPIをインポートします。
you@machine:~$ cd $PROJECT_ROOT
you@machine:~$ cp $ANDROID_PATH/astrobee_api/api/build/libs/api-1.0-SNAPSHOT.jar app/libs
you@machine:~$ cp $ANDROID_PATH/astrobee_api/ros/build/libs/ros-1.0-SNAPSHOT.jar app/libs
you@machine:~$ cp $BUILD_PATH/devel/share/maven/org/ros/rosjava_messages/ff_msgs/0.0.0/ff_msgs-0.0.0.jar app/libs
Adding the Guest Science Library to Your Android Studio Projectのセクションに進みます。
AndroidStudioで先ほど作成したプロジェクトを開いて、記述の通りに操作しましょう。
Navigate to the 'Project' section of the Android Studio window
って操作は一瞬迷ったんですが、下図のように左のボタンをクリックすれば出てきてくれるっぽい。
(開いてるプロジェクト間違えた)
マウスカーソルが合っている場所の、見切れている1:Project...ってやつをクリックします。
build.gradleは3つありますが、build.gradle(Module:App)は一つです。これを開きます。
ここでdependencies
sectionに一文追加して保存しました。
ただし、下記記事記載のものと同様の警告が発生していたため、「compile」を「implementation」で置き換えています。
Android Studioの新コンフィグレーションimplementationとapiのひとつ注意点
Telling Gradle about ROS and the Astrobee APIセクションに進みます。
今度は別のbuild.gradleを開き、allprojects
セクションを編集。
サンプル通りに記述して保存したところ、写真にも写っていますが、Syncしたらエラーが出てしまいました。
元から入っていたgoogle()
の一文を追加し直してみたらエラーが出なくなったので、これで進めることにします。
google()
追加後の様子が上図です。
Syncも上手く行ったことですので、その次のStart Serviceセクションに進みます。
当該セクションの説明によると、StartGuestScienceService
クラスがGSマネージャとGS APKの間のやり取りを上手いことやってくれるよう設計されているとのこと。
従ってStartGuestScienceService
クラスを継承したり拡張したりしながら、自分のアプリでastrobeeにやらせたいコマンドを書き込んでいくという流れになるようです。
そしてAndroidマニフェストファイルに特定のメタデータを追加することで、GSマネージャと前述クラスの連携を取れるようにする……みたいですね。
ちなみに、Androidマニフェストファイルとは、全てのAndroidアプリプロジェクトのルートディレクトリに追加する必要があるXMLファイルとのことです。
参考:アプリ マニフェストの概要
下図のように、マニフェストファイルのapplication要素の中にserviceを挟み込んであげればいいみたいですね。
リビルドも問題なく通りました。
ここまでくれば、あとはもう好きに開発ができる環境が整ったようです。すごい。
ドキュメントによるとアプリのサンプルはgs_examples
ディレクトリの中のtest_simple_trajectory
プロジェクトを見ればいいみたい。
そーゆーことで実際にサンプルアプリを見てみましょう。
中身のコードを読んでいく前に、サンプルアプリがどのように動作するのかを実行して確認してみます。
アプリを実行するためにはAndroidデバイスが必要になります。
サンプルアプリを実行してみる前に、emulator.mdを参照してUbuntuとAndroidデバイスを接続出来るように設定しましょう。
ドキュメントの3. Add an emulator
ではメニューバーのToolsからAVD Managerを開いてねって書いてありますが、私が使っているAndroidStudioのバージョン3.5.1ではツールバーにアイコンがあったのでそちらから開きました。
参考:仮想デバイスの作成と管理
AVD Managerを無事開けたら、あとはドキュメント通りに進めます。
+ Create Virtual Device...
をクリック
PhoneカテゴリーからNexus5(解像度1080x1920)を選択してNextをクリック。
Select a system Imageのページでx86 Imagesタブを選びます。
select Nougat/API Level 25/ABI x86_64/Android 7.1.1 (NO Google APIs)
の通りにシステムイメージを選びます。
リンクをクリックしてダウンロードを完了するとNextボタンを押せるようになります。
Startup orientationはPortraitを選択。
Show Advance Settingsも覗いてみましたが、RAMの割当がデフォルトで1.5GB以上になっていたので何もいじりませんでした。
Finishをクリックして仮想デバイスの設定を終了します。
設定が終わったところの画面はこんな感じ。
続いて、ADBコマンドを使用可能にするためにsudo apt-get install adb
でパッケージをインストールします。
私はaptでインストールしちゃったけど大丈夫っぽい。この2つの違いってなんなんだろ
ドキュメントの5. Setting HOST networkに進みます。
/etc/hosts
ファイルをエディタで開いて編集します。このファイルが何のためのものなのかはわかりません。
仮想デバイスを使うにあたってIPを設定していきますが、それぞれの値はドキュメントの冒頭に書かれていた10.42.0.34-36をそのまま使用します。
編集前のhosts
編集後のhosts
hlp, mlp, llpの3行を追加した形です。保存してエディタを閉じます。
環境変数を確認します。ターミナルで以下のコマンドを実行します。
~/Android/Sdk/tools/emulator -list-avds
# Nexus_5_API_25
仮想デバイスを設定した時の名前が表示されれば問題ありません。
上記のNexus_5_API_25は私の設定例です。
デバイス名を確認できたら、環境変数を設定しましょう。
- ANDROID_PATH:ここまでで既に設定済みかと思います
- EMULATOR:ドキュメントの通りです($HOME/Android/Sdk/tools/emulator)
- AVD:先ほど表示したデバイス名です。
最後にネットワークブリッジを設定したらドキュメントのセクション5は終わりです。
cd $ANDROID_PATH/scripts
./launch_emulator.sh
エミュレータを起動したまま、次のセクション6. Setting Android networkに進みます。
新しくターミナルを起動して、hostsファイルに対してpullコマンドを実行します。
adb pull /system/etc/hosts $HOME
私は1度目のコマンドは失敗したのですが、2度同じコマンドを実行することで何とかなりました
pullしたhostsをエディタで開き、前述したIPを追加します。
追加する前のhosts
追加したあとのhosts
追加できたら保存してエディタを閉じ、hostsを仮想デバイスに向けてpushします。
adb root # Wait a few seconds
adb remount
adb push ~/hosts /system/etc
その後、エディタで$ANDROID_PATH/scripts/emulator_setup_net.sh
を開き、5行目を先ほど設定したHLPのIPに書き換えます。
書き換えたあとのファイルはこんな感じ
エディタを閉じたらこちらのファイルもpushします。
adb push $ANDROID_PATH/scripts/emulator_setup_net.sh /cache
続いて、pushしたファイルを仮想デバイス側で実行します。
adb shell
コマンドを実行することで、仮想デバイス側のターミナル操作になってるっぽいことが伺えます。
そのままpingコマンドも実行していきましょう。
見た感じ、hlpのpingコマンドは成功しているみたいなんですが、llpのpingは失敗しているようです。
軽く調べただけだと修正方法もわからず、修正したほうがいいのかもわかりませんでした。
あとで問題になったら立ち戻って調べることにします。
以上でシミュレーターのセットアップは終了です。
シミュレーターを再度実行する場合は、環境変数が設定されていることを確認した上で下記コマンドを実行すればまた起動します。
cd $ANDROID_PATH/scripts
./launch_emulator.sh -n
シミュレータの準備ができたので、ようやくrunning_gs_app.mdを参照し、Test Simple Trajectoryアプリのビルドとインストールをしてみます。
you@machine:~ $ cd $ANDROID_PATH/gs_examples/test_simple_trajectory
you@machine:guest_science_manager $ ANDROID_HOME=$HOME/Android/Sdk ./gradlew assembleDebug
you@machine:guest_science_manager $ adb install -gr app/build/outputs/apk/app-debug.apk
2番目のassembleDebugの結果がBUILD SUCCESSFUL
になることを確認します。
3番目のadbコマンドを実行するときにエミュレータを起動しておく必要があります。
ここから新たにターミナルを2つ起動します。これらのターミナルを①および②としましょう。
①および②の両方のターミナルで下記コマンドを実行します。
you@machine:~ $ export ROS_IP=$(getent hosts llp | awk '{ print $1 }')
you@machine:~ $ export ROS_MASTER_URI=http://${ROS_IP}:11311
you@machine:~ $ echo $ROS_IP
①と②どちらの端末でもIPを取得できていることを確認します。
Guest Science Managerを起動します。
①のターミナル側で下記のコマンドを実行します。
you@machine:~ $ ./$ANDROID_PATH/scripts/gs_manager.sh start
しかし私はここでエラーが出てしまいました。
接続されているデバイスが見つからないという趣旨のようですが、エミュレータは検出(adb devices -lで確認)されているみたいなので謎。
原因不明のまま次のセクションに進みます。
you@machine:~ $ cd $SOURCE_PATH/tools/gds_helper/
you@machine:gds_helper $ python gds_simulator.py
当該のPythonコードを実行しようとしましたが、rospyライブラリがインストールされていないために失敗しました。追加でインストールしようとしたのですが、力尽きてしまいました……