esp32 webteleop - dingdongdengdong/astra_ws GitHub Wiki

ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ:

  1. ESP32 (๋งˆ์ดํฌ๋กœ์ปจํŠธ๋กค๋Ÿฌ):

    • ๋กœ๋ด‡์˜ ๋ชจํ„ฐ, ์„ผ์„œ ๋“ฑ ํ•˜๋“œ์›จ์–ด๋ฅผ ์ง์ ‘ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
    • Wi-Fi๋ฅผ ํ†ตํ•ด ๋„คํŠธ์›Œํฌ์— ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.
    • ์›น์†Œ์ผ“(WebSocket) ๋˜๋Š” HTTP ์š”์ฒญ์„ ํ†ตํ•ด ์›น ์„œ๋ฒ„(๋˜๋Š” ์ง์ ‘ ์›น ๋ธŒ๋ผ์šฐ์ €)์™€ ํ†ต์‹ ํ•˜์—ฌ ์ œ์–ด ๋ช…๋ น์„ ์ˆ˜์‹ ํ•˜๊ณ , ๋กœ๋ด‡์˜ ์ƒํƒœ ์ •๋ณด(์„ผ์„œ ๊ฐ’ ๋“ฑ)๋ฅผ ์†ก์‹ ํ•ฉ๋‹ˆ๋‹ค.
    • ESP32์— ์—…๋กœ๋“œ๋œ ํŽŒ์›จ์–ด๋Š” ์ˆ˜์‹ ๋œ ๋ช…๋ น์„ ํ•ด์„ํ•˜์—ฌ ๋ชจํ„ฐ๋ฅผ ๊ตฌ๋™ํ•˜๊ฑฐ๋‚˜ LED๋ฅผ ์ œ์–ดํ•˜๋Š” ๋“ฑ์˜ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  2. ์›น ๋ธŒ๋ผ์šฐ์ € (์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค):

    • ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๋ด‡์„ ์›๊ฒฉ์œผ๋กœ ์กฐ์ข…ํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: non_ros_src/astra_teleop_web/src/astra_teleop_web/static/index.html)
    • HTML, CSS, JavaScript๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ, ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ(๋ฒ„ํŠผ ํด๋ฆญ, ์Šฌ๋ผ์ด๋” ์กฐ์ž‘ ๋“ฑ)์„ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.
    • JavaScript๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น์†Œ์ผ“์„ ํ†ตํ•ด ESP32 ๋˜๋Š” ์ค‘๊ฐ„ ์„œ๋ฒ„(ROS2 ๋…ธ๋“œ)๋กœ ์ œ์–ด ๋ช…๋ น์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
    • ํ•„์š”์— ๋”ฐ๋ผ ESP32๋กœ๋ถ€ํ„ฐ ๋กœ๋ด‡ ์ƒํƒœ ์ •๋ณด๋ฅผ ๋ฐ›์•„ ํ™”๋ฉด์— ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ˆ: ๋ฐฐํ„ฐ๋ฆฌ ์ž”๋Ÿ‰, ์„ผ์„œ ๊ฐ’, ์นด๋ฉ”๋ผ ์˜์ƒ ์ŠคํŠธ๋ฆฌ๋ฐ).
  3. teleop_web_node.py (ROS2 ์›น ์›๊ฒฉ ์กฐ์ข… ๋…ธ๋“œ):

    • ROS2 ์‹œ์Šคํ…œ๊ณผ ์›น ์ธํ„ฐํŽ˜์ด์Šค, ๊ทธ๋ฆฌ๊ณ  ESP32 ๊ฐ„์˜ ์ค‘๊ฐ„ ๋‹ค๋ฆฌ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋…ธ๋“œ๋Š” astra_controller ํŒจํ‚ค์ง€์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์›น ์„œ๋ฒ„ ์—ญํ• : ์›น ๋ธŒ๋ผ์šฐ์ €(ํด๋ผ์ด์–ธํŠธ)๋กœ๋ถ€ํ„ฐ ์›น์†Œ์ผ“ ๋˜๋Š” HTTP ์š”์ฒญ์„ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค. (Python์˜ aiohttp, flask, fastapi ๋“ฑ์˜ ์›น ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์›น์†Œ์ผ“ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ)
    • ROS2 ํผ๋ธ”๋ฆฌ์…”/์„œ๋ธŒ์Šคํฌ๋ผ์ด๋ฒ„:
      • ์›น ๋ธŒ๋ผ์šฐ์ €๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์ œ์–ด ๋ช…๋ น (์˜ˆ: ์ „์ง„, ํ›„์ง„, ์ขŒํšŒ์ „, ์šฐํšŒ์ „, ํŒ”/ํ—ค๋“œ ๊ฐ๋„ ์กฐ์ ˆ)์„ ROS2 ํ† ํ”ฝ (์˜ˆ: /cmd_vel, /joint_command)์œผ๋กœ ๋ฐœํ–‰ํ•˜์—ฌ ๋กœ๋ด‡์˜ ๋‹ค๋ฅธ ์ œ์–ด ๋…ธ๋“œ(head_node.py, arm_node.py ๋“ฑ)๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
      • ESP32์™€ ์ง์ ‘ ํ†ต์‹ ํ•˜๋Š” ๊ฒฝ์šฐ, ์ˆ˜์‹ ํ•œ ์›น ๋ช…๋ น์„ ESP32๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์‹œ๋ฆฌ์–ผ ๋˜๋Š” ๋„คํŠธ์›Œํฌ(TCP/IP, UDP, ์›น์†Œ์ผ“)๋ฅผ ํ†ตํ•ด ESP32๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
      • (์„ ํƒ ์‚ฌํ•ญ) ESP32๋กœ๋ถ€ํ„ฐ ๋กœ๋ด‡์˜ ์ƒํƒœ ์ •๋ณด๋ฅผ ๋ฐ›์•„ ์ด๋ฅผ ์›น ๋ธŒ๋ผ์šฐ์ €๋กœ ์ „์†กํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ROS2 ๋…ธ๋“œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํŠน์ • ํ† ํ”ฝ์œผ๋กœ ๋ฐœํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  4. (์„ ํƒ ์‚ฌํ•ญ) astra_teleop_web/src/astra_teleop_web/webserver.py ๋ฐ teleoperator.py:

    • non_ros_src์— ์žˆ๋Š” ์ด ์ฝ”๋“œ๋Š” ROS2์™€ ์ง์ ‘์ ์ธ ์—ฐ๊ด€์ด ์—†์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๋…๋ฆฝ์ ์ธ ์›น ๊ธฐ๋ฐ˜ ์›๊ฒฉ ์กฐ์ข… ์‹œ์Šคํ…œ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • webserver.py: Python ๊ธฐ๋ฐ˜์˜ ์›น ์„œ๋ฒ„(Flask, aiohttp ๋“ฑ)๋ฅผ ์‹คํ–‰ํ•˜์—ฌ static/index.html๊ณผ ๊ฐ™์€ ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•˜๊ณ , ์›น์†Œ์ผ“ ๋˜๋Š” HTTP ์—”๋“œํฌ์ธํŠธ๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ(์›น ๋ธŒ๋ผ์šฐ์ €, ESP32)์™€ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค.
    • teleoperator.py: ์›น ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๋ช…๋ น์„ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜, ESP32์™€ ์ง์ ‘ ํ†ต์‹ ํ•˜๋Š” ๋กœ์ง์„ ๋‹ด๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹  ๋ฐ ๊ตฌ๋™ ๋ฐฉ์‹ ๋‹ค์ด์–ด๊ทธ๋žจ:

