このドキュメントの内容
ROSを触り始めたが、pythonもC++もあまり得意ではないので、RustでNodeを書きたくやり方を調べた。
rosrustを利用すればできることはすぐわかったし、わかりやすい記事も紹介されていたが、これらのページだけではcatkinで管理する方法がわからなかったので調べた結果をメモする。
以下の内容は基本的に公式サイトのチュートリアルとrosrustのリポジトリに立っていたissueの内容である。
手順
まずRustのプロジェクトを作る。プロジェクト名は適宜変更する。
$cd ~/catkin_ws/src
$cargo new --bin rust_test
作られたRustのプロジェクトをROSパッケージとして認識させるためには、package.xmlとCMakeLists.txtを含まなければならない(公式サイトのチュートリアル参照)ので、この2つを作る。
CMakeファイルはissueに neachdainnさんが記載されていた内容ほぼそのままであるが、オリジナルではcargoのpオプションでmy-projectとしているのに、copyの行ではmy-project-binaryと書かれており、コピーに失敗するので注意が必要である。
project名はRustのプロジェクト名と合わせて変更する。
(これでも動くけど変更箇所が多いので、修正参照)
cmake_minimum_required(VERSION 3.0)
project(rust_test)
find_package(catkin REQUIRED)
catkin_package()
add_custom_target(rust_test
ALL
COMMAND cargo build --release -p rust_test
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/cargo/release/rust_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rust_test
COMMENT "Building my Rust library"
)
package.xmlはC++のときと同じ容量で書き換える。これもプロジェクト名を合わせる
<?xml version="1.0"?>
<package format="2">
<name>rust_test</name>
<version>0.0.0</version>
<description>my 1st rosrust package</description>
//以下略
これでROSのパッケージとして認識され、catkin_makeのビルド対象として扱われる。
但しこのままだとまだビルドがうまく行かないので、Rust側で設定をいくつか行う。
まず~/catkin_ws/Cargo.tomlに、ビルド対象となるRustリポジトリの場所を記載する。
[workspace]
members = [ "src/rust_test" ]
次に~/catkin_ws/.cargo/configに以下の設定を入れる。
[build]
target-dir = "build/cargo"
こうしておくと、cargoでビルドされたファイルが~/catkin_ws/build/cargo内に収まるので、C++で書かれたパッケージと混じらない。
これでビルド環境自体はできたので、実際のコードを記載する。これは元記事やrosrustにある通りで、Rustがかける人には問題にならないので割愛。
(但し、rosrustのトップページに有るpub/subの例は、talkerがStringで送っているのにlistenerがUInt64で待ち受けているので通信に失敗する。何かしら間違っているのかと思って三度見したので注意が必要。)
最終的にディレクトリ構成はこうなる
catkin_ws
|--- Cargo.toml
|--- .cargo
| |--- config
|--- src
|--- rust_test
| |--- Cargo.toml
| |--- CMakeLists.txt
| |--- package.xml
| |--- src
| |--- main.rs
この状態で
$cd ~/catkin_ws
$catkin_make
$rosrun rust_test rust_test
するとRustで書いたROSパッケージが起動する。roslaunchも大丈夫だった。C++を書く必要はなくなりそうで一安心。
修正(2020/10/5)
CMakefileで何箇所もプロジェクト名を書かないといけないのは面倒なので、変数化した。
cmake_minimum_required(VERSION 3.0)
# add_custom_targetでコマンドを叩くので環境変数として定義しておく
set (ENV{PROJECT_NAME} rust_test)
project($ENV{PROJECT_NAME})
find_package(catkin REQUIRED COMPONENTS
std_msgs
message_generation
)
add_message_files(
FILES
Orientation.msg
)
catkin_package(
CATKIN_DEPENDS std_msgs message_runtime
)
add_custom_target($ENV{PROJECT_NAME}
ALL
COMMAND cargo build --release -p $ENV{PROJECT_NAME}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/cargo/release/$ENV{PROJECT_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$ENV{PROJECT_NAME}
COMMENT "Building my Rust library"
)
# セットした環境変数をクリアしておく
unset (ENV{PROJECT_NAME})
あと、当然だがCMakefileやpackage.xmlで記載しているプロジェクト名と、Cargo.toml内のプロジェクト名が一致していないと動かないので注意。
(今日別のリポジトリをコピーしてハマった)