Unitree Go1


History

(과거)

기존 Jetson XGA에 ROS2 Humble이 설치되어있고 Raspi에는 ROS1 Melodic이 설치되어있었음

→ ROS버전이 맞지 않음

따라서 Jetson에 ROS1 Neotic을 설치하여 Jetson ↔ Raspi간 ROS 버전을 일치시킴

(현재)

문제는 XGA에서 ROS로 Raspi에게 이동명령을 내려도 로봇이 움직이지 않음

확인해보니 Go1을 움직이기 위해서는 unitree에서 제공하는 SDK를 XGA에 설치해서 unitree에서 제공하는 명령어로만 동작함

프로젝트 목표

OpenVLA 모델을 선정하여 Go1 로봇개에 VLA모델을 적용한다.

그리고 “이리와”(사람을 인식해서 따라오기) 명령어를 사용자가 음성으로 입력하면 동작하도록하는 서비스를 적용시켜야 한다.

Go1 스펙

아키텍처

  • Raspberry Pi: 메인 컨트롤러(IP: 192.168.12.1, 192.168.123.161) Ros1 Melodic
  • Nano1: 헤드 카메라 처리 (IP: 192.168.123.13)
  • Nano2: 사이드 카메라 처리 (IP: 192.168.123.14)
  • Nano3(Main): AI 및 바닥 카메라 처리 (IP: 192.168.123.15)
  • MCU(Microcontroller Unit): 모터(정밀) 제어PC IP: 192.168.123.10

센서 시스템

  • 5개의 스테레오 카메라
    • 총 10개의 카메라(헤드 2개, 측면 오,왼 각 2개씩 총 4개, 바닥 아래, 위에 각 2개씩 총 4개)

통신 계층

  • 실시간 UDP 통신

Jetson XGA 스펙

Jetson AGX Orin Developer Kit

Arcitecture: aarch64

CPU: 12 core / 12 thread Cortex-A78AE @ 2.2 GHz

GPU: Ampere 2048 CUDA cores + 64 Tensor Cores

RAM: 64 GB LPDDR5

OS: Jetpack 6.2.1 (Ubuntu 22.04 LTS, Kernel 5.15)

Storage: 64 GB eMMC

Swap: 31GB

ROS1 neotic installed

AI Model: OpenVLA

https://www.jetson-ai-lab.com/openvla.html?utm_source=chatgpt.com

PC ↔ Go1 제어방식

두 가지 제어 레벨을 제공

  • High-level control
    • Go1 Mode: Sport Mode
    • 보행, 속도, 턴 등 “행동 단위”의 명령
    • UDP(192.168.123.161:8082)로 직접 전송
    • 예: example_walk
    Example_walk.py (PC) -> Raspi(Controller) -> MCU -> 모터
  • Low-level control
    • 모터 각 관절을 직접 토크/속도/위치로 제어
    • MCU(192.168.123.10:8007)로 직접 전송
    • 예: example_position, example_torque, example_velocity
    Example_position.py (PC) -> MCU -> 모터

두 가지 통신 방식 제공

  • UDP 통신
  • ROS기반 LCM 통신

1. SDK 방식(UDP)

Python/C++ SDK (PC) → UDP 통신 → Raspi → MCU → 모터
  • LCM 서버 필요 없음
  • ROS 필요 없음

2. ROS 방식(LCM서버 사용)

ROS Node (PC) → LCM 메시지 → sdk_lcm_server → UDP 통신 → Raspi → MCU → Motor
  • LCM(Lightweight Communications and Marshalling) 사용 이유
    • ROS1은 Linux 시스템에서 실행되므로 정확한 타이밍에 메시지가 전달된다는 보장이 없음
    • 제어 명령이 지연되면 로봇이 넘어질 위험
    • LCM은 지연편차(jitter)가 매우 낮고 UDP 기반으로 실시간 통신 가능
  • LCM 서버 실행 명령어(High-level)
    $ roslaunch unitree_legged_real real.launch ctrl_level:=highlevel
    • HighCmd 기반 LCM 메시지를 UDP로 변환해 Go1에 전송
    • ROS 노드는 /go1/HighCmd 토픽을 LCM으로 publish
  • LCM 서버 실행 명령어(Low-level)
    roslaunch unitree_legged_real real.launch ctrl_level:=lowlevel
    • LowCmd 기반 LCM 메시지를 UDP로 변환
    • ROS에서 관절 토크/속도/위치를 직접 제어 가능

Toy Project

