はじめに
roslibjsを使って開発している中で、日本語の情報がまとまっておらず不便だったためまとめてみました。
基本的にはROS Wiki に記載されている内容ですが、サービスについては追加しています。
paramについては利用していないので記載していません。
他の使い方も、勉強し次第追記しようと思います。
間違い等あれば指摘していただけると幸いです。
環境
- Ubuntu16.04
- ROS kinetic
-
rosbridge-server
パッケージをインストール
-
- node
-
roslib
をインストール
-
ウェブページ等で動かす場合にはnodeのインストールは不要です。
roslibjsのインポート
NodeJSを利用する場合
const ROSLIB = require("roslib");
ウェブページ等で利用する場合 (html内に)
<script type="text/javascript" src="http://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script type="text/javascript" src="http://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
rosとの接続の確立
接続するurlやrosbridge-websocket
を介してrosと接続したとき、接続でエラーが起きたとき、接続が閉じられた時などに行う処理を記載します。
この際、url内のホスト名はrosbridge-websocket
を起動するPCのホスト名であり、roscore
が起動しているROS_MASTER_URI
のホスト名とは異なるため注意します。
const ros = new ROSLIB.Ros({
url: 'ws://localhost:9090'
});
ros.on('connection', () => {
console.log('Connected to websocket server');
});
ros.on('error', error =>{
console.log('Error connecting to websocket server: ', error);
});
ros.on('close', () => {
console.log("Connection to websocket server was closed");
});
Publish
トピックの宣言、メッセージの宣言等は以下のように行います。
const cmdVel = new ROSLIB.Topic({
ros : ros,
name : '/cmd_vel',
messageType : 'geometry_msgs/Twist'
});
const twist = new ROSLIB.Message({
linear : {
x : 0.1,
y : 0.2,
z : 0.3
},
angular : {
x : -0.1,
y : -0.2,
z : -0.3
}
});
宣言したcmdVel
トピックのメッセージとしてtwist
をpublishする場合は以下のようにします。
cmdVel.publish(twist);
Subscribe
まずは、publish時と同様に、subscribeしたいトピックを宣言します。
const listener = new ROSLIB.Topic({
ros : ros,
name : '/listener',
messageType : 'std_msgs/String'
});
そして、そのトピックを受け取った際に行う関数を登録します。
listener.subscribe(message => {
console.log('Received message on ' + listener.name + ': ' + message.data);
});
以上の方法でトピックを受け取ることができます。
これ以上受け取る必要がない場合には、以下のようにunsubscribe()
を実行しましょう。
listener.unsubscribe();
Service
ROS Wikiには、サービスコールについてのみしか記載されていないため、roslibjsのリポジトリを見て理解したことをまとめます。
サービスの宣言
name
にはサービスの名前を,serviceType
にはサービスタイプを記載します。rosbridge_websocket
を起動するPC上でsrvファイルを作成し、catkin_make
しておくか、ROSの基本パッケージで定義されたサービスタイプを利用しましょう。
ここでは、ROS Wikiで使用されているrospy_tutorials/AddTwoInts
を使用しています。必要な場合はros-kinetic-rospy-tutorials
をインストールしましょう。
const addTwoIntsClient = new ROSLIB.Service({
ros: ros,
name: '/add_two_ints',
serviceType: 'rospy_tutorials/AddTwoInts',
});
サービスコール
宣言したサービスへのリクエストの内容を宣言し、サービス.callService()
の引数としてリクエストの内容と、レスポンスがあった際の処理を記載することでサービスコールを行うことができます。
let request = new ROSLIB.ServiceRequest({
a : 1,
b : 2
});
addTwoIntsClient.callService(request, result => {
console.log('Result for service call on '
+ addTwoIntsClient.name
+ ': '
+ result.sum);
});
サービスの実行
宣言したサービスを、js上で実行する方法です。
上で宣言したサービスをそのまま使ってもいいのですが、名前がClientなのに違和感があるので新たに宣言します。
const addTwoIntsServer = new ROSLIB.Service({
ros: ros,
name: '/add_two_ints_server',
serviceType: 'rospy_tutorials/AddTwoInts',
});
そして、リクエストへの処理をコールバックとして記述し、以下のようにサービス.advertise()
の引数に与えることでサービスを実行できます。
addTwoIntsServer.advertise((req, res) => {
res.sum = req.a + req.b
return;
}
この際、rosbridge_websocket
を実行したままの状態で、ページの再読込等によって同じサービスの宣言が複数回行われてしまうと、初回のサービスコールが失敗する場合があるため注意してください。
サービスの停止
一度実行したサービスを停止したい場合には、以下のようにサービス.unadvertise
を実行します。
addTwoIntsServer.unadvertise();
おまけ
pythonやC++で開発を行う際に、別のノードで実行されているサービスへサービスコールを行う場合には,waitForService()
等を利用するかと思います。
roslibjs
には同様の関数はありませんが、
ros.getServices(services => {
if(services.indexOf('/add_two_ints') != -1){
...(中略)...
});
以上のようにgetServices()
メソッドで、サービスの一覧をリストで取得できるため、使用したいサービスが格納されているindexを探すと、サービスが実行されているかが分かります。
もっと良い使い方があれば教えてください。