Unity Robotics Hub 入門 (8) - ROS–Unity Integrationのサンプルコード
「Unity Robotics Hub」のROS–Unity Integrationのサンプルコードを確認してみます。
前回
1. パブリッシュ
トピック「pos_rot」でGameObjectの姿勢を0.5秒毎にパブリッシュするコードです。
・unity_scripts/RosPublisherExample.cs
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
using RosMessageTypes.UnityRoboticsDemo;
// パブリッシュ
public class RosPublisherExample : MonoBehaviour
{
ROSConnection ros; // ROSコネクション
public string topicName = "pos_rot"; // トピック名
public GameObject cube; // GameObject
public float publishMessageFrequency = 0.5f; // パブリッシュレート
private float timeElapsed; // 経過時間
// スタート時に呼ばれる
void Start()
{
// ROSコネクションの準備
ros = ROSConnection.GetOrCreateInstance();
// パブリッシャーの登録 (1)
ros.RegisterPublisher<PosRotMsg>(topicName);
}
// スタート時に呼ばれる
private void Update()
{
// 0.5秒毎
timeElapsed += Time.deltaTime;
if (timeElapsed > publishMessageFrequency)
{
cube.transform.rotation = Random.rotation;
// メッセージの生成 (2)
PosRotMsg cubePos = new PosRotMsg(
cube.transform.position.x,
cube.transform.position.y,
cube.transform.position.z,
cube.transform.rotation.x,
cube.transform.rotation.y,
cube.transform.rotation.z,
cube.transform.rotation.w
);
// パブリッシュ (3)
ros.Publish(topicName, cubePos);
timeElapsed = 0;
}
}
}
2. サブスクライブ
トピック「color」をサブスクライブし、GameObjectの色を変更するコードです。
・unity_scripts/RosSubscriberExample.cs
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
using RosColor = RosMessageTypes.UnityRoboticsDemo.UnityColorMsg;
// サブスクライブ
public class RosSubscriberExample : MonoBehaviour
{
ROSConnection ros; // ROSコネクション
public GameObject cube; // GameObject
// スタート時に呼ばれる
void Start()
{
// ROSコネクションの準備
ros = ROSConnection.GetOrCreateInstance();
// サブスクライブ時のコールバックの登録 (1)
ros.Subscribe<RosColor>("color", ColorChange);
}
// サブスクライブ時のコールバックの実装 (2)
void ColorChange(RosColor colorMessage)
{
// GameObjectの色の変更
cube.GetComponent<Renderer>().material.color = new Color32((byte)colorMessage.r, (byte)colorMessage.g, (byte)colorMessage.b, (byte)colorMessage.a);
}
}
3. サービス
サービス「obj_pose_srv」でリクエストを受信しレスポンスを返すコードです。
・unity_scripts/RosUnityServiceExample.cs
using RosMessageTypes.UnityRoboticsDemo;
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
using Unity.Robotics.ROSTCPConnector.ROSGeometry;
// サービス
public class RosUnityServiceExample : MonoBehaviour
{
ROSConnection ros; // ROSコネクション
string m_ServiceName = "obj_pose_srv"; // サービス名
// スタート時に呼ばれる
void Start()
{
// ROSコネクションの準備
ros = ROSConnection.GetOrCreateInstance();
// サービスのリクエスト受信時のコールバックの登録 (1)
ros.ImplementService<ObjectPoseServiceRequest, ObjectPoseServiceResponse>(m_ServiceName, GetObjectPose);
}
// サービスのリクエスト受信時のコールバックの実装 (2)
private ObjectPoseServiceResponse GetObjectPose(ObjectPoseServiceRequest request)
{
// レスポンスの生成
ObjectPoseServiceResponse objectPoseResponse = new ObjectPoseServiceResponse();
GameObject gameObject = GameObject.Find(request.object_name);
if (gameObject)
{
objectPoseResponse.object_pose.position = gameObject.transform.position.To<FLU>();
objectPoseResponse.object_pose.orientation = gameObject.transform.rotation.To<FLU>();
}
// レスポンスを返す
return objectPoseResponse;
}
}
4. サービス呼び出し
定期的にサービス「pos_srv」にリクエストし、行き先を取得して、GameObjectを移動させるコードです。
・unity_scripts/RosServiceCallExample.cs
using RosMessageTypes.UnityRoboticsDemo;
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
// サービス呼び出し
public class RosServiceCallExample : MonoBehaviour
{
ROSConnection ros; // ROSコネクション
public string serviceName = "pos_srv"; // サービス名
public GameObject cube; // GameObject
public float delta = 1.0f; // 距離のしきい値
public float speed = 2.0f; // 速度
private Vector3 destination; // 行き先
float awaitingResponseUntilTimestamp = -1; // 待機時間
// スタート時に呼ばれる
void Start()
{
// ROSコネクションの準備
ros = ROSConnection.GetOrCreateInstance();
// サービスのレスポンス受信時のコールバック (1)
ros.RegisterRosService<PositionServiceRequest, PositionServiceResponse>(serviceName);
// 行き先の準備
destination = cube.transform.position;
}
// フレーム毎に呼ばれる
private void Update()
{
// GameObjectの位置を行き先(destination)に近づける
float step = speed * Time.deltaTime;
cube.transform.position = Vector3.MoveTowards(cube.transform.position, destination, step);
// 現在位置と行き先が近い時
if (Vector3.Distance(cube.transform.position, destination) < delta && Time.time > awaitingResponseUntilTimestamp)
{
// メッセージの生成 (2)
PosRotMsg cubePos = new PosRotMsg(
cube.transform.position.x,
cube.transform.position.y,
cube.transform.position.z,
cube.transform.rotation.x,
cube.transform.rotation.y,
cube.transform.rotation.z,
cube.transform.rotation.w
);
// リクエストの送信 (3)
PositionServiceRequest positionServiceRequest = new PositionServiceRequest(cubePos);
ros.SendServiceMessage<PositionServiceResponse>(serviceName, positionServiceRequest, Callback_Destination);
// 待機時間の更新
awaitingResponseUntilTimestamp = Time.time + 1.0f;
}
}
// サービスのレスポンス受信時のコールバックの実装 (4)
void Callback_Destination(PositionServiceResponse response)
{
// 行き先の更新
awaitingResponseUntilTimestamp = -1;
destination = new Vector3(response.output.pos_x, response.output.pos_y, response.output.pos_z);
}
}
5. 参考
この記事が気に入ったらサポートをしてみませんか?