Bu, konunun uzun ve teknik rehberi (ESP-IDF, MicroPython, rclcpp gibi alternatiflerle). Adım adım yol için Porti görevlerine dön.
ESP32 ROS 2 konuşuyor
micro-ROS: /cmd_vel al, durum yayınla, her şeyi kaydet
1. haftanın motoru artık ROS 2 dünyasının bir parçası. Bilgisayardaki klavye komutu WiFi üzerinden ESP32'ye gidiyor, motorun durumu geri geliyor, hepsi bir bag dosyasına kaydediliyor. Kontrol döngüsü ESP32'de kalıyor: ağ koparsa motor 0.5 saniyede duruyor.
- Ubuntu + ROS 2 Jazzy kurulu; node, topic, service, param kavramları elinde
- ESP32 micro-ROS node'u: /cmd_vel → motor, motor → /motor/state
- Agent kapanıp açılınca ESP32 kendiliğinden yeniden bağlanıyor
- Aynı test node'u hem rclpy hem rclcpp ile
- MCAP kaydı ve Foxglove'da çizilmiş grafik
ROS 2 Jazzy'yi kur, kavramları dene
Ubuntu 24.04'te ROS 2 Jazzy çalışıyor. turtlesim üzerinde node, topic, service ve parametreyi komut satırından kullandın.
# Ubuntu 24.04 + ROS 2 Jazzy (resmi deb paketleri)
sudo apt install -y software-properties-common curl
sudo add-apt-repository universe
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" \
| sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
sudo apt update && sudo apt install -y ros-jazzy-desktop ros-dev-tools
echo "source /opt/ros/jazzy/setup.bash" >> ~/.bashrc && source ~/.bashrc
# Kurulum kontrolü: iki terminal
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_py listener
# Ağdaki her şey aynı domain'de olsun (robot, PC, Pi)
echo "export ROS_DOMAIN_ID=7" >> ~/.bashrc
- Mac'te Docker ile GUI (RViz, rqt) zahmetli; USB cihazlar da görünmez. Bu rota için Ubuntu bir makine, ikinci el bir mini PC bile olsa, çok zaman kazandırır.
- Her yeni terminalde source /opt/ros/jazzy/setup.bash gerekir. .bashrc'ye yazmadıysan "ros2: command not found" görürsün.
ESP32'yi ROS 2 node'una çevir
ESP32 WiFi üzerinden agent'a bağlanıyor, /cmd_vel dinliyor, /motor/state yayınlıyor. Agent'ı kapatıp açtığında kendini yeniden bağlıyor.
- Gecikmeyi 20-40 ms yap: WiFi üzerinden PID koşarsan ne olacağını görürsün.
- Bu yüzden döngü ESP32'de kalıyor; ağdan yalnız hedef hız geliyor.
; platformio.ini — micro-ROS (Jazzy) + WiFi UDP transport
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
board_microros_distro = jazzy
board_microros_transport = wifi
lib_deps =
https://github.com/micro-ROS/micro_ros_platformio
- micro-ROS build zinciri hassastır: PlatformIO önbelleğini (.pio) silip temiz derlemek çoğu tuhaf hatayı çözer.
- ESP32 ile PC farklı alt ağdaysa (misafir WiFi, VPN) agent bulunamaz.
- sensor_msgs/JointState gibi dizi içeren mesajlar micro-ROS'ta önceden bellek ayırmayı ister. Bu yüzden ilk adımda sabit boyutlu Vector3 kullandık.
Daha derin
- Transport'u seri porta çevir (board_microros_transport = serial), gecikme ve kaybı WiFi ile karşılaştır.
- micro_ros_utilities ile JointState için statik bellek ayır, /joint_states yayınla.
- ROS 2 middleware'ini rmw_zenoh_cpp'ye çevir; WiFi'de multicast sorunlarını nasıl çözdüğüne bak.
- micro_ros_platformio
- esp32-microros-robot-control · /cmd_vel + timeout örneği
- awesome-micro-ros-projects
Aynı node: Python ve C++
Bir test node'u /cmd_vel'e step profili yolluyor ve sonucu CSV'ye yazıyor. Aynısını rclpy ve rclcpp ile yazıp farkı gördün.
#!/usr/bin/env python3
"""step_test.py — /cmd_vel'e step profili yollar, /motor/state'i CSV'ye yazar.
ros2 run motor_tools step_test --ros-args -p speed:=0.4 -p out:=step.csv
Parametreler çalışırken değişebilir: ros2 param set /step_test speed 0.2
"""
import csv
import rclpy
from geometry_msgs.msg import Twist, Vector3
from rclpy.node import Node
from rclpy.qos import qos_profile_sensor_data
class StepTest(Node):
def __init__(self):
super().__init__("step_test")
self.declare_parameter("speed", 0.3) # m/s
self.declare_parameter("out", "step.csv")
self.pub = self.create_publisher(Twist, "cmd_vel", 10)
self.create_subscription(Vector3, "motor/state", self.on_state, qos_profile_sensor_data)
self.t0 = self.get_clock().now()
self.file = open(self.get_parameter("out").value, "w", newline="")
self.csv = csv.writer(self.file)
self.csv.writerow(["t", "target_rpm", "rpm", "duty"])
self.create_timer(0.05, self.tick) # 20 Hz komut: watchdog'u besler
def elapsed(self) -> float:
return (self.get_clock().now() - self.t0).nanoseconds * 1e-9
def tick(self):
t = self.elapsed()
v = self.get_parameter("speed").value
cmd = Twist()
cmd.linear.x = 0.0 if t < 0.5 else v if t < 3 else v * 0.4 if t < 5 else v if t < 7 else 0.0
self.pub.publish(cmd)
if t > 8:
self.get_logger().info("bitti → " + self.get_parameter("out").value)
self.file.close()
raise SystemExit
def on_state(self, m: Vector3):
self.csv.writerow([f"{self.elapsed():.3f}", m.x, m.y, m.z])
def main():
rclpy.init()
node = StepTest()
try:
rclpy.spin(node)
except SystemExit:
pass
finally:
node.destroy_node()
rclpy.try_shutdown()
if __name__ == "__main__":
main()
- colcon build sonrası source install/setup.bash yapmazsan yeni paket görünmez.
Daha derin
- Aynı node'u rclnodejs ile TypeScript'te yaz; ROS 2'nin istemci kütüphanesi katmanını anlamak için iyi bir egzersiz.
Kaydet, oynat, Foxglove'da bak
Her deney bir MCAP dosyası. Foxglove'da hedef ve ölçülen hız aynı grafikte; deneyi istediğin zaman tekrar oynatabiliyorsun.
Daha derin
- foxglove_bridge ile canlı veriyi Foxglove'a akıt; 6. haftada web arayüzünde bunu kullanacaksın.
Kavramlar
Kaynaklar
- ROS 2 Jazzy tutorial'ları
- micro-ROS
- Strands Robots: ROS 2 · Üç transport, ne zaman hangisi