Ros-sharpを使って、UnityとROSで通信する方法をご紹介します。
テスト環境:
- Robovie-Z with Pi4 running ROS Melodic
- Win10 with Unity v2019.4.16.f1
- Ros-sharp v1.6
ROSのセットアップ方法は、ここで紹介してます。
1.UnityストアからRos-sharpをインストール
Unityプロジェクトを開く、または新規作成してください。
ツールバーの”Edit”→”Project Settings”から”Player”を開いて、
”Api compatibility Level” を”.Net 4.x”に変更します。
(なぜか設定変更し忘れても動いてました…。)
Unityストアの検索バーに”ROS”と入れて検索すると、2番目に出てきます。
インポートボタンを押して、Assetに追加します。
Unityバージョンが古いと、インポートボタンが無効になっていると思います。
必要に応じてアップデートしてください。
インポートすると、AssetフォルダにRosSharpがついかされます。
ツールバーには”RosBridgeClient”が追加されます。
2.Unity上のテストアプリを用意する
空のGameObjectを作ります。
UnityのHirarchyウィンドウ上で右クリック、”Create Empty”を選択
作成したGameObjectにAsset/RosSharp/RosBridgeClient/RosCommunication/RosConnectorをドラッグドロップ
インスペクタウィンドウに、RosCommunicationスクリプトがいるので、
ServerURLをROSが走っているマシンの”IPアドレス:9090”に書き換えます。
Assetフォルダに新しく、スクリプトを作成。
今回は”TestRosSharp”という名前にしました。
コードはこちら、
*このコードはビルドしますが、動作に問題があります。後ほど解説。
using std_msgs = RosSharp.RosBridgeClient.Messages.Standard; using UnityEngine; using System.Threading; namespace RosSharp.RosBridgeClient { public class TestRosSharp : MonoBehaviour { private RosConnector rosConnector; string publication_id; string subscription_id; // Start is called before the first frame update, here the connection with ROS is established and the tipics are defined void Start() { rosConnector = GetComponent<RosConnector>(); Debug.Log("Established connection with ros"); //Thread.Sleep(3000); publication_id = rosConnector.RosSocket.Advertise<std_msgs.String>("publication_test"); subscription_id = rosConnector.RosSocket.Subscribe<std_msgs.String>("/subscription_test", SubscriptionHandler); } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.S)) //press S key every time you want to send messages to ROS { std_msgs.String message = new std_msgs.String { data = "Message sent from unity" //UNITY message for ROS }; rosConnector.RosSocket.Publish(publication_id, message); Debug.Log("A message was sent to ROS"); } if (Input.GetKeyDown(KeyCode.C)) //press C key to close the connection { rosConnector.RosSocket.Close(); Debug.Log("Closed connection"); } } private static void SubscriptionHandler(std_msgs.String message) { Debug.Log(message.data); //print ROS's message to unity } } }
ここで拾ったコードを少し変更しました。
I can not send and receive simple data with ROS # – ros-sharp (gitmemory.com)
作成したテストスクリプトをGameObjectにドラッグドロップします。
GameObjectのインスペクタを確認して、TestRosSharpスクリプトが追加されていればOK。
3.Rosbridge_serverをROSにセットアップ
ワークスペースのソースディレクトリに移動して、
- rosbridge_suite
- rosauth
の2つパッケージをリポジトリから展開します。
cd ~/catkin_ws/src git clone https://github.com/RobotWebTools/rosbridge_suite.git git clone https://github.com/GT-RAIL/rosauth.git
ワークスペースのルートに戻って、rosdepを使って依存関係を解決し、catkin_makeを実行
cd ~/ros_catkin_ws rosdep install --from-paths src --ignore-src -r -y catkin_make
*rosdepを忘れると、rosbridge_serverがうまく動かないことがあります。
*もし後々”twisted”などのパッケージが足りないと出たら、rosdepを忘れてる可能性大です。
*不足パッケージをpip でインストールしてしまうと、互換性のないパッケージバージョンでインストールしてしまう可能性があるので、rosdep を使いましょう。
ここに書いてあります。私もこれで1日はまりました。
Nothing returned from rosbridge webserver · Issue #336 · RobotWebTools/rosbridge_suite · GitHub
4.通信してみる
ROSマシンでターミナルを開いて、rosbridge_serverを起動
roslaunch rosbridge_server rosbridge_websocket.launch
ステップ2で作ったUnityアプリを実行すると、
Unityアプリからrosbridge_serverに接続できていることがわかります。
UnityアプリのGameウィンドウをクリックしてキーボードの”S”を押して、
メッセージをPublishします。
ROSのマシンから別のターミナルを開いてトピックを確認してみます。
rostopic list
Unityアプリで作成した”/publication_test”と”/subscription_test”が見当たりません。
なぜかというと、rosbridge_serverとの接続が完了する前に、
”Advertise”と”Suscribe”が呼ばれているからです。
わたしはこれでまた1日はまってました…。
本当はよくないですが、今回は動作テストなので、Thread.Sleepを使って遅延します。
*ROS-Sharpのリポジトリから最新版のソースを直接Unityに展開した場合は、
ソースが少し変更されてて、こういうこともできます。
if (!rosConnector.IsConnected.WaitOne(SecondsTimeout * 1000)) Debug.LogWarning("Failed to subscribe: RosConnector not connected");
ただ、リポジトリから最新版のソースを使った場合、今回のコードに必要なオブジェクトが足りないものが出てきて、今回のテストコードはビルドできなくなります。
20行目のコメントアウトを外して、
Unityアプリを実行しなおすと。
無事にトピックが見れるようになりました。
echoコマンドを使って中身を見てみます。
rostopic echo /publication_test
ちゃんとメッセージの中身が見れてます。
ROSからUnityアプリへの通信も確認してみましょう。
pubコマンドを使って、メッセージをパブリッシュします。
rostopic pub /subscription_test std_msgs/String "Hello UNITY"
Unityのデバッグウィンドウを確認すると?
ROSからのメッセージがとどいてます!
以上、「UnityアプリとROSで通信してみた」でした。
これができるということは…
「あんなことや、こんなこと」も!?