今回はUnityからROSメッセージをSubscribeして、Robovie-Zを操作してみます。
前回までは、
UnityからRos-sharpを使って、Robovie-Zを動かす! その①
今回は、UnityアプリからRobovie-Zを動かします。
前回までは、
1. Unityプロジェクトを用意
使用するUnityプロジェクトの、Edit→Project Setting→PlayerからA...
1. ROSメッセージモジュールを用意
まずはRobovie-Z SDK で実装されているメッセージを確認すると、
AssetストアからRos-sharpをインポートした際には、
Standardメッセージ型はすでにプラグインとして実装されていましたが、
リポジトリからインポートすると、これらのスタンダード型メッセージは実装されていませんでした。
スタンダード型のメッセージモデルを、自分で作ります。
RosSharpMessagesフォルダの中にBoolとInt16というスクリプトを作り、
それぞれコードを書きます。
*フォルダ名が”RoboviezRos”から、”RoboviezRosMsgs”に変わってます。
*Namespaceも”RosSharp.RosBridgeClient.MessageTypes.RoboviezRosMsgs”に変えました。
namespace RosSharp.RosBridgeClient.MessageTypes.Standard { public class Bool : Message { public const string RosMessageName = "std_msgs/Bool"; public bool data; public Bool() { this.data = false; } public Bool(bool data) { this.data = data; } } }
namespace RosSharp.RosBridgeClient.MessageTypes.Standard { public class Int16 : Message { public const string RosMessageName = "std_msgs/Int16"; public short data { get; set; } public Int16() { this.data = 0; } public Int16(short data) { this.data = data; } } }
2.Publish用のコードを書く
MsgSendReceiveスクリプトにPublish用コードを追加します。
using System.Collections; using System.Collections.Generic; using RosSharp.RosBridgeClient; using robovie_msgs = RosSharp.RosBridgeClient.MessageTypes.RoboviezRosMsgs; using std_msgs = RosSharp.RosBridgeClient.MessageTypes.Standard; using UnityEngine; namespace Roboviez { public class MsgSendReceive : MonoBehaviour { private RosConnector rosConnector; private readonly int SecondsTimeout = 3; private string subscription_id; private string publication_id_poweron; private string publication_id_uartmotion; private bool isPoweron = false; // 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>(); if (!rosConnector.IsConnected.WaitOne(SecondsTimeout * 1000)) Debug.LogWarning("Failed to subscribe: RosConnector not connected"); subscription_id = rosConnector.RosSocket.Subscribe<robovie_msgs.IMU>("/roboviez_ros_controller/imu", SubscriptionHandler, (int)(1 * 3000)); publication_id_poweron = rosConnector.RosSocket.Advertise<std_msgs.Bool>("/roboviez_ros_controller/poweron"); publication_id_uartmotion = rosConnector.RosSocket.Advertise<std_msgs.Int16>("/roboviez_ros_controller/uartmotion"); } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.P)) { isPoweron = !isPoweron; //toggle the value std_msgs.Bool pwr_msg = new std_msgs.Bool() { data = isPoweron //UNITY message for ROS }; rosConnector.RosSocket.Publish(publication_id_poweron, pwr_msg); Debug.Log("Sent Poweron message to ROS:" + isPoweron.ToString()); } if (Input.GetKeyDown(KeyCode.Alpha0)) { publishUartmotion(0); } if (Input.GetKeyDown(KeyCode.Alpha4)) { publishUartmotion(4); } if (Input.GetKeyDown(KeyCode.Alpha5)) { publishUartmotion(5); } if (Input.GetKeyDown(KeyCode.Alpha6)) { publishUartmotion(6); } } private void publishUartmotion(short motionNumber) { std_msgs.Int16 uartmotion = new std_msgs.Int16() { data = motionNumber }; rosConnector.RosSocket.Publish(publication_id_uartmotion, uartmotion); Debug.Log("Sent animation request to ROS:" + uartmotion.data.ToString()); } private static void SubscriptionHandler(robovie_msgs.IMU message) { Debug.Log(message.temperature); //print ROS's message to unity } } }
3.プログラムを実行
CPUがONになっていることを確認して、
ターミナルを開いて、ROSにログインし、RosBridgeServerを起動。
roslaunch rosbridge_server rosbridge_websocket.launch
別ターミナルから、roboviez_ros_controllerを起動。
rosrun roboviez_ros_samples roboviez_ros_controller.py
Unityでアプリを実行すると!?
キーボードのキーを入力するだけで、Robovie-ZのサーボON/OFF、
アニメーションの呼び出しができるようになりました!