소프트웨어 스택

블록코딩(Blockly/Entry 호환) → Python 자동 생성 → ROS2 토픽 → BLDC 제어
Cite as: mecha4wd software v26.06a · wiki/software

1. 레이어 구조 — 한 화면에

L7 UIBlockly 웹 에디터 (Chromium 110+, 7세그)
L6 CodeGenBlock-to-Python Transpiler (Blockly API)
L5 RuntimePython asyncio 스케줄러 (50Hz tick)
L4 PerceptionPi Camera v3 + VL53L0X ×4 + BNO055
L3 InferenceONNX Runtime (RKNN NPU optional) — RL 정책
L2 ROS2cyclonedds · 4 node (cam, imu, policy, motor)
L1 MCUPico 2 — 1 kHz BLDC PWM + WS2812 ring control
L0 HW4 BLDC + rubber tires + 3S LiPo + Pi Camera v3

2. ROS2 토픽 흐름

                                 ┌───────────────┐
[BT keyboard / RC RX] ──Twist──►│ /cmd_vel_in   │
                                 └────┬──────────┘
                                      │
                              ┌───────▼──────────┐
                              │ /cmd_vel_priority │  ← block_orchestrator merges sources
                              └───────┬──────────┘
                                      │
                  ┌───────▼────────────▼──────────────┐
                  │                                      │
              ┌───▼────────┐                ┌─────────▼────────┐
              │ block_node  │                │ policy_node      │
              │ (Blockly    │                │ ONNX 50Hz       │
              │  exec loop) │                └─────────┬────────┘
              └────┬────────┘                          │
                   │ Twist / Toggle                     │
                   └────────────┬──────────────────────┘
                                │
                       ┌────────▼────────┐
                       │ /motor_targets    │  Float32[4]
                       └────────┬────────┘
                                │
                       ┌────────▼────────┐
                       │ controller_node  │ (motor PID + safety)
                       └────────┬────────┘
                                │ USB-CDC
                          [Pico 2 firmware]
                                │ PWM ×4
                       ┌────────▼────────┐
                       │ 4 BLDC + tires    │
                       └──────────────────┘

[sensors]
[Pi Camera v3] ──Image──► /camera/image_raw ──► perception_node ────► /detections
[BNO055 IMU]   ──Imu──► /imu/data    ────► state_estimator ────► /odom
[VL53L0X ×4]   ──Range──► /scan (LaserScan) ──► costmap_node

3. Blockly → Python 자동 생성 코드 예

학생이 블록 코딩으로 구성

[Start]
  [Forever]
    [If distance < 30 cm]
      [Stop]   [Wait 1 sec]   [Turn left 90°]    [Wait 1 sec]
    [Else]
      [Forward at 0.4 m/s]

Python 코드 자동 생성

# Auto-generated from Blockly XML
from mecha4wd import robot, sensors, lcd
import asyncio

async def main():
    await robot.start()
    while True:
        d = sensors.tof_front.distance_cm()
        if d is not None and d < 30:
            await robot.stop()
            await asyncio.sleep(1.0)
            await robot.rotate_degrees(-90)
            await asyncio.sleep(1.0)
        else:
            await robot.go_forward_at(0.4)
        await asyncio.sleep(0.05)   # 20 Hz sensing tick

asyncio.run(main())

4. 의존성 — install on Rock 5C

# Debian 12 on Radxa Rock 5C Lite 8GB
sudo apt update && sudo apt upgrade -y

# ROS2 Humble + cyclonedds
sudo apt install -y software-properties-common curl
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/keys/ros-keyring.gpg -o /usr/share/keyrings/ros-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/ros-keyring.gpg] http://packages.ros.org/ros2/ubuntu bookworm main" | sudo tee /etc/apt/sources.list.d/ros2.list
sudo apt update
sudo apt install -y ros-humble-desktop ros-humble-ros-base python3-colcon-common-extensions
sudo apt install -y ros-humble-rmw-cyclonedds-cpp
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp

# Python AI / block / perception deps
pip install --break-system-packages \
    onnxruntime==1.18.0 \
    rknn-toolkit2 \
    pyserial numpy ultralytics==8.0.0 \
    rpi_ws281x adafruit-circuitpython-bno055 adafruit-circuitpython-vl53l0x

# Pi Camera v3 (CSI)
sudo apt install -y libcamera-apps ros-humble-camera-info-manager

5. Pico 2 펌웨어 — BLDC + WS2812 control

// Pico 2 SDK · USB-CDC → Rock 5C + I2C bridge
#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include "hardware/i2c.h"

#define I2C_PORT i2c0
#define SDA_PIN 0
#define SCL_PIN 1

void motor_pwm(float duty[4]) {
    // 4 슬라이드 PWM out → DRV8871 IN1/IN2 4개
    for (int i = 0; i < 4; i++) {
        uint slice = pwm_gpio_to_slice_num(2 + i);
        uint chan  = pwm_gpio_to_channel(2 + i);
        pwm_set_chan_duty(chan, (uint16_t)(duty[i] * 65535));
    }
}

int main() {
    stdio_init_all();
    i2c_init(I2C_PORT, 400000);
    gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(SCL_PIN, GPIO_FUNC_I2C);

    for (int i = 0; i < 4; i++) {
        gpio_set_function(2 + i, GPIO_FUNC_PWM);
        pwm_set_wrap(pwm_gpio_to_slice_num(2 + i), 65535);
        pwm_set_enabled(pwm_gpio_to_slice_num(2 + i), true);
    }

    // USB-CDC로 4-float HM 패킷 수신:  "M 0.4 -0.4 0.0 0.0\n"
    char buf[64];
    int idx = 0;
    while (true) {
        int c = getchar_timeout_us(100);
        if (c == EOF) continue;
        if (c == '\n') {
            buf[idx] = 0;
            float a,b,c2,d;
            if (sscanf(buf, "M %f %f %f %f", &a, &b, &c2, &d) == 4) {
                float duty[4] = {a, b, c2, d};
                motor_pwm(duty);
            }
            idx = 0;
        } else if (idx < 63) {
            buf[idx++] = c;
        }
    }
}

6. 데이터 흐름 — 카메라 인지 → block input

Pi Camera v3 CSI → libcamera → Python ROS2 /camera/image_raw 발행. 학생은 block-coding에서 다음 두 가지 입력을 자연스럽게 사용:

  • YOLO detectionsensors.camera.detect("person") returns bool
  • Color detectionsensors.camera.find_color("red", tol=0.1) returns 좌표(x, y)
  • Infrared lanesensors.camera.lane_offset() returns lane center에서 deviation in cm

7. RL 학습 호환 — 등반할 부분

고급 사용자(고학년·연구)는 ONNX 기반 RL 정책으로 자동차의 ‘자율 lanekeeping’· ‘표지 sign 처리’ 같은 학습으로 확장 가능. 학습 시뮬은 Isaac Lab + rsl_rl로 PC에서 진행, export ONNX → Rock 5C에서 RKNN NPU 추론.

설계 차이 — 4WD는 4족 보행과 다른 두 가지 차이: (a) 동작 차원·선택지가 더 제한적 (직진·회전·정도), (b) 카메라·라인 인지 task가 훨씬 쉬움. 학급용 block-coding 핵심은 (a)에서 시작해 (b)·RL로 확장하는 자연스러운 progression.

다음 단계

mecha4wd v26.06a · 2026-08-21