VnRobo
Về chúng tôiBảng giáBlogLiên hệ
🇺🇸ENĐăng nhậpDùng thử miễn phí
🇺🇸EN
VnRobo logo

Hạ tầng AI cho robot công nghiệp thế hệ mới.

Sản phẩm

  • Tính năng
  • Bảng giá
  • Kiến thức
  • Dịch vụ

Công ty

  • Về chúng tôi
  • Blog
  • Liên hệ

Pháp lý

  • Chính sách bảo mật
  • Điều khoản sử dụng

© 2026 VnRobo. Bảo lưu mọi quyền.

Được tạo với♥tại Việt Nam
VnRobo
Về chúng tôiBảng giáBlogLiên hệ
🇺🇸ENĐăng nhậpDùng thử miễn phí
🇺🇸EN
  1. Trang chủ
  2. Blog
  3. PlotJuggler + G1: Cài đặt ROS2 và kết nối live
humanoidplotjugglerros2unitree-g1cycloneddsdebugginghumanoidtutorial

PlotJuggler + G1: Cài đặt ROS2 và kết nối live

Cài ros-humble-plotjuggler-ros, cấu hình CycloneDDS cho Unitree G1, rồi stream live /lowstate và /sportmodestate trong 15 phút.

Nguyễn Anh Tuấn15 tháng 6, 202614 phút đọc
PlotJuggler + G1: Cài đặt ROS2 và kết nối live

Khi robot Unitree G1 của bạn làm điều gì đó kỳ lạ — chân trái run run lúc đứng yên, IMU liên tục báo roll lệch 2 độ, hay một khớp khuỷu tay có torque cao bất thường — câu hỏi đầu tiên luôn là: dữ liệu thật sự đang nói gì? PlotJuggler là công cụ trả lời câu hỏi đó nhanh nhất. Bài này hướng dẫn bạn đi từ terminal trống đến việc stream live 23 khớp cùng IMU của G1 vào PlotJuggler, tất cả trong vòng 15 phút.

Roadmap series — 5 bài

# Bài Nội dung
1 Cài đặt & kết nối live (bài này) Cài PlotJuggler, CycloneDDS, subscribe /lowstate và /sportmodestate
2 Layout 23 khớp + ghi MCAP Nhóm panel theo limb, đặt layout template, ghi file .mcap chuẩn
3 Debug IMU, Quaternion & FFT Phân tích tư thế, phát hiện rung động cơ học qua FFT
4 Lua Transforms — custom metric Viết script Lua tính power per joint, slip index, derived signal
5 ZMQ Publisher + video overlay sim2real Cầu nối ZMQ từ MuJoCo sang PlotJuggler, overlay camera feed, so sánh sim2real

Tại sao PlotJuggler thay vì RViz hay rqt_plot?

rqt_plot chỉ vẽ được 4–5 topic đồng thời, lag rõ ràng, và không thể phân tích dữ liệu đã ghi sau này. RViz giỏi về không gian 3D nhưng hoàn toàn không phải công cụ time-series. ros2 topic echo đúng là... đọc không nổi khi có 29 trường motor đang thay đổi 500 lần mỗi giây.

PlotJuggler giải quyết ba vấn đề cùng lúc:

  1. Layout linh hoạt — kéo thả field vào 10+ panel đồng thời, đồng bộ trục thời gian, zoom bất cứ đâu
  2. Live streaming và internal buffer — vừa xem real-time vừa giữ buffer 60 giây để scrub lại
  3. Mở file .mcap trực tiếp — không cần ros2 bag play, file tự chứa schema

Với G1, bạn sẽ cần cả ba. Live streaming để xem robot đang làm gì ngay lúc chạy thử, internal buffer để tua lại đúng khoảnh khắc robot vấp ngã, và file .mcap để so sánh nhiều run với nhau sau buổi test.

