ROS

Ros2 to Unity(TCP)

luke12 2022. 7. 6. 00:14

이번에 알아볼 예시는 유니티 공식 깃허브에서 제공해주는 Unity TCP connector이다. Unity와 ROS2를 TCP통신을 통해 연결해준다.

ROS Unity 통신 방법

사용법

로스 설정

1. unity에서 프로젝트 만들기(unity_ros2)

2. 로스 환경 구현

만든 유니티 패키지 안에 로스 워크스페이스 만들기(ros2_ws), 로스 워크스페이스 안에 src만들기

3. src에 unity tcp 통신 툴 들고오기

터미널로 src까지 들어가서 아래의 코드 입력

git clone -b "main-ros2" --single-branch https://github.com/Unity-Technologies/ROS-TCP-Endpoint.git

4. 빌드하기

2번 source를 해주어야한다고함(첫 번째는 빌드가 사용할 환경을 설정하고 두 번째는 새로 빌드된 패키지를 환경에 추가)

source install/setup.bash
colcon build
source install/setup.bash

5. 로스 열기

먼저 로스가 열려있어야 tcp통신을 통해서 유니티로 받아올수있기때문에 아래의 코드를 입력해주어야함. (launch에 들어가야할듯)

ip주소는 우분투에서 hostname -I, 맥에서 ipconfig getifaddr en0을 통해 알 수 있다.

ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=<your IP address>

유니티 설정

1.패키지 가져오기

window→Package Manager→ 아래의 코드넣기 → ADD

https://github.com/Unity-Technologies/ROS-TCP-Connector.git?path=/com.unity.robotics.ros-tcp-connector

상단에 Robotics 메뉴가 추가된것을 볼 수 있음

2. 로스 세팅

Robotics→ROS Settings→ ROS2로 변경

예제 실행 및 분석

인터페이스 가져오기

1.예제 초기 설정

  • Unity-Robotics-Hub 깃 클론
git clone https://github.com/Unity-Technologies/Unity-Robotics-Hub.git
  • 패키지 가져오기

Unity-Robotics-Hub파일→tutorials파일→ ros_unity_integration파일 →ros2_packages파일을 내가 아까 만든 로스 워크스페이스 src에 복사하기

아래의 명령어로 빌드

colcon build
source install/setup.bash

2. 로스 인터페이스(msg, srv) c#으로 바인딩

유니티 메뉴 바에 Robotics→ Generate ROS Messages…

가져온 패키지의 ros_packages/unity_robotics_demo_msgs를 ROS message path의 경로로 지정

아래의 사진처럼 msg와 srv 빌드

유니티에서 Assets/RosMessages/UnityRoboticsDemo/msg와 Assets/RosMessages/UnityRoboticsDemo/srv가 생성된 것을 알 수 있다.

Publisher

Unity-Robotics-Hub에 tutorials/ros_unity_integration/unity_scripts/RosPublisherExample.cs의 파일을 unity asset에 드레그엔 드롭

  • 큐브(cube)와 평면(plane) 만들기

큐브 위치를 평면보다 위로 올린다.

  • game object만들기

큐브만드는 방식에서 create Empty를 통해 빈 game object를 만들수있다.

  • 스트립트 넣기

RosPublisherExample를 GameObject에 드레그엔 드롭으로 놓고 cube도 내부에 드래그엔 드롭으로 넣는다.

  • 작동

재생을 누르면 아래의 사진처럼 정상적으로 작동하면서 랜덤하게 위치가 변경된다.

  • 터미널에서 퍼플리쉬한 값 보기
source install/setup.bash
ros2 topic echo pos_rot
  • RosPublisherExample.cs코드
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
using RosMessageTypes.UnityRoboticsDemo;

/// <summary>
///
/// </summary>
public class RosPublisherExample : MonoBehaviour
{
    ROSConnection ros;
    public string topicName = "pos_rot";

    // The game object
    public GameObject cube;
    // Publish the cube's position and rotation every N seconds
    public float publishMessageFrequency = 0.5f;

    // Used to determine how much time has elapsed since the last message was published
    private float timeElapsed;

    void Start()
    {
        // start the ROS connection
        ros = ROSConnection.GetOrCreateInstance();
        ros.RegisterPublisher<PosRotMsg>(topicName);
    }

    private void Update()
    {
        timeElapsed += Time.deltaTime;

        if (timeElapsed > publishMessageFrequency)
        {
            cube.transform.rotation = Random.rotation;

            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
            );

            // Finally send the message to server_endpoint.py running in ROS
            ros.Publish(topicName, cubePos);

            timeElapsed = 0;
        }
    }
}

Subscriber

Unity-Robotics-Hub에 tutorials/ros_unity_integration/unity_scripts/RosSubscriberExample.cs의 코드를 유니티 asset에 드래그엔 드롭

빈 GameObject에 RosSubscriberExample 스크립트 드래그 엔 드롭

  • 터미널에 로스 스트라이브 명령어 보내기

아래의 명령어를 터미널로 보낼때마다 유니티 큐브의 색상이 변경되는 것을 볼 수 있다.

ros2 run unity_robotics_demo color_publisher
  • RosSubscriberExample.cs코드
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
using RosColor = RosMessageTypes.UnityRoboticsDemo.UnityColorMsg;

public class RosSubscriberExample : MonoBehaviour
{
    public GameObject cube;

    void Start()
    {
        ROSConnection.GetOrCreateInstance().Subscribe<RosColor>("color", ColorChange);
    }

    void ColorChange(RosColor colorMessage)
    {
        cube.GetComponent<Renderer>().material.color = new Color32((byte)colorMessage.r, (byte)colorMessage.g, (byte)colorMessage.b, (byte)colorMessage.a);
    }
}
  • color_publisher.py코드
import random
import rclpy

from rclpy.node import Node

from unity_robotics_demo_msgs.msg import UnityColor


class ColorPublisher(Node):

    def __init__(self):
        super().__init__('color_publisher')
        self.publisher_ = self.create_publisher(UnityColor, 'color', 10)
        timer_period = 0.5  # seconds
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.i = 0
        self.do_publish()

    def do_publish(self):
        if self.i == 0:
            color = UnityColor()
            color.r = random.randint(0, 255)
            color.g = random.randint(0, 255)
            color.b = random.randint(0, 255)
            color.a = 1
            self.get_logger().info(f'Publishing: {color}')
            self.publisher_.publish(color)
            
        self.i += 1
        
    def timer_callback(self):
        quit()     


def main(args=None):
    rclpy.init(args=args)

    color_pub = ColorPublisher()

    while rclpy.ok():
        rclpy.spin_once(color_pub)

    #color_pub.destroy_node()
    #rclpy.shutdown()


if __name__ == '__main__':
    main()

'ROS' 카테고리의 다른 글

Unity urdf import  (0) 2022.07.11
Robotics-Nav2-SLAM[ROS2-Unity]  (1) 2022.07.09
Ros2 to Unity(rclcs)  (0) 2022.07.04
[ROS2] 토픽, 서비스, 액션 및 각각 인터페이스 비교표  (0) 2022.06.20
[ROS2] 인터페이스  (0) 2022.06.20