์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

  • ์‹œ๋‚˜๋ฆฌ์˜ค 1: ์›น ๋ธŒ๋ผ์šฐ์ € -> teleop_web_node.py (ROS2) -> ๋กœ๋ด‡ ์ œ์–ด ๋…ธ๋“œ -> ESP32 (๋˜๋Š” ์ง์ ‘ ํ•˜๋“œ์›จ์–ด) (ROS2 ์‹œ์Šคํ…œ์— ํ†ตํ•ฉ๋œ ๊ฒฝ์šฐ)
  • ์‹œ๋‚˜๋ฆฌ์˜ค 2: ์›น ๋ธŒ๋ผ์šฐ์ € -> astra_teleop_web/webserver.py -> ESP32 (๋…๋ฆฝ์ ์ธ ์›น ์กฐ์ข… ์‹œ์Šคํ…œ์˜ ๊ฒฝ์šฐ, ๋˜๋Š” teleop_web_node.py๊ฐ€ ์ด ์—ญํ• ์„ ๊ฒธํ•˜๋Š” ๊ฒฝ์šฐ)
graph TD
    %% ์ „์ฒด ๊ทธ๋ž˜ํ”„ ๋ฐฉํ–ฅ ์„ค์ • (Set overall graph direction)
    direction TB

    %% ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ์„œ๋ธŒ๊ทธ๋ž˜ํ”„ (User Interface Subgraph)
    subgraph "์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค (User Interface)"
        direction LR
        A[์›น ๋ธŒ๋ผ์šฐ์ € - index.html, JS]
    end

    %% ๋„คํŠธ์›Œํฌ ํ†ต์‹  ์„œ๋ธŒ๊ทธ๋ž˜ํ”„ (Network Communication Subgraph)
    subgraph "๋„คํŠธ์›Œํฌ ํ†ต์‹  (Network Communication)"
        direction LR
        B[Websocket, HTTP]
    end

    %% ์„œ๋ฒ„ ๋ฐ ROS2 ํ†ตํ•ฉ ์„œ๋ธŒ๊ทธ๋ž˜ํ”„ (Server-Side/ROS2 Integration Subgraph)
    subgraph "์„œ๋ฒ„/ROS2 ํ†ตํ•ฉ (Server-Side/ROS2 Integration)"
        direction LR
        C[teleop_web_node.py - ROS2]
        D[webserver.py - Non-ROS]
    end

    %% ROS2 ์‹œ์Šคํ…œ ์„œ๋ธŒ๊ทธ๋ž˜ํ”„ (ROS2 System Subgraph)
    subgraph "ROS2 ์‹œ์Šคํ…œ (ROS2 System)"
        direction LR
        E[ROS2 ๋…ธ๋“œ - head_node, arm_node, base_node]
        F[ROS2 ํ† ํ”ฝ - cmd_vel, joint_command]
    end

    %% ๋งˆ์ดํฌ๋กœ์ปจํŠธ๋กค๋Ÿฌ ๋ฐ ํ•˜๋“œ์›จ์–ด ์„œ๋ธŒ๊ทธ๋ž˜ํ”„ (Microcontroller/Hardware Subgraph)
    subgraph "๋งˆ์ดํฌ๋กœ์ปจํŠธ๋กค๋Ÿฌ/ํ•˜๋“œ์›จ์–ด (Microcontroller/Hardware)"
        direction LR
        G[ESP32]
        H[๋กœ๋ด‡ ๋ชจํ„ฐ, ์„ผ์„œ]
    end

    %% ์—ฐ๊ฒฐ (Connections)
    A -->|"์ œ์–ด ๋ช…๋ น - JSON, Text"| B
    B -->|"์›น ๋ช…๋ น"| C
    B -->|"์›น ๋ช…๋ น"| D

    %% ์‹œ๋‚˜๋ฆฌ์˜ค 1: teleop_web_node.py๋ฅผ ํ†ตํ•œ ROS2 ํ†ตํ•ฉ (Scenario 1: ROS2 Integration via teleop_web_node.py)
    C -->|"ํŒŒ์‹ฑ๋œ ๋ช…๋ น"| F
    F --> E
    E -->|"์ €์ˆ˜์ค€ ๋ช…๋ น - Serial, CAN, I2C"| G
    %% ๋Œ€์ฒด ๊ฒฝ๋กœ: teleop_web_node์—์„œ ์ง์ ‘ ์ œ์–ด (Alternative path: Direct control from teleop_web_node)
    C -->|"์ง์ ‘ ๋ช…๋ น - Serial, TCP, UDP, Websocket"| G

    %% ์‹œ๋‚˜๋ฆฌ์˜ค 2: ๋…๋ฆฝ ์›น ์„œ๋ฒ„ (Scenario 2: Standalone Web Server)
    D -->|"ํŒŒ์‹ฑ๋œ ๋ช…๋ น - Serial, TCP, UDP, Websocket"| G

    %% ํ•˜๋“œ์›จ์–ด ์ƒํ˜ธ์ž‘์šฉ (Hardware Interactions)
    G -->|"์ œ์–ด ์‹ ํ˜ธ"| H
    H -->|"์„ผ์„œ ๋ฐ์ดํ„ฐ"| G
    G -->|"์ƒํƒœ, ์„ผ์„œ ๋ฐ์ดํ„ฐ - Websocket, TCP, UDP, Serial"| C
    G -->|"์ƒํƒœ, ์„ผ์„œ ๋ฐ์ดํ„ฐ - Websocket, HTTP"| D
    D -->|"์ƒํƒœ, ์„ผ์„œ ๋ฐ์ดํ„ฐ"| B
    C -->|"์ƒํƒœ, ์„ผ์„œ ๋ฐ์ดํ„ฐ - Websocket ๋˜๋Š” ROS2 ํ† ํ”ฝ"| B
    B -->|"ํ™”๋ฉด ์—…๋ฐ์ดํŠธ, ๋กœ๋ด‡ ์ƒํƒœ"| A

    %% ์Šคํƒ€์ผ๋ง (Styling)
    classDef ui fill:#D5F5E3,stroke:#28B463,stroke-width:2px
    classDef network fill:#E8DAEF,stroke:#8E44AD,stroke-width:2px
    classDef ros fill:#D6EAF8,stroke:#2E86C1,stroke-width:2px
    classDef hardware fill:#FDEDEC,stroke:#CB4335,stroke-width:2px
    classDef topic fill:#FEF9E7,stroke:#F39C12,stroke-width:1px

    class A ui
    class B network
    class C,E ros
    class D ros
    class F topic
    class G,H hardware
