Bu, konunun uzun ve teknik rehberi (ESP-IDF, MicroPython, rclcpp gibi alternatiflerle). Adım adım yol için Porti görevlerine dön.

Ana rota · Hafta 6 · 9–18 saat

Evin haritası

LiDAR + IMU, EKF ile füzyon, SLAM Toolbox

Robota göz takıyorsun. LiDAR ile evin haritasını çıkarıyor, tekerlek odometry'si ile gyro'yu EKF'de birleştirip yön tahminini güçlendiriyorsun. Haritanın kalitesinin neden doğrudan odometry'nin kalitesine bağlı olduğunu önce simülasyonda, sonra kendi evinde görüyorsun.

Günün sonunda elinde
  • Raspberry Pi robotta: ros2_control + LiDAR sürücüsü; ağır iş PC'de
  • LiDAR /scan RViz'de, TF ağacında doğru yerde
  • robot_localization EKF: tekerlek + gyro; önce/sonra yön kayması
  • SLAM Toolbox ile evin haritası (.pgm + .yaml)
  • Haritayı çıkarırken çekilmiş hızlandırılmış video
6.1

Pi'yi robota koy, LiDAR'ı gör

Robotta Pi + LiDAR çalışıyor, PC'deki RViz'de /scan doğru yönde görünüyor.

Yap
Kod
pi.sh
# Raspberry Pi 4/5: Ubuntu Server 24.04 (64-bit) + ROS 2 Jazzy ros-base
# Raspberry Pi Imager → Ubuntu Server 24.04 LTS, SSH ve WiFi'yi imager'da ayarla.
sudo apt update && sudo apt install -y ros-jazzy-ros-base ros-dev-tools \
  ros-jazzy-ros2-control ros-jazzy-ros2-controllers ros-jazzy-robot-localization
echo "source /opt/ros/jazzy/setup.bash" >> ~/.bashrc
echo "export ROS_DOMAIN_ID=7" >> ~/.bashrc

# LiDAR ve ESP32 için sabit cihaz adları (idVendor/idProduct: udevadm info -a -n /dev/ttyUSB0)
sudo tee /etc/udev/rules.d/99-rover.rules > /dev/null <<'RULES'
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{serial}=="LIDAR_SERI_NO", SYMLINK+="lidar"
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="rover"
RULES
sudo udevadm control --reload-rules && sudo udevadm trigger

# Mimari: Pi'de ros2_control + LiDAR sürücüsü, PC'de SLAM / Nav2 / RViz.
# İkisi aynı ROS_DOMAIN_ID ile aynı ağda.
Kanıt: RViz'de robot modeli ve tarama noktaları; robotun önüne konan kutu doğru yerde.
Tuzaklar
  • Tarama 180° ters görünüyorsa laser_joint'in yaw'ı yanlış: LiDAR'ın 0° yönü üretici dokümanında.
  • WiFi'de DDS multicast sorunluysa node'lar birbirini görmez. Önce aynı makinede dene, sonra ağ ayarına bak (ya da rmw_zenoh).
  • LiDAR motoru dönmüyor ya da tarama kesik geliyorsa güç yetersiz: ayrı 5V hattından besle.
6.2

Kalman'ın özü ve EKF

robot_localization tekerlek odometry'sini ve gyro'yu birleştiriyor. Yerinde 10 tur döndürünce yön hatası EKF ile ve EKF'siz ölçülü.

Önce simülasyonda
Dene:
  • IMU açık ve kapalı iken kareyi sür: yön hatası nasıl değişiyor?
  • Patinajı artır: gyro patinajdan etkilenmiyor, tekerlek etkileniyor.
Simülasyon yükleniyor…
Yap
Kod
tools/kalman_1d.py
#!/usr/bin/env python3
"""kalman_1d.py — Kalman filtresinin özü, 30 satır. EKF'nin ne yaptığını sezmek için.

Robotun yönünü (yaw) iki kaynaktan tahmin ediyoruz:
  - tahmin: gyro ile entegrasyon (kayar, ama kısa vadede pürüzsüz)
  - ölçüm: tekerlek odometry'sinin yönü (patinajla sıçrar, ama kaymaz)
"""
import numpy as np

rng = np.random.default_rng(0)
dt, n = 0.02, 1500
true_rate = 0.4 * np.sin(np.arange(n) * dt * 0.5)          # rad/s
true_yaw = np.cumsum(true_rate) * dt
gyro = true_rate + 0.01 + rng.normal(0, 0.02, n)           # 0.01 rad/s bias
wheel_yaw = true_yaw + rng.normal(0, 0.05, n)
wheel_yaw[700:720] += np.linspace(0, 0.3, 20)              # patinaj anı
wheel_yaw[720:] += 0.3