1. PC에서 SDK를 사용하여 Go1 제어

git clone https://github.com/unitreerobotics/unitree_legged_sdk.git
  • Build
$ cd unitree_legged_sdk/
$ mkdir build
$ cd build/
$ cmake ..
$ make -j$(nproc)
  • 빌드가 완료되면 example_walk가 생긴다.
  • 아래 명령어를 실행하면 로봇이 앞으로 간다.
cd /home/{user_name}/unitree_legged_sdk/build
sudo ./example_walk

2. PC에서 Ros를 사용하여 Go1 제어

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
git clone https://github.com/unitreerobotics/unitree_legged_sdk.git
git clone https://github.com/unitreerobotics/unitree_ros_to_real.git
cd ..
catkin_make
  • Catkin
    • ROS패키지를 실행 가능한 상태로 만들어주는 자돵화 시스템으로 Linux/C++ 프로젝트를 자동으로 빌드하기 위해 ROS 전용 CMake도구를 묶어놓은 것.
  • LCM 서버 실행
roslaunch unitree_legged_real real.launch ctrl_level:=highlevel
  • ROS로 걷는 명령어 실행
$ rosrun unitree_legged_real ros_example_walk
  • ROS Run
    • 패키지 안의 하나의 노드를 바로 실행할 때 사용
  • ROS launch
    • launch 파일(.launch) 을 읽어서 여러 노드를 한 번에 실행

VLA

  • Model: NaVILA(Legged Robot Vision-Language-Action Model for Navigation)
    • Navigation + Vision Language Action
    • 2024. 12. 5 출간

제어

터미널 하나를 열어서 Xavier에서 Roscore를 실행한다.

Xavier가 Ros Master.

그리고 터미널 하나를 더열어서 아래 명령어를 입력해준다.

$ rosrun unitree_legged_real twist_sub

그리고 난 후에 다시 터미널 하나를 더 열어서 토픽값을 날리면 unitree go 가 움직인다.

jet@ubuntu:~$ rostopic pub /cmd_vel geometry_msgs/Twist "linear:
>   x: 0.0
>   y: 0.0
>   z: 0.0
> angular:
>   x: 0.0
>   y: 0.0
>   z: 0.3" -r 10

프론트 카메라는 Nano와 연결되어있다.

카메라를 보기 위해서 아래 명령어를 치면 에러가난다.

unitree@unitree-desktop:~/Unitree/sdk/UnitreeCameraSdk/bins$ ./example_getRawFrame 

(example_getRawFrame:8788): GStreamer-CRITICAL **: 00:08:21.192: 
Trying to dispose element pipeline0, but it is in PAUSED instead of the NULL state.
You need to explicitly set elements to the NULL state before
dropping the final reference, to allow them to clean up.
This problem may also be caused by a refcounting bug in the
application or some element.

[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (886) open OpenCV | GStreamer warning: unable to start pipeline

(example_getRawFrame:8788): GStreamer-CRITICAL **: 00:08:21.192: 
Trying to dispose element videoconvert0, but it is in PLAYING instead of the NULL state.
You need to explicitly set elements to the NULL state before
dropping the final reference, to allow them to clean up.
This problem may also be caused by a refcounting bug in the
application or some element.

[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created

(example_getRawFrame:8788): GStreamer-CRITICAL **: 00:08:21.192: 
Trying to dispose element appsink0, but it is in READY instead of the NULL state.
You need to explicitly set elements to the NULL state before
dropping the final reference, to allow them to clean up.
This problem may also be caused by a refcounting bug in the
application or some element.


(example_getRawFrame:8788): GStreamer-CRITICAL **: 00:08:21.192: gst_element_post_message: assertion 'GST_IS_ELEMENT (element)' failed

에러가 나는 이유는 go1이 켜질때 autostart의 항목이 이미 카메라 스트림을 점유하여 라즈베리파이에 쏘고 있기 때문이다.

이를 사용하기 위해서는 autostart되는 부분의 카메라 이미지를 스트리밍하는 아이피주소를 변경해주면된다.

unitree@unitree-desktop:~/Unitree/autostart/camerarosnode/cameraRosNode$ ls
build  calib.HrC6RP  devel  kill.sh  patch  src  startNode.sh
unitree@unitree-desktop:~/Unitree/autostart/camerarosnode/cameraRosNode$ sudo vim startNode.sh

그 다음

cd ~/Unitree/autostart/camerarosnode/cameraRosNode/src/unitree_camera/config/
sudo vim stereo_camera_config.yaml