소속: 한양대학교 ERICA, 로봇공학과 — 팀 DRAFT 기간: 2023.10 – 2025.05 언어: 한국어 / English
AT-EX는 팀 DRAFT가 자체 설계·제작한 12 자유도(DoF) 하체형 휴머노이드 로봇으로, 본 레포지토리는 이 로봇을 강화학습으로 직접 제어하는 풀스택 파이프라인을 담고 있습니다. NVIDIA Isaac Sim 4.0 + Isaac Lab (OmniIsaacGymEnvs) 환경에서 PPO 기반 액터-크리틱 정책을 학습한 뒤, ROS2 파이프라인을 통해 학습된 정책을 실기(real robot)에서 그대로 추론·제어합니다.
- 시뮬레이션: Isaac Sim에서 4096개 환경 병렬 학습
- 정책: rl_games 기반 actor-critic MLP (400-200-100), 입력 45차원 / 출력 12차원
- 실기 통신: Python 추론 노드 → C++ UART 노드 → STM32 Nucleo-F7 ×2 → CAN → 모터
- 센서: EBIMU-9DOFV5 IMU (자세 추정), 모터 내장 엔코더 (관절 상태)
| 항목 | 다이어그램 |
|---|---|
| 소프트웨어 아키텍처 | ![]() |
| 전장 아키텍처 | ![]() |
| 하드웨어 구조 | ![]() |
| 역할 | 팀원 |
|---|---|
| ROS2 제어 파이프라인 / STM32 펌웨어 | 안의찬 (본 레포지토리 작성자) |
| 강화학습 (학습 환경·정책 설계) | 이기현 |
| 기구 설계 | 한희대, 이의택 |
| 전장 설계 | 유연철 |
| 항목 | 사양 |
|---|---|
| 로봇 명칭 | AT-EX |
| 형태 | 하체형 휴머노이드 (12 DoF, 다리당 6 DoF) |
| 고관절·무릎 모터 (관절 1–4) | CubeMars AK70-10 (±25 Nm 매핑) |
| 발목 모터 (관절 5–6) | Steadywin GIM8108-6 (±18.25 Nm 매핑) |
| 메인 컨트롤러 | STM32 Nucleo-F7 ×2 (좌/우 다리 분리 제어) |
| 통신 | 호스트 ↔ MCU: UART 1 Mbps / MCU ↔ 모터: CAN |
| IMU | E2BOX EBIMU-9DOFV5 (USB 시리얼) |
| 호스트 | Ubuntu + ROS2 (rclcpp / rclpy) |
capstone-design-2025/
├── ebimu_pkg/ # IMU 센서 ROS2 인터페이스 (Python)
├── hardware_package/ # 모터/MCU UART 통신 ROS2 노드 (C++)
└── isaac_sim_controller/ # RL 정책 추론 및 시뮬/실기 제어 (Python)
E2BOX EBIMU-9DOFV5 9축 IMU에서 USB 시리얼로 들어오는 자세 데이터를 ROS2 토픽으로 변환·전처리합니다.
| 파일 | 역할 |
|---|---|
ebimu_publisher.py |
/dev/ttyUSB_CP2102 (115200 bps) 시리얼 데이터를 그대로 ebimu_data 토픽(String)으로 발행. |
ebimu_subscriber.py |
원시 IMU 데이터를 파싱해 콘솔로 출력하는 디버그용 노드. |
ebimu_tuning_data_subscriber.py |
부팅 직후 첫 샘플을 초기 오프셋으로 잡고, 상대 roll/pitch/yaw, 각속도, up_proj·heading_proj(상체 직립도·목표 방향 정렬도) 등 RL 관측치에 직접 들어가는 값을 계산. |
/joint_command(JointState)를 STM32 Nucleo-F7 두 대에 분배해 UART로 송신하고, MCU가 회신하는 모터 상태를 /joint_states로 다시 합쳐 발행합니다.
| 파일 | 역할 |
|---|---|
src/joint_state_to_uart.cpp |
좌·우 다리에 각각 1개씩 띄우는 노드. JointState의 position/effort를 모터별 4바이트 패킷(헤더 0xFF + 모터수 + N×4B + 테일 0xFF 0xFC)으로 직렬화. 관절 1–4는 ±25 Nm, 5–6은 ±18.25 Nm 범위로 모터 종류에 따라 매핑 테이블을 분기. NaN position이 들어오면 토크 모드로 처리. 별도 스레드에서 회신 패킷을 읽어 `/joint_states_left |
src/multicast.cpp |
통합 토픽과 좌/우 분리 토픽을 잇는 라우터. /joint_command → 이름의 left_*/right_* 접두로 분리해 `/joint_command_left |
config/left_leg.yaml / config/right_leg.yaml |
다리별 노드 파라미터 (모터 6개, 토픽 prefix, MCU 디바이스 이름). |
config/reset_nucleo.sh |
부팅 시 OpenOCD로 ST-Link 시리얼 번호를 지정해 좌/우 Nucleo를 하드 리셋. |
launch/simple_control.launch.py |
Nucleo 두 대 리셋 → 1초 대기 → 좌·우 UART 노드 + 멀티캐스터를 한 번에 기동. |
펌웨어(STM32 측)는 별도 레포지토리에서 관리합니다 → Hanyangsaja/AT-EX_firmware
학습된 정책을 PyTorch로 로드해 실기/시뮬에 동일 인터페이스로 추론하는 핵심 패키지입니다. 추론 주기는 약 120 Hz (0.0083 s 타이머).
| 파일 | 역할 |
|---|---|
Capstone_Humanoid_Controller.py |
토크 모드 제어(초기 시도). 정책 출력(액션) × joint_gears ÷ torque_divisors 를 effort로 발행. |
Capstone_Humanoid_Controller_p.py |
포지션 모드 제어 (최종 채택본). 토크 모드는 호스트–MCU–모터 전체 루프의 제어 주기가 부족해 발산하기 쉬워, 액션 [-1, 1]을 각 관절의 허용 범위로 매핑한 뒤 1차 저역통과 필터로 부드럽게 추종. GUI에서 Base(현재 자세 → 0 rad 수렴), Torque ON/OFF, 높이/필터 슬라이더로 안전한 시작·정지 절차를 제공. |
두 노드 모두 ebimu_data와 /joint_states를 구독해 45차원 관측 텐서를 구성하고, runs/에 저장된 .pth 가중치를 Tkinter GUI에서 선택해 로드합니다.
| 파일 | 역할 |
|---|---|
Capstone_Humanoid_Isaac_Sim_Controller.py |
Isaac Sim 안의 로봇에 대해 동일 정책으로 토크 모드 제어. sensor_msgs/Imu, /joint_states_sim, WrenchStamped(/odom) 구독 후 /joint_command_sim 발행. sim-to-real 동치 검증용. |
Capstone_Humanoid_Isaac_Sim_Controller_p.py |
위의 포지션 모드 변형. 실기 _p 컨트롤러와 동일한 매핑/필터 로직을 사용. |
| 파일 | 역할 |
|---|---|
Humanoidtest.yaml |
Isaac Lab 태스크 설정. 4096 envs, 60 Hz 제어, episode 1000, 보상 항(headingWeight 0.5, upWeight 0.1, energyCost 0.05 등), PhysX GPU 파라미터. |
HumanoidtestPPO.yaml |
rl_games 기반 PPO 알고리즘 설정. MLP [400, 200, 100], ELU, learning_rate 5e-4, KL adaptive, mini-batch 32768, horizon 32. |
runs/Humanoidtest/ |
학습된 정책 가중치 (.pth). |
models/ |
다양한 물리 파라미터(마찰, 토크 한계, 댐핑, 시작 자세 등) 튜닝 실험 시 저장된 USD 환경 스냅샷. |
*.usd |
Isaac Sim 씬 파일 (학습용 / 평가용 / 의자 시나리오 등). |
코드의 클래스명은
A2CNetwork이지만, rl_games의 actor-critic 명명 관례를 그대로 사용한 것이며 실제 학습은 PPO로 진행했습니다. 학습 시도한 두 정책 중Humanoidtest(Locomotion)만 실기 검증을 마쳤고,Humanoidtestp(Walking)는 실기 적용까지 가지 못했습니다.
| 파일 | 역할 |
|---|---|
joint_command_publisher.py |
고정 effort를 일정 주기로 발행하는 단순 테스트 노드. |
joint_state_listener.py |
/joint_states를 콘솔로 모니터링. |
joints_publisher_gui.py |
PyQt5 슬라이더로 12개 관절의 effort를 수동 조작 (실기 + 시뮬 동시 발행). 안전을 위해 관절 한계치 도달 시 자동으로 명령을 0으로 리셋. |
joints_publisher_p_gui.py |
같은 GUI의 포지션 모드 버전. |
joints_subscriber_gui.py |
/joint_states_sim을 받아 matplotlib으로 실시간 플로팅. |
model_test.py |
고정 입력으로 정책 출력을 단독 검증하는 스크립트 (ROS 무관). |
plot/*.xml |
rqt_plot 프리셋 (커맨드↔상태, 조인트 상태, sim-to-real 비교). |
┌──────────────────────────────────────────────────────┐
│ Host PC (Ubuntu + ROS2) │
│ │
EBIMU IMU ──USB──┼─▶ ebimu_publisher ──/ebimu_data──┐ │
│ ▼ │
│ Capstone_Humanoid_Controller_p │
│ (PyTorch policy @120 Hz) │
│ │ │
│ /joint_states ◀──┐ ▼ /joint_command │
│ │ │
│ multicaster │
│ ▲ /joint_states_left|right│
│ /joint_command_left|right ▼ │
│ │
│ joint_state_to_uart (left) ─UART 1Mbps─┐ │
│ joint_state_to_uart (right) ─UART 1Mbps─┤ │
└─────────────────────────────────────────────────┼────┘
│
┌───────────────────────────┴┐
│ STM32 Nucleo-F7 ×2 (펌웨어) │
└───────────────┬────────────┘
│ CAN
▼
CubeMars AK70-10 ×8 + Steadywin GIM8108-6 ×4
학습/시뮬 환경에서는 *_Isaac_Sim_Controller(_p)가 위 그림의 EBIMU + UART + 모터를 Isaac Sim의 IMU/JointState 토픽으로 대체해 동일 정책을 그대로 검증합니다.
팀 내 다른 구성원의 기여(강화학습, 기구·전장 설계)와 별개로, 본 레포지토리에 포함된 ROS2 파이프라인과 펌웨어는 본인이 담당했습니다.
- ROS2 제어 파이프라인 설계 및 구현
- 추론 노드 ↔ 멀티캐스터 ↔ UART 노드의 토픽 토폴로지 설계
joint_state_to_uart의 모터별 위치/토크 매핑 테이블 분기 및 패킷 프로토콜 구현 (Boost.Asio 기반 송수신)message_filtersApproximateTime으로 좌/우 다리 상태 동기화- 학습 정책의 45차원 관측 정합(roll/pitch/yaw 오프셋 보정,
up_proj·heading_proj계산)을 실기 IMU 파이프라인에서 동일하게 재현
- 포지션 모드 컨트롤러 설계
- 토크 모드의 제어 주기 한계를 식별하고, 액션-각도 매핑 + α-필터 기반 포지션 추종 구조로 전환
- GUI에
Base자세 수렴, 토크 ON/OFF, 높이/필터 슬라이더를 추가해 안전한 기동/정지 절차 확립
- STM32 펌웨어 개발 (AT-EX_firmware)
- 호스트 UART 패킷 ↔ 다리당 6모터 CAN 명령 변환
- 모터별 위치/토크 스케일링과 안전 한계 처리
# capstone_ws/src/ 아래에 본 레포를 둔 상태에서
cd ~/capstone_ws
colcon build --symlink-install
source install/setup.bash# 1) Nucleo 리셋 + UART 노드 + 멀티캐스터
ros2 launch hardware_package simple_control.launch.py
# 2) IMU 퍼블리셔
ros2 run ebimu_pkg ebimu_publisher
# 3) RL 정책 추론 + GUI
ros2 run isaac_sim_controller drl_ros_controller_pGUI에서 Locomotion 모델을 선택 → Load Model → Torque ON → Start 순으로 기동합니다.
ros2 run isaac_sim_controller drl_ros_controller_p_simIsaac Sim의 USD 씬(capston_rl_test_p.usd 등)을 로드한 상태에서 동일한 GUI/모델 흐름으로 검증합니다.
- 펌웨어 (STM32CubeIDE): https://github.com/Hanyangsaja/AT-EX_firmware
각 패키지(hardware_package)는 Apache-2.0를 따르며, 그 외 디렉토리는 상위 README의 지침을 따릅니다.