Yêu cầu trước khi bắt đầu

  • Ubuntu 22.04 trên workstation của bạn
  • ROS2 Humble, Iron, hoặc Jazzy đã cài đặt và source
  • Unitree G1 đang bật, kết nối Ethernet trực tiếp với PC bằng cáp
  • Biết dùng terminal: ip addr, ros2 topic list, ping

Bài này dùng ROS2 Humble cho tất cả lệnh mẫu. Thay humble thành iron hoặc jazzy nếu bạn dùng distro mới hơn — mọi thứ khác giữ nguyên.


Bước 1: Cài đặt PlotJuggler và plugin ROS2

Một lệnh duy nhất cài cả PlotJuggler core lẫn toàn bộ ROS2 plugin (Topic Subscriber, Bag Reader, và Re-publisher):

sudo apt install ros-humble-plotjuggler-ros

Iron/Jazzy: Thay humble bằng iron hoặc jazzy. Tên package giữ nguyên plotjuggler-ros.

Kiểm tra cài đặt thành công:

source /opt/ros/humble/setup.bash
ros2 run plotjuggler plotjuggler --version
# Kết quả: PlotJuggler version 3.x.x

Package ros-humble-plotjuggler-ros gộp sẵn tất cả plugin — bạn không cần cài riêng plotjuggler và plotjuggler-ros-plugins như hướng dẫn build-from-source cũ.

Tổng quan các nguồn dữ liệu PlotJuggler hỗ trợ: file (CSV, MCAP, ULog), live stream (ROS2, ZMQ, MQTT, WebSocket) — nguồn: repo PlotJuggler/PlotJuggler
Tổng quan các nguồn dữ liệu PlotJuggler hỗ trợ: file (CSV, MCAP, ULog), live stream (ROS2, ZMQ, MQTT, WebSocket) — nguồn: repo PlotJuggler/PlotJuggler


Bước 2: Kết nối vật lý và cấu hình mạng

G1 giao tiếp với PC qua Ethernet. Robot có IP cố định 192.168.123.10 — PC của bạn phải ở cùng subnet 192.168.123.x.

Xác định tên interface Ethernet:

ip addr show
# hoặc: ifconfig

Tìm interface có trạng thái UP kết nối cổng Ethernet (thường là eth0, enp3s0, eno1, enx...). Ghi nhớ tên này — bạn sẽ dùng lại ở bước CycloneDDS.

Đặt IP tĩnh qua nmcli (terminal):

# Thay "Wired connection 1" bằng tên kết nối và "enp3s0" bằng interface thực tế
sudo nmcli connection modify "Wired connection 1" \
    ipv4.method manual \
    ipv4.addresses "192.168.123.99/24" \
    ipv4.gateway "" \
    connection.autoconnect yes
sudo nmcli connection up "Wired connection 1"

Hoặc qua Ubuntu Network Settings (GUI):

  • Mở Settings → Network → Cổng Ethernet kết nối G1 → cài đặt (⚙)
  • IPv4 Method: Manual
  • Address: 192.168.123.99, Netmask: 255.255.255.0, Gateway: (để trống)
  • Nhấn Apply → tắt/bật connection

Kiểm tra kết nối:

ping -c 4 192.168.123.10
# Bình thường: 64 bytes from 192.168.123.10: icmp_seq=1 ttl=64 time=0.4 ms
# Nếu "Request timeout": cáp chưa cắm, hoặc IP chưa đặt đúng

Bước 3: Cấu hình CycloneDDS — bước không được bỏ qua

Đây là điểm gây nhầm lẫn nhiều nhất. ROS2 Humble mặc định dùng FastDDS làm middleware, nhưng Unitree G1 chạy CycloneDDS. Nếu hai bên không đồng nhất DDS implementation, ros2 topic list sẽ trống hoàn toàn dù G1 đang broadcast dữ liệu.

Cài CycloneDDS middleware cho ROS2 Humble:

sudo apt install ros-humble-rmw-cyclonedds-cpp

Tạo file cấu hình ~/cyclonedds_g1.xml:

