rosrustとは
rosrustは adnanademovic
さんによって開発されているpure rustによるROS(ROS1)クライアントです。
Rustは次世代のC++と目されていたり、Linux/Mac/Windowsで動作します。
ロボットと相性の良い言語です。
二年前にRustとRoboticsの相性を語った記事
開発状況
基本的な機能はすべて実装済みで、実用的に利用出来る状態にあると思います。
ただし、TFの扱い、sensor_msgs/Imageの変換等が簡単には出来ないのでRustでプログラムする上で困ることは正直あると思います。
試したことないですがactionlibは対応しているようです。
https://github.com/adnanademovic/rosrust/tree/master/rosrust_actionlib
以前調査したros2_rustはPub/Subしか出来ておらず、作ってみた感が強いですが、rosrustは実用レベルにあると思います。
rosrustは2年前から存在していて、しかも今も開発が継続されています。
個人管理リポジトリにしてはなかなか素晴らしいのではないでしょうか?
サンプル
以下にexamplesがありますので、これを参照するのがいいと思います。
一応転載しておきます。
Publisher
use env_logger;
use rosrust;
mod msg {
rosrust::rosmsg_include!(std_msgs / String);
}
fn main() {
env_logger::init();
// Initialize node
rosrust::init("talker");
// Create publisher
let chatter_pub = rosrust::publish("chatter", 2).unwrap();
let log_names = rosrust::param("~log_names").unwrap().get().unwrap_or(false);
let mut count = 0;
// Create object that maintains 10Hz between sleep requests
let rate = rosrust::rate(10.0);
// Breaks when a shutdown signal is sent
while rosrust::is_ok() {
// Create string message
let mut msg = msg::std_msgs::String::default();
msg.data = format!("hello world from rosrust {}", count);
// Log event
rosrust::ros_info!("Publishing: {}", msg.data);
// Send string message to topic via publisher
chatter_pub.send(msg).unwrap();
if log_names {
rosrust::ros_info!("Subscriber names: {:?}", chatter_pub.subscriber_names());
}
// Sleep to maintain 10Hz rate
rate.sleep();
count += 1;
}
}
Subscriber
use env_logger;
use rosrust;
mod msg {
rosrust::rosmsg_include!(std_msgs / String);
}
fn main() {
env_logger::init();
// Initialize node
rosrust::init("listener");
// Create subscriber
// The subscriber is stopped when the returned object is destroyed
let subscriber_info = rosrust::subscribe("chatter", 2, |v: msg::std_msgs::String| {
// Callback for handling received messages
rosrust::ros_info!("Received: {}", v.data);
})
.unwrap();
let log_names = rosrust::param("~log_names").unwrap().get().unwrap_or(false);
if log_names {
let rate = rosrust::rate(1.0);
while rosrust::is_ok() {
rosrust::ros_info!("Publisher uris: {:?}", subscriber_info.publisher_uris());
rate.sleep();
}
} else {
// Block the thread until a shutdown signal is received
rosrust::spin();
}
}
解説
非常に直感的にかけているのであまり解説は不要な気がしますが、いくつかポイントだけ。
メッセージ生成
rosrust::rosmsg_include!(std_msgs / String);
ここでマクロを使ってstd_msgs/String
をRustに変換しています。
SubscriberのCallbackについて
subscriberのコールバックが以下のように定義されています。
|v: msg::std_msgs::String| {
// Callback for handling received messages
rosrust::ros_info!("Received: {}", v.data);
}
これはC++11でいうと、
[](std_msgs::String::ConstPtr &v) {
ROS_INFO("Received: %s", v.data.c_str());
}
と同じなのですが、{}
の中は別スレッドで実行されるのでデータのやり取りをする場合にはしっかり排他制御してやる必要があります。Rustのありがたいところは排他制御しないとコンパイルエラーになるため、実行時にわけの分からないバグが発生する余地がないところです。
ライセンス表記
一応
The MIT License (MIT)
Copyright (c) 2016 Adnan Ademovic
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
最後に
というわけでrosrustは結構実用レベルなのでぜひ使ってみてはどうでしょうか。
ros2もなんとかしてほしいところではあります・・・。