Loading

๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹  ๋ฐ ๊ตฌ๋™ ์ƒ์„ธ ์„ค๋ช…:

  1. ์‚ฌ์šฉ์ž ์ž…๋ ฅ (A -> B):

    • ์‚ฌ์šฉ์ž๋Š” ์›น ๋ธŒ๋ผ์šฐ์ €(A)์— ๋กœ๋“œ๋œ index.html ํŽ˜์ด์ง€์˜ ๋ฒ„ํŠผ(์ „์ง„, ํ›„์ง„, ํ—ค๋“œ ์˜ฌ๋ฆผ ๋“ฑ)์„ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ์Šฌ๋ผ์ด๋”๋ฅผ ์กฐ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
    • ๋ธŒ๋ผ์šฐ์ €์˜ JavaScript (index.js ๋“ฑ)๋Š” ์ด ์ž…๋ ฅ์„ ๊ฐ์ง€ํ•˜์—ฌ ํŠน์ • ํ˜•์‹(์ฃผ๋กœ JSON ๋˜๋Š” ๊ฐ„๋‹จํ•œ ๋ฌธ์ž์—ด)์˜ ์ œ์–ด ๋ฉ”์‹œ์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ์ƒ์„ฑ๋œ ๋ฉ”์‹œ์ง€๋Š” ์›น์†Œ์ผ“(์‹ค์‹œ๊ฐ„ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์— ์œ ๋ฆฌ) ๋˜๋Š” HTTP POST/GET ์š”์ฒญ(B)์„ ํ†ตํ•ด ์„œ๋ฒ„๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค. ์›น์†Œ์ผ“ ์ฃผ์†Œ๋‚˜ HTTP URL์€ JavaScript ์ฝ”๋“œ์— ๋ช…์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์„œ๋ฒ„์—์„œ์˜ ๋ช…๋ น ์ˆ˜์‹  ๋ฐ ์ฒ˜๋ฆฌ (B -> C ๋˜๋Š” B -> D):

    • teleop_web_node.py (C)์˜ ๊ฒฝ์šฐ (ROS2 ํ†ตํ•ฉ):
      • ์ด Python ์Šคํฌ๋ฆฝํŠธ๋Š” ์›น ์„œ๋ฒ„(์˜ˆ: aiohttp ์„œ๋ฒ„)๋ฅผ ๋‚ด์žฅํ•˜๊ณ  ์žˆ์–ด ํŠน์ • ํฌํŠธ์—์„œ ์›น์†Œ์ผ“ ์—ฐ๊ฒฐ ๋˜๋Š” HTTP ์š”์ฒญ์„ ์ˆ˜์‹  ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค.
      • ์›น ๋ธŒ๋ผ์šฐ์ €๋กœ๋ถ€ํ„ฐ ์ œ์–ด ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์œผ๋ฉด, ์ด๋ฅผ ํŒŒ์‹ฑํ•˜์—ฌ ๋กœ๋ด‡์˜ ์–ด๋–ค ๋ถ€๋ถ„์„ ์–ด๋–ป๊ฒŒ ์›€์ง์ผ์ง€์— ๋Œ€ํ•œ ์ •๋ณด(์˜ˆ: ์„ ์†๋„, ๊ฐ์†๋„, ๋ชฉํ‘œ ์กฐ์ธํŠธ ๊ฐ๋„)๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.
      • ์ถ”์ถœ๋œ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ ์ ˆํ•œ ROS2 ๋ฉ”์‹œ์ง€ ํƒ€์ž…(์˜ˆ: geometry_msgs/msg/Twist ๋˜๋Š” astra_controller_interfaces/msg/JointCommand)์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
      • ์ƒ์„ฑ๋œ ROS2 ๋ฉ”์‹œ์ง€๋ฅผ ํ•ด๋‹น ์ œ์–ด ํ† ํ”ฝ(F) (์˜ˆ: /cmd_vel ๋˜๋Š” /joint_command)์œผ๋กœ ๋ฐœํ–‰(publish)ํ•ฉ๋‹ˆ๋‹ค.
      • ๋งŒ์•ฝ ESP32์™€ ์ง์ ‘ ํ†ต์‹ ํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด (์˜ˆ: ํŠน์ • GPIO ํ•€ ์ œ์–ด), ROS2 ํ† ํ”ฝ ๋ฐœํ–‰ ๋Œ€์‹  ๋˜๋Š” ์ถ”๊ฐ€์ ์œผ๋กœ ESP32๋กœ ์ง์ ‘ ๋ช…๋ น์„ ์ „์†กํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. (์ด ๊ฒฝ์šฐ teleop_web_node.py๊ฐ€ ESP32์™€์˜ ํ†ต์‹  ๋กœ์ง๋„ ๋‹ด๋‹น)
    • astra_teleop_web/webserver.py (D)์˜ ๊ฒฝ์šฐ (๋…๋ฆฝ ์‹คํ–‰ ๋˜๋Š” teleop_web_node.py๊ฐ€ ์ด ์—ญํ•  ์ˆ˜ํ–‰):
      • ์ด Python ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์›น ์„œ๋ฒ„ ์—ญํ• ์„ ํ•˜๋ฉฐ ์›น ๋ธŒ๋ผ์šฐ์ €๋กœ๋ถ€ํ„ฐ ์ง์ ‘ ๋ช…๋ น์„ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.
      • ์ˆ˜์‹ ๋œ ๋ช…๋ น์„ ESP32๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœํ† ์ฝœ(์˜ˆ: ๊ฐ„๋‹จํ•œ ๋ฌธ์ž์—ด ๋ช…๋ น "FORWARD", "LEFT", ๋˜๋Š” JSON ๊ฐ์ฒด)๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
      • ๋ณ€ํ™˜๋œ ๋ช…๋ น์„ Wi-Fi๋ฅผ ํ†ตํ•ด ESP32(G)๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ํ†ต์‹  ๋ฐฉ์‹์€ ESP32 ํŽŒ์›จ์–ด์— ๋งž์ถฐ ์›น์†Œ์ผ“ ํด๋ผ์ด์–ธํŠธ, TCP ํด๋ผ์ด์–ธํŠธ, UDP ํŒจํ‚ท ๋“ฑ์œผ๋กœ ๊ตฌํ˜„๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ROS2 ์‹œ์Šคํ…œ ๋‚ด์—์„œ์˜ ์ œ์–ด (C -> F -> E -> G, ๋˜๋Š” C -> G):

    • teleop_web_node.py(C)๊ฐ€ ROS2 ํ† ํ”ฝ(F)์œผ๋กœ ๋ช…๋ น์„ ๋ฐœํ–‰ํ•˜๋ฉด, ํ•ด๋‹น ํ† ํ”ฝ์„ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” ๋กœ๋ด‡์˜ ์‹ค์ œ ์ œ์–ด ๋…ธ๋“œ๋“ค(E) (์˜ˆ: head_node.py, arm_node.py, base_node.py)์ด ์ด ๋ช…๋ น์„ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.
    • ๊ฐ ์ œ์–ด ๋…ธ๋“œ๋Š” ์ˆ˜์‹ ๋œ ๋ช…๋ น์— ๋”ฐ๋ผ ์ž์‹ ์˜ ๋‹ด๋‹น ๋ถ€๋ถ„(ํ—ค๋“œ, ํŒ”, ๋ฒ ์ด์Šค ๋“ฑ)์„ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด head_controller.py, arm_controller.py, base_controller.py ๋“ฑ์˜ ์ €์ˆ˜์ค€ ์ปจํŠธ๋กค๋Ÿฌ ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
    • ์ด ์ €์ˆ˜์ค€ ์ปจํŠธ๋กค๋Ÿฌ๋“ค์€ ์‹œ๋ฆฌ์–ผ, CAN, I2C ๋“ฑ์˜ ํ†ต์‹  ๋ฐฉ์‹์„ ํ†ตํ•ด ์‹ค์ œ ํ•˜๋“œ์›จ์–ด(๋ชจํ„ฐ ๋“œ๋ผ์ด๋ฒ„ ๋“ฑ) ๋˜๋Š” ESP32(G)์™€ ํ†ต์‹ ํ•˜์—ฌ ๋ช…๋ น์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
    • ๋งŒ์•ฝ teleop_web_node.py๊ฐ€ ESP32์™€ ์ง์ ‘ ํ†ต์‹ ํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ๋‹ค๋ฉด, ์ด ๋‹จ๊ณ„์—์„œ ๋ฐ”๋กœ ESP32๋กœ ๋ช…๋ น์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  4. ESP32์—์„œ์˜ ๋ช…๋ น ์‹คํ–‰ (G -> H):

    • ESP32(G)๋Š” Wi-Fi๋ฅผ ํ†ตํ•ด ์›น ์„œ๋ฒ„(teleop_web_node.py ๋˜๋Š” astra_teleop_web/webserver.py)๋กœ๋ถ€ํ„ฐ ์ œ์–ด ๋ช…๋ น์„ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.
    • ESP32์— ํ”„๋กœ๊ทธ๋ž˜๋ฐ๋œ ํŽŒ์›จ์–ด๋Š” ์ˆ˜์‹ ๋œ ๋ช…๋ น์„ ํ•ด์„ํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: "FORWARD" ๋ช…๋ น์„ ๋ฐ›์œผ๋ฉด ํŠน์ • GPIO ํ•€๋“ค์„ ์ œ์–ดํ•˜์—ฌ ๋ชจํ„ฐ ๋“œ๋ผ์ด๋ฒ„์— ์‹ ํ˜ธ๋ฅผ ๋ณด๋ƒ„).
    • ํ•ด์„๋œ ๋ช…๋ น์— ๋”ฐ๋ผ ์—ฐ๊ฒฐ๋œ ๋ชจํ„ฐ(H)๋ฅผ ๊ตฌ๋™์‹œํ‚ค๊ฑฐ๋‚˜, LED๋ฅผ ์ผœ๊ฑฐ๋‚˜, ๋‹ค๋ฅธ ์•ก์ถ”์—์ดํ„ฐ๋ฅผ ์ž‘๋™์‹œํ‚ต๋‹ˆ๋‹ค.
  5. ์ƒํƒœ ์ •๋ณด ์†ก์‹  (H -> G -> D/C -> B -> A) (์„ ํƒ ์‚ฌํ•ญ):

    • ๋กœ๋ด‡์˜ ์„ผ์„œ(H) (์˜ˆ: ๋ฐฐํ„ฐ๋ฆฌ ์ „์•• ์„ผ์„œ, ๊ฑฐ๋ฆฌ ์„ผ์„œ, ์—”์ฝ”๋”) ๊ฐ’์€ ESP32(G)์—์„œ ์ฝํž ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ESP32๋Š” ์ด ์ƒํƒœ ์ •๋ณด๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ๋˜๋Š” ์š”์ฒญ์— ๋”ฐ๋ผ Wi-Fi๋ฅผ ํ†ตํ•ด ์›น ์„œ๋ฒ„(D ๋˜๋Š” C)๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์›น ์„œ๋ฒ„(D ๋˜๋Š” C)๋Š” ์ˆ˜์‹ ๋œ ์ƒํƒœ ์ •๋ณด๋ฅผ ์›น์†Œ์ผ“์ด๋‚˜ HTTP ์‘๋‹ต์„ ํ†ตํ•ด ์›น ๋ธŒ๋ผ์šฐ์ €(A)๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
    • ์›น ๋ธŒ๋ผ์šฐ์ €์˜ JavaScript๋Š” ์ด ์ •๋ณด๋ฅผ ๋ฐ›์•„ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋กœ๋ด‡์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
    • teleop_web_node.py(C)์˜ ๊ฒฝ์šฐ, ESP32๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฅธ ROS2 ๋…ธ๋“œ์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํŠน์ • ROS2 ํ† ํ”ฝ์œผ๋กœ ๋ฐœํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹คํ–‰ ๋‹จ๊ณ„ (์ผ๋ฐ˜์ ์ธ ์‹œ๋‚˜๋ฆฌ์˜ค):

  1. ESP32 ์ค€๋น„:

    • ESP32์— Wi-Fi ์ ‘์† ์ •๋ณด(SSID, ๋น„๋ฐ€๋ฒˆํ˜ธ)์™€ ์›น ์„œ๋ฒ„ ์ฃผ์†Œ(IP, ํฌํŠธ)๋ฅผ ์„ค์ •ํ•˜๊ณ , ์ œ์–ด ๋ช…๋ น ์ˆ˜์‹  ๋ฐ ํ•˜๋“œ์›จ์–ด ์ œ์–ด ๋กœ์ง์ด ํฌํ•จ๋œ ํŽŒ์›จ์–ด๋ฅผ ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
    • ESP32๊ฐ€ ๋„คํŠธ์›Œํฌ์— ์—ฐ๊ฒฐ๋˜๊ณ  ์›น ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ช…๋ น์„ ๋ฐ›์„ ์ค€๋น„๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ์›น ์›๊ฒฉ ์กฐ์ข… ์„œ๋ฒ„ ์‹คํ–‰:

    • ROS2 ํ™˜๊ฒฝ:
      source /opt/ros/<your_ros_distro>/setup.bash
      source <path_to_your_astra_ws>/install/setup.bash
      ros2 run astra_controller teleop_web_node
      (ํ•„์š”์— ๋”ฐ๋ผ launch ํŒŒ์ผ์„ ํ†ตํ•ด ๊ด€๋ จ ๋…ธ๋“œ๋“ค๊ณผ ํ•จ๊ป˜ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ์˜ˆ: ros2 launch astra_controller start.launch.py)
    • ๋…๋ฆฝ ์‹คํ–‰ ํ™˜๊ฒฝ (Non-ROS, astra_teleop_web ์‚ฌ์šฉ ์‹œ):
      cd <path_to_your_astra_ws>/non_ros_src/astra_teleop_web/src/astra_teleop_web
      python webserver.py
      (์‹คํ–‰ ๋ช…๋ น์–ด๋Š” ํ•ด๋‹น ์Šคํฌ๋ฆฝํŠธ์˜ ๊ตฌํ˜„ ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)
    • ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋˜๋ฉด ํŠน์ • IP ์ฃผ์†Œ์™€ ํฌํŠธ์—์„œ ์›น ์š”์ฒญ์„ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. (ํ„ฐ๋ฏธ๋„ ๋กœ๊ทธ์—์„œ ์ฃผ์†Œ ํ™•์ธ)
  3. ์›น ๋ธŒ๋ผ์šฐ์ € ์ ‘์†:

    • PC ๋˜๋Š” ๋ชจ๋ฐ”์ผ ๊ธฐ๊ธฐ์˜ ์›น ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์—ด๊ณ , ์›น ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ์ฃผ์†Œ (์˜ˆ: http://<์„œ๋ฒ„_IP_์ฃผ์†Œ>:<ํฌํŠธ๋ฒˆํ˜ธ>, ์˜ˆ๋ฅผ ๋“ค์–ด http://192.168.1.100:8080)๋กœ ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.
    • index.html ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋˜๊ณ , ์‚ฌ์šฉ์ž๋Š” ํ™”๋ฉด์˜ ์ปจํŠธ๋กค์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ๋ด‡ ์กฐ์ข…์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ๊ธฐ์ˆ :

  • ESP32: Wi-Fi ํ†ต์‹ , GPIO ์ œ์–ด, ์„ผ์„œ ์ธํ„ฐํŽ˜์ด์Šค.
  • ์›น ๊ธฐ์ˆ : HTML, CSS, JavaScript (ํ”„๋ก ํŠธ์—”๋“œ UI).
  • ํ†ต์‹  ํ”„๋กœํ† ์ฝœ:
    • ์›น์†Œ์ผ“ (WebSockets): ์›น ๋ธŒ๋ผ์šฐ์ €์™€ ์„œ๋ฒ„ ๊ฐ„ ์‹ค์‹œ๊ฐ„ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์— ์ฃผ๋กœ ์‚ฌ์šฉ. ๋‚ฎ์€ ์ง€์—ฐ ์‹œ๊ฐ„.
    • HTTP (HyperText Transfer Protocol): ์š”์ฒญ-์‘๋‹ต ๊ธฐ๋ฐ˜ ํ†ต์‹ . ๊ฐ„๋‹จํ•œ ๋ช…๋ น ์ „์†ก์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Œ.
    • TCP/IP ๋˜๋Š” UDP: ์„œ๋ฒ„(Python ์Šคํฌ๋ฆฝํŠธ)์™€ ESP32 ๊ฐ„์˜ ์ง์ ‘์ ์ธ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Œ.
  • Python (์„œ๋ฒ„ ์‚ฌ์ด๋“œ):
    • ์›น ํ”„๋ ˆ์ž„์›Œํฌ: aiohttp (๋น„๋™๊ธฐ, teleop_web_node.py์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ์„ฑ ๋†’์Œ), Flask, FastAPI ๋“ฑ.
    • ์›น์†Œ์ผ“ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ: websockets, aiohttp-websockets ๋“ฑ.
    • ROS2 ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ: rclpy.
    • (ํ•„์š”์‹œ) ์‹œ๋ฆฌ์–ผ ํ†ต์‹  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ: pyserial.

์ด ๋‹ค์ด์–ด๊ทธ๋žจ๊ณผ ์„ค๋ช…์€ ESP32์™€ ์›น์„ ์‚ฌ์šฉํ•œ ์›๊ฒฉ ์กฐ์ข… ์‹œ์Šคํ…œ์˜ ์ผ๋ฐ˜์ ์ธ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์‹ค์ œ ๊ตฌํ˜„์€ ์ œ๊ณต๋œ ์ฝ”๋“œ์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๋‹ค์†Œ ์ฐจ์ด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, teleop_web_node.py์™€ astra_teleop_web ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์˜ Python ์Šคํฌ๋ฆฝํŠธ ๋ฐ HTML/JavaScript ํŒŒ์ผ๋“ค์˜ ๋‚ด์šฉ์„ ํ•จ๊ป˜ ์‚ดํŽด๋ณด์‹œ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