<CycloneDDS>
  <Domain>
    <General>
      <Interfaces>
        <!-- Thay "enp3s0" bằng tên interface Ethernet của bạn kết nối G1 -->
        <NetworkInterface name="enp3s0" priority="default" multicast="default" />
      </Interfaces>
    </General>
  </Domain>
</CycloneDDS>

Quan trọng: Điền đúng tên interface vật lý (ví dụ enp3s0, eth0, eno1). Không dùng lo (loopback) trừ khi đang test local với Mujoco simulator. CycloneDDS cần biết đúng interface để gửi multicast discovery đến đúng subnet.

Export biến môi trường:

export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI=file:///home/$USER/cyclonedds_g1.xml

Tự động load khi mở terminal mới:

echo 'export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp' >> ~/.bashrc
echo "export CYCLONEDDS_URI=file:///home/$USER/cyclonedds_g1.xml" >> ~/.bashrc
source ~/.bashrc

Mẹo cho người dùng nhiều robot: Nếu workstation của bạn cũng kết nối các robot khác không dùng CycloneDDS, đừng hardcode vào .bashrc. Tạo alias thay thế:

# Thêm vào ~/.bashrc
alias ros-g1='export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp && \
    export CYCLONEDDS_URI=file:///home/$USER/cyclonedds_g1.xml && \
    echo "CycloneDDS G1 mode active"'

Gõ ros-g1 trước khi làm việc với G1. Terminal khác không bị ảnh hưởng.


Bước 4: Xác nhận kết nối ROS2 với G1

Với G1 đang bật và CycloneDDS đã cấu hình:

source /opt/ros/humble/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI=file:///home/$USER/cyclonedds_g1.xml

ros2 topic list

Bạn sẽ thấy danh sách topic, trong đó có:

/lowstate
/sportmodestate
/lowcmd
/wirelesscontroller
/utlidar/cloud
/lf/lowstate
/lf/sportmodestate

Prefix /lf/ là "low frequency" — cùng dữ liệu nhưng publish ở tần số thấp hơn, phù hợp khi bạn không cần full 500 Hz.

Kiểm tra nhanh dữ liệu IMU:

# Xem roll/pitch/yaw thời gian thực
ros2 topic echo /lowstate --field imu_state.rpy

# Kiểm tra tần số publish
ros2 topic hz /lowstate
# G1 publish /lowstate ở 500 Hz (2 ms/lần)
ros2 topic hz /sportmodestate
# /sportmodestate thường ở 50–100 Hz

Nếu ros2 topic list vẫn trống hoặc chỉ có /parameter_events:

Vấn đề Cách kiểm tra
Network vật lý ping 192.168.123.10 → nếu fail, vấn đề ở cáp/IP
Tên interface sai ip addr show enp3s0 → thay đúng tên vào XML
CycloneDDS chưa load echo $RMW_IMPLEMENTATION → phải là rmw_cyclonedds_cpp
Firewall chặn sudo ufw disable rồi thử lại (tái bật sau: sudo ufw enable)
G1 chưa bật hẳn Chờ ~30s sau khi bật, hoặc kiểm tra đèn LED trạng thái

Bước 5: Launch PlotJuggler và subscribe topics G1

ros2 run plotjuggler plotjuggler

Giao diện PlotJuggler mở ra với ba vùng chính:

  • Trái — Signal List: Tất cả topic fields xuất hiện ở đây sau khi subscribe
  • Giữa — Plot Area: Kéo thả field vào đây để vẽ đồ thị
  • Phải — Time Panel: Điều chỉnh cửa sổ thời gian hiển thị (cuộn, zoom)

Quy trình subscribe topics G1:

  1. Nhấn nút Streaming trên toolbar (biểu tượng sóng radio) — hoặc vào menu Streaming → Start
  2. Dropdown xuất hiện → chọn "ROS2 Topic Subscriber"
  3. Nhấn nút Start màu xanh lá
  4. Dialog hiện ra với danh sách tất cả topic đang broadcast trong mạng ROS2
  5. Tìm và tích chọn:
    • ☑ /lowstate
    • ☑ /sportmodestate
  6. Nhấn OK

