본문 바로가기
Unreal Engine/언리얼-ROS-Physical 통합 프로젝트

[UnrealRobotics: SO-101] (3) Windows↔WSL2 TCP localhost 통신, rosbridge 설치 및 기동

by 테크앤아트 2026. 4. 8.
728x90
반응형

 

 

 


 

 

.wslconfig 미러링 모드 확인, 웹소켓 통신 확인

WSL2와 Windows11 사이의 네트워크를 확인하기 위해서 다음의 과정을 거친다.

 

 

PowerShell에서 파일 생성

@"
[wsl2]
networkingMode=mirrored
"@ | Out-File -FilePath $env:UserProfile\.wslconfig -Encoding ASCII

 

확인

Get-Content $env:UserProfile\.wslconfig

networkingMode=mirrored가 뜨면 성공이다

 

 

WSL2 터미널에서 포트 9090으로 테스트

python3 -m http.server 9090

 

PowerShell에서 확인

Test-NetConnection -ComputerName localhost -Port 9090

TcpTestSucceeded : True가 뜨면 성공

WSL 폴더 목록이 HTTP에도 나타나는 것을 볼 수 있다.

 

 


*rclUE 대신 rosbridge_suite + WebSocket C++를 써야 하는 이유

- rclUE의 한계 (Windows 환경): rclUE 플러그인은 내부적으로 ROS 2의 C++ 핵심 라이브러리(rclc 또는 rclcpp)를 언리얼 빌드 시스템(UBT)에 링크해야 합니다. 이를 Windows 언리얼에서 빌드하려면 ROS 2를 Windows용으로 네이티브 빌드해야 하는데, 이는 의존성 지옥(Dependency Hell)을 유발하며 굉장히 불안정합니다. (Opus가 Linux UE 빌드 전제라고 한 이유가 바로 이것입니다.)

- rosbridge_suite의 압도적 장점: 운영체제나 언어에 구애받지 않습니다. WSL2(ROS 2)에서는 단순히 rosbridge_server 노드만 띄워 포트(9090)만 열어두면 됩니다.

- 가장 깔끔한 선택 (UE C++ WebSocket 클라이언트): 서드파티 플러그인(ROSIntegration 등)을 쓰면 언리얼 5.4.4 같은 최신 엔진 업데이트 때마다 호환성이 깨져서 빌드 에러가 납니다. 첨부하신 SKILL.md에 나와 있듯, 언리얼 엔진에 내장된 자체 WebSockets 모듈과 Json 모듈을 사용해서 C++로 직접 브릿지 서브시스템(Subsystem)을 짜는 것이 가장 가볍고 유지보수하기 존 완벽한 형태입니다.

 

 


 

 

WSL2에 rosbridge_suite 세팅하기

rosbridge_suite 설치

sudo apt update
sudo apt install -y ros-humble-rosbridge-suite

 

완료 된 후 확인해본다.

ros2 pkg list | grep rosbridge

4가지가 잘 보이면 성공

 

 

rosbridge 실행

ros2 launch rosbridge_server rosbridge_websocket_launch.xml

WSL에서 실행하여 서버를 연다. 이 상태로 PowerShell로 간다.

 

 

Windows에서 접속 검증

Test-NetConnection -ComputerName localhost -Port 9090

TcpTestSucceeded: True가 나오면 성공

 

 

하지만 TCP 연결만 되는 것과 WebSocket 핸드셰이크가 되는 건 다른 문제라서, WebSocket 레벨로 한 번 더 확인

$ws = New-Object System.Net.WebSockets.ClientWebSocket
$cts = New-Object System.Threading.CancellationTokenSource
$ws.ConnectAsync("ws://localhost:9090", $cts.Token).Wait()
$ws.State

Open이 뜨면 성공

 

 

확인이 끝나면 닫는다.

$ws.CloseAsync([System.Net.WebSockets.WebSocketCloseStatus]::NormalClosure, "done", $cts.Token).Wait()

 

 

end-to-end 검증

TCP/WebSocket까진 됐으니, 실제로 ROS 토픽이 rosbridge를 통해 오가는지 보는 게 마지막 관문

 

rosbridge 내부 연결 확인 -> 내부 연결 실패, 외부 연결은 성공

첫 번째 터미널에서 rosbridge 켜고

ros2 launch rosbridge_server rosbridge_websocket_launch.xml

 

두 번째 터미널에서 쏴주고

source /opt/ros/humble/setup.bash
ros2 topic pub /test_topic std_msgs/String "data: 'hello from wsl2'" -r 1

 

세 번째 터미널에서 받고 있는지 확인