x, P = 0.0, 1.0            # durum: yaw, belirsizliği
Q, R = (0.02 * dt) ** 2, 0.05**2
est = []
for k in range(n):
    x, P = x + gyro[k] * dt, P + Q                          # tahmin
    K = P / (P + R)                                         # Kalman kazancı
    x, P = x + K * (wheel_yaw[k] - x), (1 - K) * P          # düzeltme
    est.append(x)

gyro_only = np.cumsum(gyro) * dt
for name, e in [("sadece gyro", gyro_only), ("sadece tekerlek", wheel_yaw), ("kalman", np.array(est))]:
    print(f"{name:16s} RMS hata: {np.degrees(np.sqrt(np.mean((e - true_yaw) ** 2))):.2f}°")
# Q ve R'yi değiştir: filtre hangi kaynağa ne kadar güveniyor?
Kanıt: 10 tur dönüş testinde yön hatası: sadece odometry ve EKF (derece).
Tuzaklar
  • Aynı bilgiyi iki kez verme (örn. hem odometry'nin yaw'ı hem gyro): EKF ona fazla güvenir.
  • IMU'nun eksenleri REP 103'e uymuyorsa (x ileri, y sol, z yukarı) EKF ters döner. TF ile imu_link yönelimini düzelt.
Daha derin
6.3

Evin haritasını çıkar

SLAM Toolbox ile evin bir bölümünün temiz haritası kayıtlı; loop closure'ın haritayı nasıl düzelttiğini gördün.

Önce simülasyonda
Dene:
  • Varsayılan ayarlarla haritayı çıkar: duvarlar çiftleşiyor, oran düşük.
  • IMU + EKF'yi aç: yön kayması 10 kat azalıyor, harita toparlanıyor.
  • SLAM düzeltmesini aç: tek ve tutarlı bir harita.
  • Yön kaymasını 0, mesafe hatasını 6% yap: hangisi haritayı daha çok bozuyor?
Simülasyon yükleniyor…
Yap
Kod
slam.sh
# PC'de: SLAM Toolbox ile harita çıkar
sudo apt install -y ros-jazzy-slam-toolbox ros-jazzy-nav2-map-server
ros2 launch slam_toolbox online_async_launch.py use_sim_time:=false

# RViz: Fixed Frame = map · Add > Map (/map) · LaserScan (/scan) · TF
# Robotu YAVAŞ sür (teleop'ta hızı 0.15 m/s, dönüşü 0.5 rad/s'ye indir).
# Aynı yerden ikinci kez geçince loop closure'ı izle.

# Haritayı kaydet: Nav2 formatı (pgm + yaml) ve SLAM Toolbox'ın kendi formatı
ros2 run nav2_map_server map_saver_cli -f ~/maps/ev
ros2 service call /slam_toolbox/serialize_map slam_toolbox/srv/SerializePoseGraph "{filename: '/home/$USER/maps/ev'}"
Kanıt: Evin haritası (pgm) ve harita çıkarmanın hızlandırılmış ekran kaydı.
Tuzaklar
  • Hızlı dönüşte tarama "bulanıklaşır": robot dönerken LiDAR bir turu tamamlamadan pozisyon değişir.
  • Cam yüzeyler ve aynalar LiDAR'ı şaşırtır; haritada hayalet duvarlar normal.
  • Harita kayıyorsa sorun çoğunlukla odometry'de ya da TF zaman damgalarında, SLAM'de değil.
Daha derin
  • Aynı bag dosyasını Cartographer ile haritala, sonuçları karşılaştır.
  • Henki Robotics'in açık kursundaki SLAM alıştırmalarını Gazebo'da Andino robotuyla yap.

Kavramlar

LaserScan360° etrafındaki mesafe ölçümleri. SLAM'in ve engelden kaçınmanın ham verisi.
EKFGürültülü sensörleri belirsizliklerine göre birleştirip tek, daha iyi bir durum tahmini çıkarır.
Occupancy gridHaritanın her hücresi için "dolu olma olasılığı". Nav2 bunu okur.
Scan matchingYeni taramayı haritaya oturtarak odometry hatasını düzeltmek.
Loop closureDaha önce geçtiği yeri tanıyınca biriken hatayı bütün haritaya yaymak.
map → odomSLAM bu dönüşümü yayınlar, odometry odom → base'i. Biri sıçrar ama kaymaz, diğeri pürüzsüz ama kayar.

Kaynaklar