Sau 2–3 giây, Signal List bên trái expand thành cây nhiều cấp. Cấu trúc điển hình của /lowstate:

/lowstate
  ├─ imu_state
  │    ├─ quaternion[0]   ← w (phần thực)
  │    ├─ quaternion[1]   ← x
  │    ├─ quaternion[2]   ← y
  │    ├─ quaternion[3]   ← z
  │    ├─ rpy[0]          ← roll (rad)
  │    ├─ rpy[1]          ← pitch (rad)
  │    ├─ rpy[2]          ← yaw (rad)
  │    ├─ accelerometer[0..2]   ← m/s²
  │    └─ gyroscope[0..2]       ← rad/s
  └─ motor_state[0..28]
       ├─ q               ← góc khớp (rad)
       ├─ dq              ← vận tốc khớp (rad/s)
       ├─ tau_est         ← torque ước tính (Nm)
       └─ temperature     ← nhiệt độ motor (°C)

Vẽ plot đầu tiên:

Kéo /lowstate/imu_state/rpy[0] (roll) từ Signal List thả vào vùng plot trống. Đường roll xuất hiện và cập nhật real-time. Kéo thêm rpy[1] (pitch) vào cùng panel bằng cách giữ Ctrl khi thả — hai đường vẽ chung trục để so sánh.


Bước 6: Giải phẫu /lowstate và /sportmodestate

/lowstate — dữ liệu thô từ firmware

Topic /lowstate publish ở 500 Hz (2 ms/lần), dùng message type unitree_hg::msg::LowState — đặc thù cho humanoid Unitree, khác với unitree_go::msg::LowState của Go2/B2/B1 (quadruped).

Các field quan trọng:

Field Kiểu Ý nghĩa
motor_state[0..28] array[29] 29 motor của G1
motor_state[i].q float32 Góc khớp (radian)
motor_state[i].dq float32 Vận tốc khớp (rad/s)
motor_state[i].tau_est float32 Torque ước tính (Nm)
motor_state[i].temperature float32 Nhiệt độ motor (°C)
imu_state.quaternion[4] float32[4] Tư thế (w, x, y, z)
imu_state.rpy[3] float32[3] Roll, Pitch, Yaw (radian)
imu_state.accelerometer[3] float32[3] Gia tốc pelvis (m/s²)
imu_state.gyroscope[3] float32[3] Vận tốc góc pelvis (rad/s)
foot_force[4] int16[4] Lực tiếp xúc chân (đơn vị tương đối)

23 khớp body vs 29 motor — sự khác biệt:

G1 có tổng cộng 29 motor:

  • Chân (Legs): 12 motor (6 mỗi chân — hip roll, hip pitch, hip yaw, knee, ankle pitch, ankle roll)
  • Eo (Waist): 3 motor (yaw, roll, pitch)
  • Tay (Arms): 14 motor (7 mỗi tay — shoulder pitch, shoulder roll, shoulder yaw, elbow, wrist roll, wrist pitch, gripper nếu có DEX3)

Khi stream vào PlotJuggler, bạn thấy motor_state[0] đến motor_state[28]. Mapping index → tên khớp cụ thể có trong tài liệu chính thức của unitree_ros2 — bài 2 của series sẽ đi sâu vào việc gán nhãn từng motor.

/sportmodestate — trạng thái high-level

Topic /sportmodestate publish ở 50–100 Hz và chứa dữ liệu sau khi G1's onboard controller đã xử lý và tích hợp:

Field Ý nghĩa
position[3] Vị trí ước tính (x, y, z) trong world frame (m)
velocity[3] Vận tốc tịnh tiến (m/s)
yaw_speed Vận tốc xoay quanh trục z (rad/s)
gait_type Loại dáng đi (integer enum)
foot_force[4] Lực chân ước tính
mode Chế độ hoạt động của controller
body_height Chiều cao thân ước tính (m)

