UnityからRos-sharpを使って、Robovie-Zのメモリーマップに書き込む方法をご紹介します!
Unity+ROS+Robovie-Zシリーズ最終回は、
Robovie-Z SDKに実装されているROSサービスをつかって、
Robovie-Zのメモリマップを書き換えてみます。
前回までは、



1.ROS サービスモデルを作る
ROSメッセージモデルを作った時の同じ要領で、
ROSサービスモデルを作ります。

パッケージ名を確認して実行。

アセットフォルダに、サービスモジュールが作成されます。

SDKには”MemRead”と”MemWrite”の2つのサービスが定義されています。
両方ともモジュールを作っておきましょう。

2.コードを書く
スクリプトを新規作成し、
ROSとサービスのやり取りをするコードを書きます。
using RosSharp.RosBridgeClient;
using RosSharp.RosBridgeClient.MessageTypes.RoboviezRosMsgs;
using RosSharp.RosBridgeClient.MessageTypes.Std;
using UnityEngine;
using System;
using System.Threading;
using System.Collections.Generic;
public class MemReadWrite : MonoBehaviour
{
public int memAddress;
public int dataToSend;
private RosConnector rosConnector;
private readonly int SecondsTimeout = 3;
private MemReadRequest readRequest;
private MemWriteRequest writeRequest;
void Start()
{
rosConnector = GetComponent<RosConnector>();
if (!rosConnector.IsConnected.WaitOne(SecondsTimeout * 1000))
Debug.LogWarning("Failed to subscribe: RosConnector not connected");
}
void Update()
{
if (Input.GetKeyDown(KeyCode.R)) //press S key every time you want to send messages to ROS
{
readRequest = new MemReadRequest((short)memAddress, 2);
rosConnector.RosSocket.CallService<MemReadRequest, MemReadResponse>("/roboviez_ros_controller/memmap_read", ReadServiceCallHandler, readRequest);
}
if (Input.GetKeyDown(KeyCode.W)) //press S key every time you want to send messages to ROS
{
Write(memAddress, dataToSend);
}
}
public void Write(int addresss, int value)
{
MultiArrayLayout layout = new MultiArrayLayout();
layout.data_offset = 0;
layout.dim = new MultiArrayDimension[1];
layout.dim[0] = new MultiArrayDimension("x", 2, 1);
byte[] data = new byte[] { (byte)(value & 255), (byte)(value >> 8) };
writeRequest = new MemWriteRequest((short)addresss, new UInt8MultiArray(layout, data));
rosConnector.RosSocket.CallService<MemWriteRequest, MemWriteResponse>("/roboviez_ros_controller/memmap_write", WriteServiceCallHandler, writeRequest);
}
private static void ReadServiceCallHandler(MemReadResponse response)
{
byte[] values = new byte[2];
response.Buf.CopyTo(values, 0);
try
{
int value = BitConverter.ToInt16(values, 0);
Debug.Log("Value Received: " + value.ToString());
}
catch (Exception ex)
{
Debug.Log(ex.ToString());
}
//Debug.Log(BitConverter.ToString(response.Buf));
}
private static void WriteServiceCallHandler(MemWriteResponse response)
{
//Debug.Log("Service requested to ROS");
}
}
できたスクリプトは、忘れずにGameObjectにドラグドロップして追加。
3.Unityでアプリを実行
CPUがONになっていることを確認して、

ターミナルを開いて、ROSにログインし、RosBridgeServerを起動。
roslaunch rosbridge_server rosbridge_websocket.launch
別ターミナルから、roboviez_ros_controllerを起動。
rosrun roboviez_ros_samples roboviez_ros_controller.py
Unityでアプリを実行。
GameObjectを選択してInspectorウィンドウから、

書き込むアドレスと数値を入力。
今回は、SDKマニュアルの例と同じように、
アドレス3872番に、1234を書き込みます。
Gemeシーンをクリックしてアクティブにして、
キーボードの”R”キーを押し、数値を読み込むと?

次に、キーボードの”W”キーを押して、”1234”を書き込み、
”R”キーを押して再度、値を読み込むと?

アドレス3872番の数値が0から1234に変わりました!
メモリーマップへの書き込み成功です!
4. 何ができる?
これでメモリーマップの読み書きができるようになりました!
ということは、Unityアプリからロボットの各関節を、
自由にコントロールできるようになったということです!!!

今回は残念ながら時間切れで、検証できませんでしたが、
Unity上で踊る3Dモデルの関節の動きを、Robovie-Zにコピーしてシンクロダンス!
RealSenseを使って、人の動きを読み込み、Robovie-Zを動かしたり。
他にもいろいろ面白そうなことができそうですね!
今回は、Unityを使ってアプリを書きましたが、
ROSとのやりとりさえできれば、どんな開発環境でも問題ありません。
でも、UIありのアプリ作るなら、Unityが一番楽なんだよね。
みなさんも是非、Robovie-Zと遊んでみてください!