source /opt/ros/humble/setup.bash
ros2 topic echo /test_topic

 

 

*이 부분에서 세 번째 터미널에서 아무것도 뜨지 않아서 원인을 찾아 고쳐야 했다.

더보기

모든 WSL2 터미널에서 같은 ID 인지 확인

echo $ROS_DOMAIN_ID

-> 세 터미널 모두 빈 칸으로 같은 값이 나옴.

 

 

터미널3을 멈추고 리스트가 뜨는지 확인

source /opt/ros/humble/setup.bash
ros2 topic list

 -> /test_topic  리스트가 뜨지 않음.

 

 결론 : WSL2 + FastDDS의 멀티캐스트 디스커버리 실패

 

 

해결 방법으로도 시도해봤지만 여전히 실패.

1. 터미널 1 (rosbridge 재기동)

export ROS_LOCALHOST_ONLY=1
source /opt/ros/humble/setup.bash
ros2 launch rosbridge_server rosbridge_websocket_launch.xml

 

2. 터미널 2 (퍼블리셔)

export ROS_LOCALHOST_ONLY=1
source /opt/ros/humble/setup.bash
ros2 topic pub /test_topic std_msgs/String "data: 'hello from wsl2'" -r 1

 

3. 터미널 3 (echo)

export ROS_LOCALHOST_ONLY=1
source /opt/ros/humble/setup.bash
ros2 topic echo /test_topic

 

 

내부 rosbridge 소통은 실패. PowerShell 소켓이 바로 성공하여 이 문제는 넘어감.

 

 

rosbridge를 통해 Windows로 메시지 수신 확인 -> 외부 연결 성공

우리가 필요한 진짜 검증은 talker(정상 동작 확인된 노드)를 띄워놓고 PowerShell에서 WebSocket으로 받아보는 것.

 

  • WSL2 터미널 1 — rosbridge 가동
source /opt/ros/humble/setup.bash
ros2 launch rosbridge_server rosbridge_websocket_launch.xml

 

  • WSL2 터미널 2 — talker
source /opt/ros/humble/setup.bash
ros2 run demo_nodes_cpp talker

 

  • Windows PowerShell — /chatter 구독
$ws = New-Object System.Net.WebSockets.ClientWebSocket
$cts = New-Object System.Threading.CancellationTokenSource
$ws.ConnectAsync("ws://localhost:9090", $cts.Token).Wait()

$subscribeMsg = '{"op":"subscribe","topic":"/chatter","type":"std_msgs/String"}'
$bytes = [System.Text.Encoding]::UTF8.GetBytes($subscribeMsg)
$segment = New-Object System.ArraySegment[byte] -ArgumentList @(,$bytes)
$ws.SendAsync($segment, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $cts.Token).Wait()

$buffer = New-Object byte[] 4096
for ($i=0; $i -lt 5; $i++) {
    $seg = New-Object System.ArraySegment[byte] -ArgumentList @(,$buffer)
    $result = $ws.ReceiveAsync($seg, $cts.Token).Result
    $text = [System.Text.Encoding]::UTF8.GetString($buffer, 0, $result.Count)
    Write-Host "Received: $text"
}

$ws.CloseAsync([System.Net.WebSockets.WebSocketCloseStatus]::NormalClosure, "done", $cts.Token).Wait()

Received가 찍히면서 talker에서 퍼블리시한 토픽을 정상 수신하는 것을 확인했다.

 

퍼블리시 - 수신 과정
- WSL2 안의 ROS2 노드(talker)가 토픽을 퍼블리시
- rosbridge_server가 그걸 수신해서 JSON으로 변환
- WSL2 미러링 네트워크를 통해 9090 포트로 흘러나옴
- Windows의 PowerShell이 localhost:9090으로 WebSocket 연결
- rosbridge v2 프로토콜의 subscribe 요청을 보냄
- 응답으로 op:publish 메시지를 정상 수신

 

 


 

 

현재까지 완성된 부분을 정리하면,

 

  • ✅ Windows 11 + WSL2 + ROS2 Humble 환경 구성
  • ✅ .wslconfig 미러링 모드 설정 및 검증
  • ✅ Windows ↔ WSL2 TCP localhost 통신
  • ✅ rosbridge_suite 설치
  • ✅ rosbridge 기동 및 9090 포트 listen
  • ✅ Windows에서 WebSocket으로 rosbridge 연결
  • ✅ rosbridge v2 프로토콜로 토픽 구독
  • ✅ ROS 메시지가 JSON으로 Windows까지 전달

 

 

 


 

 

 

728x90
반응형