Khi nào dùng topic nào:

  • Dùng /lowstate khi debug phần cứng và firmware: motor nào bị quá nhiệt? IMU có đọc đúng không? Khớp nào có rung động bất thường?
  • Dùng /sportmodestate khi debug hành vi cấp cao: robot có đang di chuyển đúng hướng không? Vận tốc thực có khớp command không? Body height có ổn định không?

PlotJuggler Record vs ros2 bag record — khi nào dùng gì?

Câu hỏi thực tế mà nhiều người nhầm lẫn khi bắt đầu.

PlotJuggler internal buffer

Khi streaming trong PlotJuggler, tool tự động giữ một buffer trong RAM (mặc định 60 giây, có thể điều chỉnh). Bạn có thể pause streaming và scrub lại timeline để xem đúng khoảnh khắc robot gặp sự cố.

Giới hạn: Buffer mất hoàn toàn khi đóng PlotJuggler. Không lưu ra file.

Dùng khi: Debug nhanh trong buổi test, muốn xem ngay vấn đề đang xảy ra, session ngắn dưới vài phút.

ros2 bag record với định dạng MCAP

# Cài MCAP storage plugin cho Humble (Iron/Jazzy đã có sẵn)
sudo apt install ros-humble-rosbag2-storage-mcap

# Ghi /lowstate và /sportmodestate ra file MCAP
ros2 bag record -s mcap -o g1_session_$(date +%Y%m%d_%H%M) /lowstate /sportmodestate
# Ctrl+C để dừng ghi

File .mcap tự chứa message schema bên trong — PlotJuggler mở trực tiếp mà không cần cài package message type:

# Mở file MCAP để phân tích offline
ros2 run plotjuggler plotjuggler -d g1_session_20260615_1430/*.mcap
# hoặc: File → Load Data File trong giao diện PlotJuggler

Humble mặc định ghi .db3 (SQLite3): Format này không tự chứa schema, khiến PlotJuggler gặp khó khăn khi parse một số message type của Unitree. Luôn thêm flag -s mcap khi record trên Humble.

Bảng so sánh nhanh

Tiêu chí PlotJuggler Live Buffer ros2 bag record (MCAP)
Xem ngay real-time ✅ ❌ (cần play lại sau)
Lưu vĩnh viễn ❌ (mất khi đóng) ✅
Chia sẻ với đồng nghiệp ❌ ✅
Session dài (>5 phút) ❌ (RAM giới hạn) ✅ (disk)
Mở lại bất cứ lúc nào ❌ ✅
Cần ros2 bag play để xem ❌ (stream trực tiếp) ❌ (PlotJuggler mở .mcap trực tiếp)

Chiến lược thực tế tốt nhất: Bật ros2 bag record chạy nền ngay khi bắt đầu test robot, đồng thời dùng PlotJuggler để monitor live. Nếu robot làm điều gì lạ, bạn đã có file để mở lại và phân tích chi tiết.

# Terminal 1: Ghi bag nền
ros2 bag record -s mcap -o session_$(date +%Y%m%d_%H%M) /lowstate /sportmodestate &

# Terminal 2: Monitor live
ros2 run plotjuggler plotjuggler

Checklist 15 phút — từ đầu đến stream live

# === TERMINAL 1: Setup môi trường ===
source /opt/ros/humble/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI=file:///home/$USER/cyclonedds_g1.xml

# Verify kết nối vật lý
ping -c 3 192.168.123.10

# Verify ROS2 thấy G1
ros2 topic list | grep -E "lowstate|sportmode"
# Kỳ vọng: /lowstate và /sportmodestate xuất hiện

# Kiểm tra tần số
ros2 topic hz /lowstate
# Kỳ vọng: ~500 Hz

# === TERMINAL 2: (Tùy chọn) Ghi bag nền ===
source /opt/ros/humble/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI=file:///home/$USER/cyclonedds_g1.xml
ros2 bag record -s mcap -o session_$(date +%Y%m%d_%H%M) /lowstate /sportmodestate

# === TERMINAL 3: Launch PlotJuggler ===
source /opt/ros/humble/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI=file:///home/$USER/cyclonedds_g1.xml
ros2 run plotjuggler plotjuggler
# Trong PlotJuggler: Streaming → Start → ROS2 Topic Subscriber → tick /lowstate + /sportmodestate → OK

Kết luận

Sau bài này, bạn đã có pipeline hoàn chỉnh để xem dữ liệu live từ Unitree G1:

  • PlotJuggler cài trong một lệnh apt install ros-humble-plotjuggler-ros
  • CycloneDDS cấu hình đúng interface Ethernet — bước không được bỏ qua
  • /lowstate (500 Hz, 29 motor + IMU pelvis) và /sportmodestate (50 Hz, state ước tính high-level) đều đang stream vào PlotJuggler
  • Biết khi nào dùng live buffer và khi nào record .mcap

Bài tiếp theo trong series sẽ đi sâu vào việc tổ chức layout 23 khớp — cách nhóm panel theo từng limb (left leg, right leg, left arm, right arm, waist), đặt layout template để tái dùng giữa các session, và workflow ghi .mcap chuẩn để phân tích sim2real sau này.


Bài viết liên quan

  • Bài 2: Layout 23 khớp + ghi MCAP — Tổ chức panel theo limb, template layout, ghi .mcap chuẩn cho phân tích offline
  • Bài 3: Debug IMU, Quaternion và FFT rung động — Phân tích tư thế từ quaternion, dùng FFT phát hiện rung động cơ học
  • Debug MPC/WBID G1 bằng PlotJuggler trong Mujoco — Series anh em: PlotJuggler với G1 trong môi trường simulation MuJoCo
NT

Nguyễn Anh Tuấn

Robotics & AI Engineer. Building VnRobo — sharing knowledge about robot learning, VLA models, and automation.

Khám phá VnRobo

Fleet MonitoringROS 2 IntegrationAMR Solutions
plotjuggler-g1-debug — Phần 1/3
Visualize 23 khớp G1: MCAP bag replay & Layout XML →

Bài viết liên quan

NEWTutorial
IMU Debug G1: Quaternion → Euler + FFT phân tích rung
plotjugglerunitree-g1imuPhần 3
humanoid

IMU Debug G1: Quaternion → Euler + FFT phân tích rung

Dùng ToolboxQuaternion chuyển quaternion IMU G1 sang roll/pitch/yaw, áp dụng ToolboxFFT trên gyroscope để phát hiện tần số cộng hưởng cơ học, và Moving Average làm mượt foot_force khi phân tích gait.

15/6/202618 phút đọc
NT
NEWTutorial
Checklist sim2real cho controller G1
unitree-g1mujocosim2realPhần 6
humanoid

Checklist sim2real cho controller G1

Checklist chuyển controller G1 từ MuJoCo sang robot thật: DDS, ROS_DOMAIN_ID, OpenWBT, log .pkl, PlotJuggler và torque guard.

13/6/202615 phút đọc
NT
NEWTutorial
Visualize 23 khớp G1: MCAP bag replay & Layout XML
plotjugglerunitree-g1mcapPhần 2
ai

Visualize 23 khớp G1: MCAP bag replay & Layout XML

Dùng plugin DataLoadMCAP trong PlotJuggler để mở file .mcap từ G1, tạo grid multi-panel xem đồng thời q/dq/tau của tất cả 23 khớp, và lưu layout XML để tái dùng qua nhiều session debug.

15/6/202613 phút đọc
NT
VnRobo logo

Hạ tầng AI cho robot công nghiệp thế hệ mới.

Sản phẩm

  • Tính năng
  • Bảng giá
  • Kiến thức
  • Dịch vụ

Công ty

  • Về chúng tôi
  • Blog
  • Liên hệ

Pháp lý

  • Chính sách bảo mật
  • Điều khoản sử dụng

© 2026 VnRobo. Bảo lưu mọi quyền.

Được tạo với♥tại Việt Nam