Raspberry Pi 4B + ROS2 Jazzy ๊ธฐ๋ฐ์ ์์จ ์ถ์ ๋ก๋ด.
LiDAR + ์นด๋ฉ๋ผ๋ก ๋์(๊ธฐ๋ณธ: ์ฌ๋)์ ์ธ์ยท์ถ์ ํ๋ฉฐ, SLAM ๋งต ๊ธฐ๋ฐ ๋์ ๊ฐ์ฒด ํ์ง ๋ฐ ์์จ ํ์์ ์ง์ํ๋ค.
[IMX219 ์นด๋ฉ๋ผ] [RPLIDAR A1/A2]
| |
| /motherv2/image_raw | /scan
v v
[detection_node] [slam_toolbox]โโโ /map (OccupancyGrid)
| | |
| /motherv2/detections | map TF |
v v |
[follower_node]โโโโโโโ[slam_localization_node]
| |
| /motherv2/cmd_motor | /motherv2/object_estimates
v |
[serial_node]โโโ STM32 v
[web_node] :8080
|
[explore_node] (์์จ ํ์)
- libcamera ๋ฐฑ์๋๋ก IMX219 ์นด๋ฉ๋ผ๋ฅผ ์ง์ ์ ์ด
BGR888ํฌ๋งท์ผ๋ก/motherv2/image_rawํผ๋ธ๋ฆฌ์- ๊ธฐ๋ณธ ํด์๋: 640ร360 @ 30fps
- ํต์ฌ ๊ตฌ์กฐ: Detection + Tracking ๋ถ๋ฆฌ
- ์ถ๋ก (MediaPipe): ๋ณ๋ ์ค๋ ๋์์ 0.5์ด๋ง๋ค ์คํ โ CPU ๋ถํ ์ ํ
- ํธ๋ํน(MOSSE): ๋ฉ์ธ ์ฝ๋ฐฑ์์ ๋งค ํ๋ ์(~30fps) ์คํ โ ์๋ต์ฑ ์ ์ง
- ํ์ง ๋์: ์ฌ๋ (COCO class 0).
target_class_idํ๋ผ๋ฏธํฐ๋ก ๋ณ๊ฒฝ ๊ฐ๋ฅ
- LiDAR ๊น์ด์ ์นด๋ฉ๋ผ ํ์ง ๊ฒฐ๊ณผ๋ฅผ ์ตํฉํด ๊ฐ์ฒด์ SLAM ๋งต ์ขํ๋ฅผ ์ถ์
- 3๋จ๊ณ ์ถ์
- ์นด๋ฉ๋ผ + LiDAR: bbox ์ค์ฌ ๋ฐฉํฅ์ผ๋ก LiDAR ๊ฑฐ๋ฆฌ ์ธก์ โ ๋งต ์ขํ ๋ณํ
- LiDAR only (์นด๋ฉ๋ผ FOV ์ดํ ์): ์ ์ ๋งต๊ณผ ํ์ฌ ์ค์บ์ ๋น๊ตํด ๋์ ๊ฐ์ฒด(์ฌ๋) ํ์ง
- Dead-reckoning: ๊ฐ์ฒด ์์ ์์ค ์ ๋ง์ง๋ง ์๋๋ฒกํฐ๋ก 2์ด๊ฐ ์์น ์์ธก
- SLAM ๋ชจ๋
mapping: slam_toolbox๋ก ๋งต ์์ฑ ์ค. LiDAR ๋ฐฉํฅ ๊ธฐ๋ฐ ์ถ์ tracking: ์ ์ฅ๋ ๋งต ์ค๋ ์ท๊ณผ ํ์ฌ ์ค์บ์ ์ฐจ๋ถ์ผ๋ก ๋์ ๊ฐ์ฒด ์ถ์ (๋ ์ ํ)
/motherv2/slam_mode = "explore"์์ ์ ์๋ ํ์ฑํ- Nav2 ์์ด LiDAR + OccupancyGrid๋ง์ผ๋ก frontier(๋ฏธํ์ ๊ฒฝ๊ณ) ๊ธฐ๋ฐ ์์จ ๋งตํ
- ์ํ ๋จธ์ :
idle โ rotating โ driving โ idle(๋ฐ๋ณต)- frontier ์์ง ์ "tracking" ๋ชจ๋๋ก ์๋ ์ ํ
- ์ ์ฒด(8์ด/12cm ๋ฏธ๋ง ์ด๋) ๊ฐ์ง ์ ํ์ง + ์ฐํ์ ๋ณต๊ตฌ
- ์ฉ๋: ๋ฐฉ ํ๋ ํฌ๊ธฐ์ ํ๊ฒฝ์ ์ฒ์ ํ์ํ ๋ ์ฌ์ฉ
- Angular PID: ํ๋ฉด ์ค์์ ๋์์ ์ ์ง (์ข์ฐ steering)
- Distance PID: LiDAR ๊น์ด ๊ธฐ๋ฐ ๊ฑฐ๋ฆฌ ์ ์ด (
target_depth_m๊ธฐ๋ณธ 0.8m) use_slam_depth=true์ด๋ฉด LiDAR ๊น์ด ์ง์ ์ฌ์ฉ, ์๋๋ฉด bbox ๋์ด ๋น์จ๋ก ์ถ์
- STM32 UART ํ๋กํ ์ฝ:
right_speed,left_speed,right_dir,left_dir\n - Dead zone ๋ณด์: ์
๋ ฅ์
min_speed~max_speed๋ก ์ ํ ๋งคํ - ์์ ํ์ด๋จธ: 0.5์ด๊ฐ ๋ช ๋ น ์์ผ๋ฉด ์๋ ์ ์ง
:8080/โ ์น ๋์๋ณด๋ (๋ผ์ด๋ธ ์นด๋ฉ๋ผ + SLAM ๋งต + ๋ก๊ทธ):8080/streamโ MJPEG ์คํธ๋ฆผ
# ๋น๋
./build.sh
# ์คํ (SLAM ํฌํจ)
./run.sh
# SLAM ์์ด ์คํ (์นด๋ฉ๋ผ+ํ์ง๋ง)
./run.sh use_slam:=false
# ํ๋ผ๋ฏธํฐ ์ค๋ฒ๋ผ์ด๋ ์์
./run.sh camera_orientation:=2 lidar_port:=/dev/ttyAMA2
# API ์๋ฒ ์ฐ๋ (API_URL ํ๊ฒฝ๋ณ์ ์ค์ ์ api_node ์๋ ์คํ)
API_URL=http://your-server/api ./run.sh์น ๋์๋ณด๋: http://<๋ก๋ด IP>:8080
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [์นด๋ฉ๋ผ ์คํธ๋ฆผ] [SLAM ๋งต] โ
โ โ
โ โข ์ค์๊ฐ ์์ โข ์ ์ ๊ฒฉ์ ๋งต (ํ์/ํฐ์/๊ฒ์ ) โ
โ โข ํ์ง bbox ์ค๋ฒ๋ ์ด โข ๋ก๋ด ์์น (์ฒญ๋ก์ ํ์ดํ) โ
โ โข ์ถ์ ๋์ ํ์ โข ๊ฐ์ฒด ์ถ์ ์์น (์ฃผํฉ์ ์) โ
โ โข LiDAR ์ค์บ ํฌ์ธํธ (๋
น์) โ
โ โข ์ธ๋ฑ์ฑ๋ ์ฅ์ (๋
ธ๋์ ๋ ์ด๋ธ)โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ [๋ชจํฐ ์ํ] โ [๋ก๋ด ๋ก๊ทธ] โ
โ ๋ฐฉํฅ/์๋ ํ์ โ ์ด๋ฒคํธ ์๊ฐ์ ๋ชฉ๋ก โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ [์ ์ด ๋ฒํผ] โ
โ ๐ ๋งต ๋ถ๋ฌ์ค๊ธฐ ๐พ ๋งต ์ ์ฅ โ
โ [MAPPING] [์ถ์ ๋ชจ๋] [๋งคํ ๋ชจ๋] [์๋ ํ์] โ
โ + ํ์ฌ ์์น ์ฅ์ ์ด๋ฆ ์ ์ฅ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- ๋ก๋ด์ ๋ฐฉ์ ๋ฐฐ์นํ๊ณ
./run.sh์คํ - ์น ๋์๋ณด๋ ์ ์ โ ๋งคํ ๋ชจ๋ ๋ฒํผ ํ์ธ (๊ธฐ๋ณธ๊ฐ)
- ๋ฐฉ๋ฒ A โ ์๋: ๋ก๋ด์ ์ง์ ๋ฐ๊ฑฐ๋ ์กฐ์ข ํ๋ฉฐ ๋ฐฉ ์ ์ฒด๋ฅผ ๋๊ธฐ
- ๋ฐฉ๋ฒ B โ ์๋: ์๋ ํ์ ๋ฒํผ ํด๋ฆญ โ ๋ก๋ด์ด ์ค์ค๋ก frontier ํ์ ์์
- ํ์ ์๋ฃ(frontier ์์) ์ ์๋์ผ๋ก ์ถ์ ๋ชจ๋ ์ ํ๋จ
- ๋งต์ด ์ถฉ๋ถํ ์์ฑ๋๋ฉด ๐พ ๋งต ์ ์ฅ ํด๋ฆญ โ
~/maps/slam_map.*ํ์ผ๋ก ์ ์ฅ
- ๋ก๋ด์ ๋งต ์์ฑ ๋น์์ ๊ฐ์ ์์น์ ๋ฐฐ์น (์ด๊ธฐ ์์น ์ค์!)
./run.sh์คํ- ๐ ๋งต ๋ถ๋ฌ์ค๊ธฐ ํด๋ฆญ โ ์ ์ฅ๋ ๋งต ๋ก๋ + ์ถ์ ๋ชจ๋ ์๋ ์ ํ
- ๋ก๋ด์ด ๋์์ ์๋์ผ๋ก ๋ฐ๋ผ๋ค๋๊ธฐ ์์
์ฃผ์: slam_toolbox๋ ๋ก๋ด ์ด๊ธฐ ์์น๋ฅผ ๋งต์ ์์ ์ผ๋ก ๊ฐ์ ํ๋ค. ๋งค ์คํ ์ ๋์ผํ ์์์ ์์ ์ผ์ผ ๋ก์ปฌ๋ผ์ด์ ์ด์ ์ด ์ ํํ๋ค.
- ๋ก๋ด์ด ํน์ ์์น์ ์์ ๋ ํ๋จ ์ ๋ ฅ์ฐฝ์ ์ด๋ฆ ์ ๋ ฅ ํ ์ถ๊ฐ ํด๋ฆญ
- SLAM ๋งต์ ๋ ธ๋์ ๋ ์ด๋ธ๋ก ํ์๋จ
- ์ฅ์ ์ ๋ณด๋
~/.ros/motherv2/places.json์ ์ ์ฅ
| ๋ฒํผ | ๋ชจ๋ | ์ค๋ช |
|---|---|---|
| ๋งคํ ๋ชจ๋ | mapping |
slam_toolbox๋ก ๋งต ์์ฑ ์ค. LiDAR ๋ฐฉํฅ ๊ธฐ๋ฐ ๊ฐ์ฒด ์ถ์ |
| ์ถ์ ๋ชจ๋ | tracking |
์ ์ฅ๋ ๋งต๊ณผ ํ์ฌ ์ค์บ ์ฐจ๋ถ์ผ๋ก ๋์ ๊ฐ์ฒด ํ์ง |
| ์๋ ํ์ | explore |
frontier ๊ธฐ๋ฐ ์์จ ๋งตํ ์์ |
| ํ๋ผ๋ฏธํฐ | ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|
camera_device |
0 |
์นด๋ฉ๋ผ ์ธ๋ฑ์ค |
camera_width/height |
640/360 |
ํด์๋ |
camera_orientation |
0 |
ํ์ (2 = 180๋) |
serial_port |
/dev/ttyAMA0 |
STM32 UART ํฌํธ |
lidar_port |
/dev/ttyAMA2 |
RPLIDAR ์๋ฆฌ์ผ ํฌํธ |
use_slam |
true |
SLAM ํ์ฑํ ์ฌ๋ถ |
conf_threshold |
0.35 |
ํ์ง ์ ๋ขฐ๋ ์๊ณ๊ฐ |
target_depth_m |
0.8 |
LiDAR ๊ธฐ๋ฐ ๋ชฉํ ์ถ์ ๊ฑฐ๋ฆฌ (m) |
camera_hfov_deg |
62.2 |
IMX219 ์ํ ํ๊ฐ (๋) |
lidar_angle_offset_rad |
0.0 |
์นด๋ฉ๋ผ-LiDAR ์ํ ๊ฐ๋ ์คํ์ |
min_speed |
130 |
์ต์ ๋ชจํฐ PWM |
max_speed |
150 |
์ต๋ ๋ชจํฐ PWM |
mqtt_broker |
broker.emqx.io |
MQTT ๋ธ๋ก์ปค ์ฃผ์ |
| ํ ํฝ | ํ์ | ์ค๋ช |
|---|---|---|
/motherv2/image_raw |
sensor_msgs/Image |
์นด๋ฉ๋ผ ์๋ณธ (BGR8) |
/motherv2/detections |
DetectionArray |
ํ์ง/ํธ๋ํน ๊ฒฐ๊ณผ |
/motherv2/detection_image |
sensor_msgs/Image |
bbox ์ค๋ฒ๋ ์ด ์ด๋ฏธ์ง |
/motherv2/cmd_motor |
MotorCommand |
๋ชจํฐ ์ ์ด ๋ช ๋ น |
/motherv2/object_estimates |
ObjectEstimateArray |
SLAM ์ขํ ๊ฐ์ฒด ์์น ์ถ์ |
/motherv2/slam_mode |
std_msgs/String |
SLAM ๋ชจ๋ (mapping/tracking/explore) |
/scan |
sensor_msgs/LaserScan |
LiDAR ์ค์บ |
/map |
nav_msgs/OccupancyGrid |
SLAM ์ ์ ๊ฒฉ์ ๋งต |
src/
โโโ motherv2_interfaces/ # ์ปค์คํ
๋ฉ์์ง (Detection, DetectionArray, MotorCommand, ObjectEstimateArray)
โโโ motherv2_detection/ # MediaPipe + MOSSE ํ์ง/์ถ์ ๋
ธ๋
โ โโโ models/
โ โโโ efficientdet_lite0.tflite
โโโ motherv2_follower/ # LiDAR ๊ธฐ๋ฐ PID ์ถ์ ์ ์ด ๋
ธ๋
โโโ motherv2_serial/ # STM32 UART ํต์ ๋
ธ๋
โโโ motherv2_slam/ # SLAM ์ฐ๋ ๋
ธ๋
โ โโโ slam_localization_node.py # LiDAR+์นด๋ฉ๋ผ ์ตํฉ, ๋์ ๊ฐ์ฒด ํ์ง
โ โโโ explore_node.py # frontier ๊ธฐ๋ฐ ์์จ ํ์
โโโ motherv2_web/ # ์น ๋์๋ณด๋ + HTTP API
โ โโโ web_node.py # MJPEG ์คํธ๋ฆผ + ๋์๋ณด๋ + SLAM ์๊ฐํ
โ โโโ api_node.py # ์ธ๋ถ API ํด๋ง (API_URL ์ค์ ์)
โโโ motherv2_mqtt/ # MQTT ํผ๋ธ๋ฆฌ์ ๋
ธ๋ (ESP32 ๋ฆด๋ ์ด ์ ์ด)
โโโ motherv2_bringup/ # ๋ฐ์น ํ์ผ + ์ค์
โ โโโ launch/motherv2.launch.py # ์ ์ฒด ์์คํ
๋ฐ์น
โ โโโ launch/slam.launch.py # SLAM ์๋ธ ๋ฐ์น
โโโ echo_lidar/ # RPLIDAR ROS2 ๋๋ผ์ด๋ฒ
- slam_toolbox๊ฐ
/mapํ ํฝ์ TRANSIENT_LOCAL QoS๋ก ํผ๋ธ๋ฆฌ์ํ๋ค - ๊ตฌ๋ ์ธก(web_node)๋ ๋ฐ๋์ TRANSIENT_LOCAL์ด์ด์ผ ์ฐ๊ฒฐ๋จ
ros2 topic info /map --verbose๋ก QoS ํ์ธ
- ๋ก๋ด ์ด๊ธฐ ์์น๊ฐ ๋งต ์์ฑ ๋น์์ ๋ค๋ฅผ ๋ ๋ฐ์
- ํด๊ฒฐ: ๋ก๋ด์ ๋งต ์์ฑ ์์ ์ง์ (๋ณดํต ๋ฐฉ ์ถ์ ๊ตฌ)์ผ๋ก ์ด๋ ํ ์์คํ ์ฌ์์
ls /dev/ttyAMA* # ํฌํธ ํ์ธ
sudo chmod 666 /dev/ttyAMA2 # ๊ถํ ๋ถ์ฌ
# ๋๋ dialout ๊ทธ๋ฃน์ ์ฌ์ฉ์ ์ถ๊ฐ
sudo usermod -aG dialout robot- frontier ํด๋ฌ์คํฐ ์ต์ ํฌ๊ธฐ(
MIN_CLUSTER=5)์ ๋ฏธ๋ฌ โ ๋งต์ด ๋๋ฌด ์๊ฑฐ๋ LiDAR ๋ ธ์ด์ฆ ARRIVE_DIST(0.6m)๋ฅผ ๋๋ฆฌ๊ฑฐ๋MIN_CLUSTER๋ฅผ ๋ฎ์ถฐ ๋ณผ ๊ฒ
serial_node๋ก๊ทธ์์Serial openedํ์ธ- UART ํฌํธ ํ์ธ:
ls /dev/ttyAMA*โ ๊ธฐ๋ณธ๊ฐ/dev/ttyAMA0 - STM32 ํ๋กํ ์ฝ ํฌ๋งท ํ์ธ:
right_speed,left_speed,right_dir,left_dir\n
- Raspberry Pi ๋ฐ์ด ํ์ธ:
vcgencmd get_throttled(0x0= ์ ์) - ํด์๋๋ฅผ ๋ฎ์ถ๊ฑฐ๋ detection interval์ ๋๋ฆฐ๋ค
- ์นด๋ฉ๋ผ QoS๋ ๋ฐ๋์ BEST_EFFORT๋ก ๊ตฌ๋ ํด์ผ ํ๋ค
serial_nodeSIGINT ํธ๋ค๋ฌ๊ฐ ์ ์ง ๋ช ๋ น์ ์ ์กํ์ง ๋ชปํ ๊ฒฝ์ฐ- ๊ฐ์ ์ ์ง: STM32 ๋ฆฌ์ ๋ฒํผ ๋๋ ์ ์ ์ฐจ๋จ