이번에 알아볼 예시는 유니티 공식 깃허브에서 제공해주는 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 |