<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Robotics Archives - Creatronix</title>
	<atom:link href="https://creatronix.de/category/robotics/feed/" rel="self" type="application/rss+xml" />
	<link>https://creatronix.de/category/robotics/</link>
	<description>My adventures in code &#38; business</description>
	<lastBuildDate>Wed, 11 Mar 2026 19:53:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>So verwaltest du deine Roboter mit Ansible</title>
		<link>https://creatronix.de/so-verwaltest-du-deine-roboter-mit-ansible/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Wed, 11 Mar 2026 19:43:10 +0000</pubDate>
				<category><![CDATA[Robotics]]></category>
		<category><![CDATA[Software Engineering & Programming]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7893</guid>

					<description><![CDATA[<p>Motivation Eine einzelne Ubuntu-Maschine zu warten, ist noch überschaubar. Man loggt sich per SSH ein, installiert ein paar Pakete, macht ein Update – und dann läuft die Kiste wieder. In der Robotik bleibt es aber selten bei einer Maschine. Sobald mehrere Roboter im Einsatz sind, sitzt man plötzlich vor einem kleinen Zoo aus Linux-Systemen. Dann&#8230;</p>
<p>The post <a href="https://creatronix.de/so-verwaltest-du-deine-roboter-mit-ansible/">So verwaltest du deine Roboter mit Ansible</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Motivation</h2>
<p>Eine einzelne Ubuntu-Maschine zu warten, ist noch überschaubar. Man loggt sich per SSH ein, installiert ein paar Pakete, macht ein Update – und dann läuft die Kiste wieder.</p>
<p>In der Robotik bleibt es aber selten bei einer Maschine. Sobald mehrere Roboter im Einsatz sind, sitzt man plötzlich vor einem kleinen Zoo aus Linux-Systemen.</p>
<p>Dann beginnt die klassische Runde:<br />
SSH auf Rechner eins, Updates einspielen.<br />
SSH auf Rechner zwei, dieselben Updates einspielen.<br />
SSH auf Rechner drei – na, Du ahnst es schon.</p>
<p>Spätestens nach dem fünften Roboter merkt man: Das ist weniger Systemadministration und mehr Fleißarbeit mit Copy-Paste.</p>
<p>Genau hier kommt Ansible ins Spiel. Mit sogenannten Playbooks beschreibt man einfach den gewünschten Zustand der Systeme – welche Pakete installiert sein sollen, welche Konfigurationen gelten, welche Updates eingespielt werden. Ansible kümmert sich dann darum, diese Zustände automatisch auf allen Zielrechnern umzusetzen.</p>
<p>Gerade in Robotik-Umgebungen mit vielen verteilten Rechnern sorgt dieser Ansatz dafür, dass Wartung nicht mehr Handarbeit ist – sondern planbar, reproduzierbar und vor allem deutlich entspannter.</p>
<h2>Ansible</h2>
<p>Ansible wurde 2012 von Michael DeHaan entwickelt und als Open-Source-Projekt veröffentlicht. 2015 wurde das Unternehmen Ansible, Inc. von Red Hat übernommen, das wiederum seit 2019 zu IBM gehört.</p>
<p>Es ist ein agentenloses Automatisierungstool – das heißt, auf den Zielrechnern muss keine zusätzliche Software installiert werden. Ansible verbindet sich einfach per SSH und führt die gewünschten Aufgaben aus.</p>
<h2>Setup</h2>
<p>Für dieses Tutorial brauchst Du einen Ubuntu-PC und einen Raspberry Pi mit einem installierten Ubuntu. Auf deinem Control-Rechner (also deinem PC) läuft Ansible und der SSH Client, auf dem Raspberry (also dem Remote-Rechner) muss der SSH-Server aktiviert sein.</p>
<h2>Installation</h2>
<p>Auf deinem Control-Rechner installierst du Ansible wie folgt:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo apt update
sudo apt install ansible
sudo apt install sshpass</code></pre>
</div>
<p>Jetzt kannst Du testen, ob die Installation geklappt hat:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ansible --version</code></pre>
</div>
<h2>SSH aktivieren</h2>
<p>Damit Ansible funktioniert, muss auf dem Raspberry aka Remote-Rechner SSH eingerichtet sein.<br />
Probier mal im Terminal deines Control-Rechners aus, dich mit dem Raspberry zu verbinden:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ssh pi@192.168.178.50</code></pre>
</div>
<p>Falls das nicht klappt, musst du SSH auf dem Raspberry aktivieren. Das geht ganz einfach über die raspi-config:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo raspi-config</code></pre>
</div>
<p>Dann navigierst du zu &#8220;Interfacing Options&#8221; -&gt; &#8220;SSH&#8221; und aktivierst den SSH-Server.</p>
<h2>Projektordner</h2>
<p>Auf deinem Control-Rechner legst du dir z.B. einen Projektordner an:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>mkdir ~/ansible
cd ansible
touch hosts
touch ansible.cfg
touch update_pi.yml</code></pre>
</div>
<p>Die Ordnerstruktur soll nachher so aussehen:</p>
<p>ansible/<br />
├── hosts<br />
├── update_pi.yml<br />
└── ansible.cfg</p>
<h2>hosts-Datei anlegen</h2>
<p>In der hosts-Datei stehen die Rechner und ihre IP-Adressen bzw. ihre A-Records.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-json" data-lang="JSON"><code>[raspberry]
pi1 ansible_host=192.168.178.66 ansible_user=&lt;username&gt;</code></pre>
</div>
<h2>ansible.cfg</h2>
<p>Die ansible.cfg Datei ist die Konfigurationsdatei für Ansible.<br />
Hier kannst du verschiedene Einstellungen vornehmen, z.B. den Pfad zu deiner hosts-Datei.<br />
Ein einfaches Beispiel sieht so aus</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-json" data-lang="JSON"><code>[defaults]
inventory = hosts</code></pre>
</div>
<h2>Playbooks</h2>
<p>Playbooks sind die Ansible-Äquivalente zu Skripten, sie beschreiben die gewünschten Zustände der Zielrechner.<br />
Ein einfaches Playbook für die Updates des Raspberrys könnte so aussehen:</p>
<h3>update_pi.yml</h3>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-json" data-lang="JSON"><code>---
- name: Update Raspberry Pi
  hosts: raspberry
  become: yes

  tasks:
    - name: Update apt cache
      apt:
        update_cache: yes

    - name: Upgrade all packages
      apt:
        upgrade: dist</code></pre>
</div>
<h3>Im Detail</h3>
<table>
<thead>
<tr>
<th>Ansible</th>
<th>Bash</th>
</tr>
</thead>
<tbody>
<tr>
<td>become: yes</td>
<td>sudo</td>
</tr>
<tr>
<td>apt: update_cache: yes</td>
<td>apt update</td>
</tr>
<tr>
<td>upgrade: dist</td>
<td>apt upgrade</td>
</tr>
<tr>
<td>autoremove: yes</td>
<td>apt autoremove</td>
</tr>
</tbody>
</table>
<h2>Ansible starten</h2>
<p>Wenn du diese drei Dateien anegelegt hast, kann es auch schon losgehen</p>
<h3>ping</h3>
<p>Der ping-Befehl ist ein Testmodul von Ansible, das überprüft, ob der Host erreichbar und ausführbar ist.<br />
Wenn du Passwort-Login benutzt musst du Ansible sagen, dass es nach einem SSH-Passwort fragen soll:<br />
Das -k steht für &#8211;ask-pass</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ansible -i hosts raspberry -m ping -k
SSH password:</code></pre>
</div>
<p>Wenn alles funktioniert, solltest du folgenden Output sehen:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>pi1 | SUCCESS =&gt; {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}</code></pre>
</div>
<h3>Playbook starten</h3>
<p>Jetzt zum eigentlichen Task:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ansible-playbook -i hosts update_pi.yml -k -K</code></pre>
</div>
<p>Da wir sudu apt update / upgrade machen wollen, müssen wir auch das root-PW übergeben. Das machen wir mit dem Flag -K.<br />
-K steht für &#8211;ask-become-pass, damit wird Ansible nach dem sudo-Passwort fragen.</p>
<h2>Zertifikat-Login</h2>
<p>Da wir aber nicht permanent die<br />
Ansible unterstützt auch die Authentifizierung mit Zertifikaten, was sicherer ist als die Passwort-Authentifizierung.<br />
Dazu musst du auf deinem Control-Rechner ein SSH-Schlüsselpaar generieren und den öffentlichen Schlüssel auf den<br />
Zielrechner kopieren.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ssh-keygen -t rsa -b 4096 -C "@ansible-controller"
ssh-copy-id @192.168.178.66</code></pre>
</div>
<p>Danach kannst du Ansible ohne Passwort verwenden, indem du einfach den Hostnamen angibst:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ansible-playbook -i hosts update_pi.yml -K</code></pre>
</div>
<h2>Weitere Beispiele</h2>
<h3>Ubuntu-Pakete installieren</h3>
<p>Man kann natürlich auch andere Pakete installieren, z.B. git:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-json" data-lang="JSON"><code>tasks: 
- name: Install git 
  apt: 
    name: git 
    state: present 
    update_cache: yes</code></pre>
</div>
<h3>Git Repository klonen</h3>
<p>Auch das Klonen eines Git-Repositories ist mit Ansible kein Problem:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-json" data-lang="JSON"><code>tasks: 
- name: Clone Git repo 
    git:
      repo: https://github.com/user/meinprojekt.git 
      dest: /home/pi/meinprojekt 
      version: main</code></pre>
</div>
<h2>Fazit</h2>
<p>Ansible ist ein mächtiges Werkzeug, um die Wartung von Robotern zu automatisieren. Es ermöglicht dir, den Zustand deiner<br />
Systeme zu beschreiben und automatisch umzusetzen, ohne dich manuell auf jedem Rechner einzuloggen. Gerade in Umgebungen<br />
mit vielen verteilten Rechnern spart das enorm viel Zeit und Nerven.</p>
<p>The post <a href="https://creatronix.de/so-verwaltest-du-deine-roboter-mit-ansible/">So verwaltest du deine Roboter mit Ansible</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>So verwendest du die Kinect unter ROS 2</title>
		<link>https://creatronix.de/so-verwendest-du-die-kinect-unter-ros-2/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Sat, 31 Jan 2026 19:47:36 +0000</pubDate>
				<category><![CDATA[Robotics]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7834</guid>

					<description><![CDATA[<p>Motivation Microsoft Kinect v1 &#8211; damals für die Xbox 360 erschienen &#8211; ist eine sehr beliebte Kamera mit einem zusätzlichen Infrarot-Tiefensensor. Sie ist in Robotikkreisen sehr beliebt, weil sich durch die Tiefeninformation und die dadurch möglichen Umrechnungen in eine Point Cloud, Greifbewegungen von Roboterarmen automatisieren lassen. Funktionsweise Der IR-Projektor wirft ein bekanntes Punktmuster Das Muster&#8230;</p>
<p>The post <a href="https://creatronix.de/so-verwendest-du-die-kinect-unter-ros-2/">So verwendest du die Kinect unter ROS 2</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Motivation</h2>
<p>Microsoft Kinect v1 &#8211; damals für die Xbox 360 erschienen &#8211; ist eine sehr beliebte Kamera mit einem zusätzlichen Infrarot-Tiefensensor.<br />
Sie ist in Robotikkreisen sehr beliebt, weil sich durch die Tiefeninformation und die dadurch möglichen Umrechnungen in eine Point Cloud, Greifbewegungen von Roboterarmen automatisieren lassen.</p>
<h2>Funktionsweise</h2>
<ul>
<li>Der IR-Projektor wirft ein bekanntes Punktmuster</li>
<li>Das Muster wird auf Objekten verzerrt</li>
<li>Die IR-Kamera sieht diese Verzerrung</li>
<li>Aus der Abweichung vom Referenzmuster wird die Tiefe berechnet</li>
</ul>
<h2>Disclaimer</h2>
<p>Die Kinect benötigt eine externe Stromversorgung und funktioniert nicht ausschließlich über USB.</p>
<p>Ich hatte mit der Verbindung zu einer Ubuntu VM mit UMT und macos kein Glück. Hier kam es permanent zu frame drops. Deswegen bezieht sich dieses Tutorial auf die Einrichtung auf einem Raspberry Pi 4 mit ROS 2 Humble.</p>
<h2>Anschluss am Raspberry</h2>
<p>Ihr solltet die blauen USB 3.0 Ports verwenden.</p>
<h2>Software</h2>
<p>In diesem Tutorial werden wir</p>
<ul>
<li>libfreenect</li>
<li>image_pipeline</li>
<li>kinect_ros2</li>
</ul>
<p>installieren</p>
<h2>libfreenect</h2>
<p>libfreenect ist ein Open Source Treiber für die Kinect, der auf macOS, Windows und Linux läuft.</p>
<h3>Bauen und installieren</h3>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>cd ~ 
git clone https://github.com/OpenKinect/libfreenect.git 
cd libfreenect 
mkdir build &amp;&amp; cd build 
cmake .. -DBUILD_EXAMPLES=ON 
make 
sudo make install 
sudo ldconfig</code></pre>
</div>
<p>Jetzt könnt ihr mit</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>freenect-camtest</code></pre>
</div>
<p>ausprobieren, ob die Kinect bereits funktioniert. Es sollte &#8220;Received video frame&#8221; als Ausgabe kommen.</p>
<h3>freenect-glview</h3>
<p>freenect-glview ist ein weiteres Tool, um die Kinect zu testen, ihr könnt es mit:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>freenect-glview</code></pre>
</div>
<p>starten</p>
<p><img fetchpriority="high" decoding="async" src="https://creatronix.de/wp-content/uploads/2026/01/kinect-raspberry-gltest-1024x768.jpg" alt="" width="1024" height="768" class="alignnone size-large wp-image-7833" srcset="https://creatronix.de/wp-content/uploads/2026/01/kinect-raspberry-gltest-1024x768.jpg 1024w, https://creatronix.de/wp-content/uploads/2026/01/kinect-raspberry-gltest-300x225.jpg 300w, https://creatronix.de/wp-content/uploads/2026/01/kinect-raspberry-gltest-768x576.jpg 768w, https://creatronix.de/wp-content/uploads/2026/01/kinect-raspberry-gltest-1536x1152.jpg 1536w, https://creatronix.de/wp-content/uploads/2026/01/kinect-raspberry-gltest-2048x1536.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>Wenn der Befehl nicht gefunden wurde, müsst ihr noch die fehlende Abhängigkeit freeglut3-dev (Free OpenGL Utility Toolkit) installieren</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo apt install freeglut3-dev</code></pre>
</div>
<p>und die build-Schritte von oben wiederholen</p>
<h2>ROS2-Anbindung</h2>
<p>Voraussetzung ist ein funktionierender ROS-2-Workspace (~/ros2_ws) mit gesourcter Umgebung. Falls ihr das noch nicht gemacht habt, könnten euch diese Artikel helfen:<br />
<a href="https://creatronix.de/so-installierst-du-ros-2-auf-dem-raspberry-pi-ball-chaser-mit-ros2/">https://creatronix.de/so-installierst-du-ros-2-auf-dem-raspberry-pi-ball-chaser-mit-ros2/</a><br />
<a href="https://creatronix.de/so-schreibst-du-pakete-und-nodes-in-ros/">https://creatronix.de/so-schreibst-du-pakete-und-nodes-in-ros/</a></p>
<h3>Image Pipeline installieren</h3>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>cd ~/ros2_ws/src 
git clone https://github.com/ros-perception/image_pipeline 
cd image_pipeline 
git checkout humble 
cd ~/ros2_ws 
colcon build 
source install/setup.bash</code></pre>
</div>
<p>Um zu schauen, ob alles korrekt funktioniert, können wir nun in einem Terminal</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 run image_proc image_proc</code></pre>
</div>
<p>und in einem zweiten Terminal:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 run rqt_image_view rqt_image_view</code></pre>
</div>
<p>ausprobieren.</p>
<p>Wenn ein Live-Bild in rqt_image_view erscheint, funktioniert die Image Pipeline korrekt.</p>
<h3>rosdep initialisieren</h3>
<p>Falls ihr bisher kein rosdep verwendet habt, müsst ihr das einmalig machen:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>cd ~/ros2_ws 
sudo rosdep init 
rosdep update</code></pre>
</div>
<h3>kinect_ros2 installieren</h3>
<p>Obwohl das Paket offiziell nur bis Galactic gepflegt ist, lässt es sich unter Humble aktuell problemlos aus dem Source bauen.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>cd ~/ros2_ws/src 
git clone https://github.com/fadlio/kinect_ros2/tree/galactic 
cd ~/ros2_ws 
rosdep install --from-paths src --ignore-src -r -y 
colcon build
source install/setup.bash</code></pre>
</div>
<p>Jetzt können die launch files gestartet werden</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 launch kinect_ros2 pointcloud.launch.py</code></pre>
</div>
<p>Der Node kinect_ros2 publiziert jetzt die Topics /depth/image_raw und /depth/camera_info<br />
Ihr könnt das auf der Kommandozeile mit</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 topic list</code></pre>
</div>
<p>überprüfen.</p>
<p>Wir können jetzt auch die Bilder aufzeichnen und via rosbag in einem mcap speichern. Wir prüfen zuerst, ob die mcap-Erweiterung installiert ist:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 bag info --storage-id mcap</code></pre>
</div>
<p>Falls nicht</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo apt install ros-humble-rosbag2-storage-mcap</code></pre>
</div>
<p>Aufnehmen können wir nun mit</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 bag record /camera/depth/points -s mcap</code></pre>
</div>
<p>Da die Datenmenge bei Bilddaten schnell sehr groß werden können, kann man mcap auch komprimiert aufzeichnen:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 bag record \
/camera/depth/points \
-s mcap \
--compression-mode file \
--compression-format zstd</code></pre>
</div>
<p>&nbsp;</p>
<p>The post <a href="https://creatronix.de/so-verwendest-du-die-kinect-unter-ros-2/">So verwendest du die Kinect unter ROS 2</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>So ersetzt Du FastDDS mit Cyclone DDS</title>
		<link>https://creatronix.de/so-ersetzt-du-fastdds-mit-cyclone-dds/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Mon, 05 Jan 2026 16:14:02 +0000</pubDate>
				<category><![CDATA[Robotics]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7808</guid>

					<description><![CDATA[<p>Motivation Wenn du in Humble von den Vorteilen von CycloneDDS profitieren möchtest, zeige ich dir hier den Umstieg. Was ist eine Middleware? Eine Middleware ist eine Software-Schicht, die es Programmen ermöglicht, Daten auszutauschen, ohne direkt betriebssystem-spezifische Funktionen nutzen zu müssen. Was ist DDS Data Distribution Service (DDS) ist ein Standard der Object Management Group und&#8230;</p>
<p>The post <a href="https://creatronix.de/so-ersetzt-du-fastdds-mit-cyclone-dds/">So ersetzt Du FastDDS mit Cyclone DDS</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Motivation</h2>
<p>Wenn du in Humble von den Vorteilen von CycloneDDS profitieren möchtest, zeige ich dir hier den Umstieg.</p>
<h2>Was ist eine Middleware?</h2>
<p>Eine Middleware ist eine Software-Schicht, die es Programmen ermöglicht, Daten auszutauschen, ohne direkt betriebssystem-spezifische<br />
Funktionen nutzen zu müssen.</p>
<h2><img decoding="async" src="https://creatronix.de/wp-content/uploads/2026/01/ros-middleware.png" alt="" width="557" height="480" class="alignnone size-full wp-image-7807" srcset="https://creatronix.de/wp-content/uploads/2026/01/ros-middleware.png 557w, https://creatronix.de/wp-content/uploads/2026/01/ros-middleware-300x259.png 300w" sizes="(max-width: 557px) 100vw, 557px" /></h2>
<h2>Was ist DDS</h2>
<p>Data Distribution Service (DDS) ist ein Standard der Object Management Group und wurde 2004 mit der Version 1.0 veröffentlicht.</p>
<p>Mit ROS 2 wurde eine Middleware-Abstraktionsschicht eingeführt, die standardmäßig DDS nutzt, um Skalierbarkeit, Fehlertoleranz und Echtzeitfähigkeit zu verbessern.</p>
<h2>FastDDS vs Cyclone DDS</h2>
<p>Fast DDS (rmw_fastrtps_cpp) ist ab Foxy Fitzroy (2020) die standardmäßig verwendete Middleware (RMW)-Implementierung in ROS 2, was bedeutet, dass es automatisch in jeder ROS 2 Distribution (LTS und Non-LTS) enthalten ist. Die ROS-2-Community empfiehlt aber den Einsatz von Cyclone DDS aus folgenden Gründen:</p>
<ul>
<li>Weniger Discovery-Bugs</li>
<li>Weniger „mysteriöse“ Kommunikationsprobleme</li>
<li>Besseres Verhalten bei:
<ul>
<li>vielen Nodes</li>
<li>wechselnden Netzwerken</li>
<li>Simulation + Hardware parallel</li>
</ul>
</li>
</ul>
<p>Sehr gutes Verhalten auf:</p>
<ul>
<li>Embedded</li>
<li>ARM</li>
<li>Realtime-Systemen</li>
</ul>
<h2>Installation CycloneDDS</h2>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo apt install ros-&lt;ros_distro&gt;-rmw-cyclonedds-cpp</code></pre>
</div>
<p>Für Humble:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo apt install ros-humble-rmw-cyclonedds-cpp</code></pre>
</div>
<p>Wechseln kannst du über die Umgebungsvariable, die Du am besten direkt in deine bashrc hinzufügst:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp</code></pre>
</div>
<h2>Installation testen</h2>
<p>In Terminal 1 startest Du einen Demo-Node:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 run demo_nodes_cpp talker</code></pre>
</div>
<p>In Terminal 2 rufst du den ROS-Doktor:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 doctor --report</code></pre>
</div>
<p>Jetzt solltest Du folgenden Output sehen:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>RMW MIDDLEWARE 
middleware name : rmw_cyclonedds_cpp</code></pre>
</div>
<h2>Quellcode</h2>
<p><a href="https://github.com/eclipse-cyclonedds/cyclonedds">https://github.com/eclipse-cyclonedds/cyclonedds</a></p>
<h2>Weiterlesen</h2>
<p><a href="https://design.ros2.org/articles/ros_middleware_interface.html">https://design.ros2.org/articles/ros_middleware_interface.html</a></p>
<p>The post <a href="https://creatronix.de/so-ersetzt-du-fastdds-mit-cyclone-dds/">So ersetzt Du FastDDS mit Cyclone DDS</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>So schreibst Du Pakete und Nodes in ROS2</title>
		<link>https://creatronix.de/so-schreibst-du-pakete-und-nodes-in-ros/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Fri, 02 Jan 2026 14:30:40 +0000</pubDate>
				<category><![CDATA[Robotics]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7797</guid>

					<description><![CDATA[<p>Motivation Nachdem wir in den letzten Teilen ROS 2 und die Kamera auf dem Raspberry zum Laufen gebracht haben, widmen wir uns nun der Erstellung von Paketen und Nodes. Voraussetzungen Build-Tool: colcon Damit wir Pakete bauen können, benötigen wir noch ein Buildtool. In ROS 2 löst colcon catkin als Buildtool ab. Wir installieren es mit:&#8230;</p>
<p>The post <a href="https://creatronix.de/so-schreibst-du-pakete-und-nodes-in-ros/">So schreibst Du Pakete und Nodes in ROS2</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Motivation</h2>
<p>Nachdem wir in den letzten Teilen <a href="https://creatronix.de/so-installierst-du-ros-2-auf-dem-raspberry-pi-ball-chaser-mit-ros2/">ROS 2</a> und die <a href="https://creatronix.de/so-benutzt-du-die-kamera-unter-ros2/">Kamera</a> auf dem Raspberry zum Laufen gebracht haben, widmen wir uns nun der Erstellung von Paketen und Nodes.</p>
<h2>Voraussetzungen</h2>
<h3>Build-Tool: colcon</h3>
<p>Damit wir Pakete bauen können, benötigen wir noch ein Buildtool. In ROS 2 löst colcon catkin als Buildtool ab.<br />
Wir installieren es mit:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo apt install python3-colcon-common-extensions</code></pre>
</div>
<p>Damit wir Tab-Completion für colcon-Befehle erhalten, fügen wir folgende Zeile in unsere .bashrc ein:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash</code></pre>
</div>
<h3>ROS-2-Python-Abhängigkeiten</h3>
<p>Damit wir mit Python Nodes erstellen können, benötigen wir noch die Pakete <code>rclpy</code> und <code>std_msgs</code></p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo apt install ros-humble-rclpy
sudo apt install ros-humble-std-msgs</code></pre>
</div>
<p>Da rclpy Paket ist die Python Client Library für ROS; std-msgs hilft uns Nachrichten zwischen Nodes senden und empfangen zu können.</p>
<h2>Eigenes Paket erstellen</h2>
<p>Wir wollen zuerst ein einfaches Paket mit zwei Nodes schreiben, um den publish-subscriber-Mechanismus kennenzulernen:<br />
Pakete sollten in ROS immer in einem src-Ordner liegen:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>cd ~/akiro
mkdir ./src
cd ./src</code></pre>
</div>
<p>Jetzt erzeugen wir ein neues Python-Paket:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 pkg create my_first_package --build-type ament_python --dependencies rclpy</code></pre>
</div>
<h3>Sanity-Check</h3>
<p>Auch wenn das Paket noch leer ist, sollte es bereits baubar sein:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>cd ~/akiro
colcon build</code></pre>
</div>
<p>Wenn keine Fehler auftreten, ist das Setup korrekt.</p>
<h2>Nodes schreiben</h2>
<p>Nodes sind die ausführbaren Programme in ROS 2.</p>
<p>Man kann damit die Komplexität reduzieren, indem man Roboterprojekte in kleine, unabhängige Prozesse aufteilt. Nodes kapseln Funktionalität und kommunizieren über klar definierte Schnittstellen.</p>
<p>Nodes können in verschiedenen Sprachen geschrieben werden. (Derzeit Python und C++, Rust ist auf dem Weg) Wir wählen für unsere ersten Gehversuche Python, da es einfach zu lernen ist. Wir schreiben zwei nodes: einen Publisher und einen Subscriber</p>
<h3>Publisher</h3>
<p>Wir wechseln in das Python-Package my_first_package</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>cd src/my_first_package/my_first_package</code></pre>
</div>
<p>Wir erstellen eine Datei publisher.py</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>touch publisher.py</code></pre>
</div>
<p>und fügen folgenden Code ein:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class MinimalPublisher(Node):

def __init__(self):
    super().__init__('minimal_publisher')
    self.publisher = self.create_publisher(String, '/topic', 10)
    timer_period = 2.0  # Sekunden
    self.timer = self.create_timer(timer_period, self.timer_callback)

def timer_callback(self):
    msg = String()
    msg.data = 'Hello, from my first ROS 2 publisher node'
    self.publisher.publish(msg)
    self.get_logger().info('Publishing: "%s"' % msg.data)


def main(args=None):
    rclpy.init(args=args)
    minimal_publisher = MinimalPublisher()
    rclpy.spin(minimal_publisher)
    minimal_publisher.destroy_node()
    rclpy.shutdown()

if name == 'main':
    main()

</code></pre>
</div>
<p>Was passiert hier?</p>
<ul>
<li>Der Node sendet alle 2 Sekunden eine String-Nachricht</li>
<li>Das Topic heißt /talker_topic</li>
<li>Die Queue-Größe (10) ist für einfache Tests völlig ausreichend</li>
</ul>
<h3>Subscriber</h3>
<p>Für den Subscriber erstellen wir eine Datei subscriber.py im gleichen Ordner und fügen folgenden Code ein:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class MinimalSubscriber(Node):

def __init__(self):
    super().__init__('minimal_subscriber')
    self.subscription = self.create_subscription(
        String,
        '/topic',
        self.listener_callback,
        10)
    self.subscription # prevent unused variable warning

def listener_callback(self, msg):
    self.get_logger().info('I heard: "%s"' % msg.data)


def main(args=None):
    rclpy.init(args=args)
    minimal_subscriber = MinimalSubscriber()
    rclpy.spin(minimal_subscriber)
    minimal_subscriber.destroy_node()
    rclpy.shutdown()

if name == 'main':
    main()</code></pre>
</div>
<p>&nbsp;</p>
<p>Der Subscriber lauscht auf dem gleichen Topic und gibt empfangene Nachrichten aus.</p>
<h2>setup.py anpassen</h2>
<p>Damit ROS 2 unsere Nodes als Programme kennt, müssen sie in der setup.py registriert werden:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>'console_scripts': [
'talker = my_first_package.publisher:main',
'listener = my_first_package.subscriber:main',
],</code></pre>
</div>
<h2>Paket bauen</h2>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>cd ~/akiro
colcon build</code></pre>
</div>
<h2>Nodes starten</h2>
<p>Im ersten Terminal kannst du nun folgendes eingeben:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>source install/setup.bash
ros2 run my_first_package talker</code></pre>
</div>
<p>Im zweiten Terminal:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>source install/setup.bash
ros2 run my_first_package listener</code></pre>
</div>
<h2><img decoding="async" src="https://creatronix.de/wp-content/uploads/2026/01/talker-listener-1024x555.png" alt="" width="1024" height="555" class="alignnone size-large wp-image-7793" srcset="https://creatronix.de/wp-content/uploads/2026/01/talker-listener-1024x555.png 1024w, https://creatronix.de/wp-content/uploads/2026/01/talker-listener-300x163.png 300w, https://creatronix.de/wp-content/uploads/2026/01/talker-listener-768x416.png 768w, https://creatronix.de/wp-content/uploads/2026/01/talker-listener-1536x833.png 1536w, https://creatronix.de/wp-content/uploads/2026/01/talker-listener.png 1787w" sizes="(max-width: 1024px) 100vw, 1024px" />Kommunikation zwischen Nodes</h2>
<h3>Publisher / Subscriber</h3>
<p>Den Publisher / Subscriber-Mechanismus haben wir jetzt kennengelernt.<br />
Er eignet sich für asynchrone, kontinuierliche Datenströme z. B. Kamera-Bilder, Sensordaten, Steuerbefehle</p>
<h3>Services</h3>
<p>sind ein weiteres Kommunikations-Protokoll in ROS nach Request / Response-Prinzip z. B. „Starte Motor“, „Setze Parameter“</p>
<h3>Actions</h3>
<p>eignen sich für langlaufende Aufgaben mit Feedback wie z. B. Navigation, Greifbewegungen</p>
<h3>Kommunikation zwischen Nodes visualisieren</h3>
<p>Um die Kommunikation zwischen den Nodes zu visualisieren, kannst du das Tool <code>rqt_graph</code> verwenden:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 run rqt_graph rqt_graph</code></pre>
</div>
<p><img decoding="async" src="https://creatronix.de/wp-content/uploads/2026/01/rqt-graph-1024x610.png" alt="" width="1024" height="610" class="alignnone size-large wp-image-7794" srcset="https://creatronix.de/wp-content/uploads/2026/01/rqt-graph-1024x610.png 1024w, https://creatronix.de/wp-content/uploads/2026/01/rqt-graph-300x179.png 300w, https://creatronix.de/wp-content/uploads/2026/01/rqt-graph-768x457.png 768w, https://creatronix.de/wp-content/uploads/2026/01/rqt-graph-1536x914.png 1536w, https://creatronix.de/wp-content/uploads/2026/01/rqt-graph.png 1596w" sizes="(max-width: 1024px) 100vw, 1024px" />Hier siehst du:</p>
<ul>
<li>Nodes (Ovale)</li>
<li>Topics (Rechtecke)</li>
<li>Datenfluss zwischen Publisher und Subscriber</li>
</ul>
<h2>Fazit</h2>
<p>Du kannst jetzt:</p>
<ul>
<li>ROS-2-Pakete erstellen</li>
<li>Python-Nodes schreiben</li>
<li>Publisher &amp; Subscriber verbinden</li>
<li>Nodes bauen und starten</li>
<li>die Kommunikation visualisieren</li>
</ul>
<h2>Code</h2>
<p><a href="https://github.com/jboegeholz/akiro/tree/main/src/my_first_package/my_first_package">https://github.com/jboegeholz/akiro/tree/main/src/my_first_package/my_first_package</a></p>
<p>The post <a href="https://creatronix.de/so-schreibst-du-pakete-und-nodes-in-ros/">So schreibst Du Pakete und Nodes in ROS2</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AKIRO &#8211; Roboter-Lernprojekt</title>
		<link>https://creatronix.de/akiro-roboter-lernprojekt/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Fri, 02 Jan 2026 12:31:53 +0000</pubDate>
				<category><![CDATA[Robotics]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7778</guid>

					<description><![CDATA[<p>Motivation Nachbau eines Turtlebot als Open Source Software + Hardware Projekt ROS 2 Basics So installierst Du ROS 2 auf dem Raspberry Pi So benutzt du die Kamera unter ROS2 So schreibst du Launch-Dateien für deinen Roboter Teleop Twist Keyboard So steuerst du deinen Roboter mit dem Gamepad Motoren So setzt du beim Dynamixel XL430&#8230;</p>
<p>The post <a href="https://creatronix.de/akiro-roboter-lernprojekt/">AKIRO &#8211; Roboter-Lernprojekt</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Motivation</h2>
<p>Nachbau eines Turtlebot als Open Source Software + Hardware Projekt</p>
<h2>ROS 2 Basics</h2>
<p><a href="https://creatronix.de/so-installierst-du-ros-2-auf-dem-raspberry-pi-ball-chaser-mit-ros2/">So installierst Du ROS 2 auf dem Raspberry Pi</a></p>
<p><a href="https://creatronix.de/so-benutzt-du-die-kamera-unter-ros2/">So benutzt du die Kamera unter ROS2</a></p>
<p><a href="https://creatronix.de/so-schreibst-du-launch-dateien-fuer-deinen-roboter/">So schreibst du Launch-Dateien für deinen Roboter</a></p>
<p><a href="https://creatronix.de/teleop-twist-keyboard-diese-ros-pakete-solltest-du-kennen/">Teleop Twist Keyboard</a></p>
<p><a href="https://creatronix.de/so-steuerst-du-den-roboter-mit-dem-gamepad/">So steuerst du deinen Roboter mit dem Gamepad</a></p>
<h2>Motoren</h2>
<p><a href="https://creatronix.de/so-setzt-du-beim-dynamixel-xl430-die-id/">So setzt du beim Dynamixel XL430 die ID</a></p>
<p><a href="https://creatronix.de/so-steuerst-du-den-dynamixel-xl430-mit-dem-arduino-an/">So steuerst Du den Dynamixel XL430 mit dem Arduino an</a></p>
<h2>Ball Chaser</h2>
<p><a href="https://creatronix.de/so-verwendest-du-den-simpleblobdetector-von-opencv/">So verwendest du den SimpleBlobDetector von opencv</a></p>
<h2>LiDaR</h2>
<p><a href="https://creatronix.de/so-verwendest-du-das-slamtec-lidar-in-ros/">So verwendest Du das Slamtec Lidar in ROS</a></p>
<h2>Troubleshooting / Tipps und Tricks</h2>
<p><a href="https://creatronix.de/how-to-install-vs-code-on-ubuntu-for-arm64/">How to install VS Code on Ubuntu for arm64</a></p>
<p><a href="https://creatronix.de/so-kontrollierst-du-die-cpu-temperatur-am-raspberry-pi/">So kontrollierst du die CPU Temperatur am Raspberry Pi</a></p>
<p><a href="https://creatronix.de/ros2-cli-cheat-sheet/">ROS2 CLI Cheat Sheet</a></p>
<p><a href="https://creatronix.de/turtle-nest-diese-ros-pakete-solltest-du-kennen/">Turtle-Nest &#8211; Diese ROS-Pakete solltest du kennen</a></p>
<p><a href="https://creatronix.de/so-funktionieren-lifecycle-nodes-in-ros/">So funktionieren Lifecycle-Nodes in ROS2</a></p>
<p><a href="https://creatronix.de/rqt-diese-ros-pakete-solltest-du-kennen/">RQt &#8211; Diese ROS Pakete solltest du kennen</a></p>
<h2>Code</h2>
<p><a href="https://github.com/jboegeholz/akiro">https://github.com/jboegeholz/akiro</a></p>
<p>The post <a href="https://creatronix.de/akiro-roboter-lernprojekt/">AKIRO &#8211; Roboter-Lernprojekt</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>So funktionieren structs in Python</title>
		<link>https://creatronix.de/so-funktionieren-structs-in-python/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Sun, 16 Nov 2025 08:34:09 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Robotics]]></category>
		<category><![CDATA[Software Engineering & Programming]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7678</guid>

					<description><![CDATA[<p>Motivation Wenn man Daten über eine serielle Schnittstelle zwischen z.b Raspberry Pi und einem Arduino schicken will, ergibt es Sinn, sich über das Format Gedanken zu machen. Angenommen wir wollen einen Drehzahlwert von 60 RPM jeweils für die linke und rechte Seite übertragen. Standardmäßig verschickt eine Bibliothek wie pyserial ASCII-Zeichen, dass heißt eine Zahl wie&#8230;</p>
<p>The post <a href="https://creatronix.de/so-funktionieren-structs-in-python/">So funktionieren structs in Python</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Motivation</h2>
<p>Wenn man Daten über eine serielle Schnittstelle zwischen z.b Raspberry Pi und einem Arduino schicken will,<br />
ergibt es Sinn, sich über das Format Gedanken zu machen. Angenommen wir wollen einen Drehzahlwert von 60 RPM jeweils für die linke und rechte Seite übertragen.<br />
Standardmäßig verschickt eine Bibliothek wie pyserial ASCII-Zeichen, dass heißt eine Zahl wie 60 würde als zwei Byte ASCII übertragen. Das sind doppelt so viele Daten wie benötigt würden, wenn wir die Zahl als Integer übertragen. Hier kommen structs ins Spiel.</p>
<h2>struct for the rescue</h2>
<p>Mit dem struct Modul in Python können wir Binärdaten in einem bestimmten Format packen und entpacken.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>def test_struct_b():
    assert struct.pack('b', 1) == b'\x01'
    assert struct.pack('b', 127) == b'\x7f'
    assert struct.pack('b', -128) == b'\x80'
</code></pre>
</div>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>def test_unpack_b():
    packed = struct.pack('b', 127)
    unpacked = struct.unpack('b', packed)[0]
    assert unpacked == 127
</code></pre>
</div>
<h2>Mehrere Variablen</h2>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>def test_struct_bb():
    msg = struct.pack('bb', int(60), int(60))
    assert msg == b'\x3C\x3C'
</code></pre>
</div>
<h2>Fallstricke</h2>
<p>Damit die Empfängerseite die Daten auch wieder korrekt entpacken kann, muss natürlich das Format beachtet werden.</p>
<p>Achtet dementsprechend auf gute Dokumentation und versioniert idelaerweise die Dateien für die Datenübertragung in den gleichen Commits.</p>
<h2>Datentypen</h2>
<p>In structs können verschiedene Datentypen verwendet werden:<br />
Tabelle der wichtigsten Datentypen:</p>
<table border="1">
<thead>
<tr>
<th>Zeichen</th>
<th>Datentyp</th>
<th>Wertebereich</th>
</tr>
</thead>
<tbody>
<tr>
<td>b</td>
<td>signed char (1 byte)</td>
<td>-128 bis 127</td>
</tr>
<tr>
<td>B</td>
<td>unsigned char (1 byte)</td>
<td>0 bis 255</td>
</tr>
<tr>
<td>h</td>
<td>signed short (2 bytes)</td>
<td>-32768 bis 32767</td>
</tr>
<tr>
<td>H</td>
<td>unsigned short (2 bytes)</td>
<td>0 bis 65535</td>
</tr>
<tr>
<td>i</td>
<td>signed int (4 bytes)</td>
<td>-2147483648 bis 2147483647</td>
</tr>
<tr>
<td>I</td>
<td>unsigned int (4 bytes)</td>
<td>0 bis 4294967295</td>
</tr>
<tr>
<td>f</td>
<td>float (4 bytes)</td>
<td>IEEE</td>
</tr>
<tr>
<td>d</td>
<td>double (8 bytes)</td>
<td>IEEE</td>
</tr>
</tbody>
</table>
<h2>Pretty hex</h2>
<p>Wenn man die Darstellung der Zahlen auf der Konsole oder im Log etwas aufhübschen will:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>def test_pretty_hex():
    msg = struct.pack('&gt;I', 2864434397)
    pretty_hex = ' '.join(f'{b:02x}' for b in msg)
    assert pretty_hex == "aa bb cc dd"</code></pre>
</div>
<p>The post <a href="https://creatronix.de/so-funktionieren-structs-in-python/">So funktionieren structs in Python</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>So schreibst du Launch-Dateien für deinen Roboter</title>
		<link>https://creatronix.de/so-schreibst-du-launch-dateien-fuer-deinen-roboter/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Wed, 01 Oct 2025 20:03:01 +0000</pubDate>
				<category><![CDATA[Robotics]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7576</guid>

					<description><![CDATA[<p>Motivation Wenn du schon einmal mehr als zwei ROS-Nodes gleichzeitig in mehreren Terminals starten musstest, ist jetzt ein guter Zeitpunkt, etwas über Launch-Dateien zu lernen. Launch-Dateien in ROS 2 sind Python-Dateien, die die Konfiguration und das gleichzeitige Starten mehrerer Nodes strukturieren. Voraussetzungen Um launch files zu schreiben, benötigen wir das Paket roslaunch. Dieses installieren wir&#8230;</p>
<p>The post <a href="https://creatronix.de/so-schreibst-du-launch-dateien-fuer-deinen-roboter/">So schreibst du Launch-Dateien für deinen Roboter</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Motivation</h2>
<p>Wenn du schon einmal mehr als zwei ROS-Nodes gleichzeitig in mehreren Terminals starten musstest, ist jetzt ein guter Zeitpunkt, etwas über Launch-Dateien zu lernen.<br />
Launch-Dateien in ROS 2 sind Python-Dateien, die die Konfiguration und das gleichzeitige Starten mehrerer Nodes strukturieren.</p>
<h2>Voraussetzungen</h2>
<p>Um launch files zu schreiben, benötigen wir das Paket <code>roslaunch</code>. Dieses installieren wir mit:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo apt install ros-humble-launch ros-humble-launch-ros</code></pre>
</div>
<h2>Einfaches Beispiel</h2>
<p>Per Konvention liegen Launch-Dateien im <code>launch</code>-Ordner des jeweiligen Paketes.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>cd ~/ros_ws/src/my_first_package
mkdir launch
cd launch
touch my_first.launch.py
</code></pre>
</div>
<h3>Inhalt</h3>
<p>Eine minimale Launch-Datei kann so aussehen:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>from launch import LaunchDescription
import launch

def generate_launch_description():
    ld = LaunchDescription()
    logger = launch.logging.get_logger('my_launch_file')
    logger.info("Hello from my launch file")
    return ld
</code></pre>
</div>
<p>Charmant! Wir benötigen lediglich die Funktion generate_launch_description, die ein Objekt vom Typ LaunchDescription zurückgibt.</p>
<h3>setup.py</h3>
<p>Damit die Launch-Dateien auch aufrufbar werden, müssen sie wie Nodes im setup.py eingetragen werden.<br />
Empfehlung: um nicht jede Launch-Datei einzeln angeben zu müssen, kann das glob-Modul verwendet werden.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>import os
from glob import glob
setup(
    ..
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        (os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),
    ],
    ..
)</code></pre>
</div>
<h3>Starten</h3>
<p>Wenn wir jetzt colcon build und source install/setup.bash gemacht haben, können wir das launch file mit ros2 launch starten.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 launch my_first_package my_first.launch.py 
[INFO] [launch]: All log files can be found below /home/jboegeholz/.ros/log/2025-10-01-21-03-44-500932-Ubuntu22-8545 
[INFO] [launch]: Default logging verbosity is set to INFO 
[INFO] [python_launch_file]: Hello from my launch file</code></pre>
</div>
<h2>Einen Node starten</h2>
<p>Statt einen Node manuell über die CLI zu starten wie:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 run demo_nodes_py talker</code></pre>
</div>
<p>kannst du ihn in eine Launch-Datei integrieren.</p>
<p>Im Launch file müssen wir dafür 3 Dinge tun:<br />
1. Inkludieren der Node-Klasse<br />
2. Instantiieren eines Nodes mit dem package und executable Namen.<br />
3. Mit der add_action-Methode den node zur LaunchDescription hinzufügen</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    ld = LaunchDescription()

    publisher_node = Node(
            package='demo_nodes_py',
            executable='talker',
            output='screen'
        )
    ld.add_action(publisher_node)
    return ld
</code></pre>
</div>
<h3>name-Parameter</h3>
<p>Wenn du denselben Node mehrfach starten möchtest, kannst du ihn über den Parameter <code>name</code> eindeutig benennen:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>def generate_launch_description():
    ld = LaunchDescription()

    publisher_node_1 = Node(
            package='demo_nodes_py',
            executable='talker',
            name='noisy',
            output='screen'
        )
    publisher_node_2 = Node(
            package='demo_nodes_py',
            executable='talker',
            name='rowdy',
            output='screen'
        )
    ld.add_action(publisher_node_1)
    ld.add_action(publisher_node_2)
    return ld</code></pre>
</div>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 launch my_first_package multiple_publisher.launch.py
[INFO] [launch]: All log files can be found below /home/jboegeholz/.ros/log/2025-10-01-21-04-35-427546-Ubuntu22-8559 
[INFO] [launch]: Default logging verbosity is set to INFO 
[INFO] [talker-1]: process started with pid [8560] 
[INFO] [talker-2]: process started with pid [8562] [talker-1] 
[INFO] [1759345476.604967867] [noisy]: Publishing: "Hello World: 0" [talker-2] 
[INFO] [1759345476.607008668] [rowdy]: Publishing: "Hello World: 0" [talker-2] 
[INFO] [1759345477.596242658] [rowdy]: Publishing: "Hello World: 1" [talker-1] 
[INFO] [1759345477.596370980] [noisy]: Publishing: "Hello World: 1" [talker-2] </code></pre>
</div>
<h2>Launch-Dateien inkludieren</h2>
<p>Du kannst Launch-Dateien modular aufbauen, indem du sie einbindest:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>ld = LaunchDescription()

package_dir = get_package_share_directory('my_first_package')
publisher_launch_path = os.path.join(package_dir, 'launch', 'publisher.launch.py')
publisher_launch_description = IncludeLaunchDescription(PythonLaunchDescriptionSource(publisher_launch_path))
ld.add_action(publisher_launch_description)
</code></pre>
</div>
<h2>Konfigurationsdateien an Nodes übergeben</h2>
<p>Viele Nodes benötigen YAML-Konfigurationsdateien. Beispiel mit <code>twist_mux</code>:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>def generate_launch_description():
    ld = LaunchDescription()
    package_path = get_package_share_directory('my_first_package')
    twist_mux_config_file_path = os.path.join(package_path, 'config', 'twist_mux.yaml')

    twist_mux = Node(
        package='twist_mux',
            executable='twist_mux',
                name='twist_mux',
                output='screen',
                parameters=[twist_mux_config_file_path]
            )

    ld.add_action(twist_mux)
    return ld
</code></pre>
</div>
<h2>Shell-Kommandos</h2>
<p>Du kannst auch Shell-Kommandos in Launch-Dateien ausführen:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>from launch import LaunchDescription
from launch.actions import ExecuteProcess

def generate_launch_description():
    return LaunchDescription([
        ExecuteProcess(
            cmd=["echo", "Hello from the shell!"],
            output="screen"
        ),
    ])
</code></pre>
</div>
<h2>Fazit</h2>
<p>Launch-Dateien ermöglichen dir die strukturierte, wiederholbare und konfigurierbare Steuerung von ROS-2-Systemen.<br />
Sie sind essenziell für größere Projekte – lokal wie auch in der Simulation oder auf echten Robotern.</p>
<p>The post <a href="https://creatronix.de/so-schreibst-du-launch-dateien-fuer-deinen-roboter/">So schreibst du Launch-Dateien für deinen Roboter</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>So funktionieren Lifecycle-Nodes in ROS2</title>
		<link>https://creatronix.de/so-funktionieren-lifecycle-nodes-in-ros/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Sat, 27 Sep 2025 07:58:16 +0000</pubDate>
				<category><![CDATA[Robotics]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7567</guid>

					<description><![CDATA[<p>Motivation Nodes sind in ROS die wichtigsten Bausteine, da sie Sensoren und Aktoren in der Software abstrahieren. In ROS 1 waren Nodes einfach „da“. Sobald sie mit rosrun gestartet wurden, liefen sie. Stoppen bzw. Pausieren konnte man sie nur über Signale wie SIGINT (STRG + C) oder SIGTSTP (STRG + Z) In ROS 2 ermöglichen&#8230;</p>
<p>The post <a href="https://creatronix.de/so-funktionieren-lifecycle-nodes-in-ros/">So funktionieren Lifecycle-Nodes in ROS2</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Motivation</h2>
<p>Nodes sind in ROS die wichtigsten Bausteine, da sie Sensoren und Aktoren in der Software abstrahieren.<br />
In ROS 1 waren Nodes einfach „da“. Sobald sie mit rosrun gestartet wurden, liefen sie. Stoppen bzw. Pausieren konnte man sie nur über Signale wie<br />
SIGINT (STRG + C) oder SIGTSTP (STRG + Z)<br />
In ROS 2 ermöglichen Lifecycle Nodes eine genaueer Steuerung. Man kann nun:</p>
<ul>
<li>Nodes nur aktivieren, wenn sie bereit sind</li>
<li>Parameter vor der Aktivierung laden</li>
<li>Knoten schrittweise prüfen</li>
<li>Nodes ohne Neustart zurücksetzen oder neu starten</li>
</ul>
<p>Ein Lifecycle-Node hat folgende 4 Zustände:</p>
<ul>
<li>Unconfigured</li>
<li>Inactive</li>
<li>Active</li>
<li>Finalized</li>
</ul>
<h2><img decoding="async" src="https://creatronix.de/wp-content/uploads/2025/09/ros-lifecycle.png" alt="" width="402" height="694" class="alignnone size-full wp-image-7566" srcset="https://creatronix.de/wp-content/uploads/2025/09/ros-lifecycle.png 402w, https://creatronix.de/wp-content/uploads/2025/09/ros-lifecycle-174x300.png 174w" sizes="(max-width: 402px) 100vw, 402px" /></h2>
<h2>Zustände über CLI ändern</h2>
<p>Die Zustandsübergänge lassen sich via CLI triggern.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>ros2 lifecycle set /my_lifecycle_node configure 
ros2 lifecycle set /my_lifecycle_node activate 
ros2 lifecycle set /my_lifecycle_node deactivate 
ros2 lifecycle set /my_lifecycle_node shutdown</code></pre>
</div>
<h2>Code</h2>
<p>Ein eigener kleiner LifecycleNode kann so implementiert werden:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>import rclpy
from rclpy.lifecycle import LifecycleNode
from rclpy.lifecycle import State
from rclpy.lifecycle import TransitionCallbackReturn

class MyLifecycleNode(LifecycleNode):

    def __init__(self):
        super().__init__('my_lifecycle_node')

    def on_configure(self, state: State) -&gt; TransitionCallbackReturn:
        self.get_logger().info('Configuring...')
        return TransitionCallbackReturn.SUCCESS

    def on_activate(self, state: State) -&gt; TransitionCallbackReturn:
        self.get_logger().info('Activating...')
        return TransitionCallbackReturn.SUCCESS

    def on_deactivate(self, state: State) -&gt; TransitionCallbackReturn:
        self.get_logger().info('Deactivating...')
        return TransitionCallbackReturn.SUCCESS

    def on_cleanup(self, state: State) -&gt; TransitionCallbackReturn:
        self.get_logger().info('Cleaning up...')
        return TransitionCallbackReturn.SUCCESS

    def on_shutdown(self, state: State) -&gt; TransitionCallbackReturn:
        self.get_logger().info('Shutting down...')
        return TransitionCallbackReturn.SUCCESS

def main(args=None):
    rclpy.init(args=args)
    node = MyLifecycleNode()
    rclpy.spin(node)
    rclpy.shutdown()

if __name__ == '__main__':
    main()</code></pre>
</div>
<p>The post <a href="https://creatronix.de/so-funktionieren-lifecycle-nodes-in-ros/">So funktionieren Lifecycle-Nodes in ROS2</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>RQt &#8211; Diese ROS Pakete solltest du kennen</title>
		<link>https://creatronix.de/rqt-diese-ros-pakete-solltest-du-kennen/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Sun, 07 Sep 2025 20:24:39 +0000</pubDate>
				<category><![CDATA[Robotics]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7530</guid>

					<description><![CDATA[<p>Warum RQt? Wenn du mit ROS2 arbeitest, wirst du früher oder später auf ein Tool namens RQt stoßen. Der Name steht für &#8220;ROS Qt&#8221; – und genau das ist es auch: eine Qt-basierte GUI-Sammlung, die verschiedene Werkzeuge modular integriert. Egal ob Debugging, Visualisierung oder Testen – RQt bietet dir viele praktische Funktionen direkt per Mausklick.&#8230;</p>
<p>The post <a href="https://creatronix.de/rqt-diese-ros-pakete-solltest-du-kennen/">RQt &#8211; Diese ROS Pakete solltest du kennen</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Warum RQt?</h2>
<p>Wenn du mit ROS2 arbeitest, wirst du früher oder später auf ein Tool namens RQt stoßen.<br />
Der Name steht für &#8220;ROS Qt&#8221; – und genau das ist es auch: eine Qt-basierte GUI-Sammlung,<br />
die verschiedene Werkzeuge modular integriert.<br />
Egal ob Debugging, Visualisierung oder Testen – RQt bietet dir viele praktische Funktionen direkt per Mausklick.</p>
<h2>Installation</h2>
<p>Wie bei den meisten ROS-Paketen kannst du RQt unter Ubuntu über apt installieren.</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>sudo apt update 
sudo apt install ros-&lt;ros2-distro&gt;-rqt*</code></pre>
</div>
<p>Ersetze <ros2-distro> mit deiner installierten ROS2-Distribution, z. B. humble, jazzy oder rolling.</ros2-distro></p>
<h2>RQt starten</h2>
<p>RQt lässt sich ganz einfach starten mit:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>rqt</code></pre>
</div>
<p>Nach dem Start erscheint das RQt-Hauptfenster – anfangs noch leer, aber bereit für Plugins.</p>
<p>&nbsp;</p>
<h2><img decoding="async" src="https://creatronix.de/wp-content/uploads/2025/09/01-rqt-default-screen.png" alt="" width="992" height="864" class="alignnone size-full wp-image-7525" srcset="https://creatronix.de/wp-content/uploads/2025/09/01-rqt-default-screen.png 992w, https://creatronix.de/wp-content/uploads/2025/09/01-rqt-default-screen-300x261.png 300w, https://creatronix.de/wp-content/uploads/2025/09/01-rqt-default-screen-768x669.png 768w" sizes="(max-width: 992px) 100vw, 992px" /></h2>
<h2>Konsole überwachen (Console Monitoring)</h2>
<p>Sehr nützlich ist die integrierte Funktion, die ROS2-Konsolenausgaben zu monitoren:</p>
<h3><img decoding="async" src="https://creatronix.de/wp-content/uploads/2025/09/06-rqt-console-1024x714.png" alt="" width="1024" height="714" class="alignnone size-large wp-image-7523" srcset="https://creatronix.de/wp-content/uploads/2025/09/06-rqt-console-1024x714.png 1024w, https://creatronix.de/wp-content/uploads/2025/09/06-rqt-console-300x209.png 300w, https://creatronix.de/wp-content/uploads/2025/09/06-rqt-console-768x536.png 768w, https://creatronix.de/wp-content/uploads/2025/09/06-rqt-console.png 1323w" sizes="(max-width: 1024px) 100vw, 1024px" /></h3>
<h3>Menüpunkt</h3>
<pre>Plugins -&gt; Logging -&gt; Console
</pre>
<h2>Topic Monitor</h2>
<p>Alle aktiven Topics in deinem ROS2-Netzwerk kannst du mit dem Topic Monitor überwachen. Damit siehst du z. B. welche Daten gerade über</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>self.publisher = self.create_publisher(String, "robot_news", 10)</code></pre>
</div>
<p>gesendet werden.</p>
<pre><img decoding="async" src="https://creatronix.de/wp-content/uploads/2025/09/02-rqt-topic-monitor-1024x869.png" alt="" width="1024" height="869" class="alignnone size-large wp-image-7528" srcset="https://creatronix.de/wp-content/uploads/2025/09/02-rqt-topic-monitor-1024x869.png 1024w, https://creatronix.de/wp-content/uploads/2025/09/02-rqt-topic-monitor-300x255.png 300w, https://creatronix.de/wp-content/uploads/2025/09/02-rqt-topic-monitor-768x652.png 768w, https://creatronix.de/wp-content/uploads/2025/09/02-rqt-topic-monitor.png 1091w" sizes="(max-width: 1024px) 100vw, 1024px" /></pre>
<h3>Menüpunkt</h3>
<pre>Plugins -&gt; Topics -&gt; Topic Monitor
</pre>
<p>&nbsp;</p>
<h2>Nachrichten senden (Message Publisher)</h2>
<p>Natürlich kannst du auch selbst Nachrichten auf ein Topic publizieren – direkt aus der GUI heraus!</p>
<h3><img decoding="async" src="https://creatronix.de/wp-content/uploads/2025/09/04-message-publisher.png" alt="" width="961" height="837" class="alignnone size-full wp-image-7524" srcset="https://creatronix.de/wp-content/uploads/2025/09/04-message-publisher.png 961w, https://creatronix.de/wp-content/uploads/2025/09/04-message-publisher-300x261.png 300w, https://creatronix.de/wp-content/uploads/2025/09/04-message-publisher-768x669.png 768w" sizes="(max-width: 961px) 100vw, 961px" /></h3>
<h3>Menüpunkt</h3>
<pre>Plugins -&gt; Topics -&gt; Message Publisher</pre>
<p>&nbsp;</p>
<h2>Services aufrufen (Service Caller)</h2>
<p>Genauso einfach wie beim Publizieren von Messages kannst du mit RQt auch ROS2-Services aufrufen.<br />
Beispiel Service:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-python" data-lang="Python"><code>self.server = self.create_service(AddTwoInts, "add_two_ints", self.callback_add_two_ints)</code></pre>
<h3>Menüpunkt:</h3>
<pre>Plugins -&gt; Services -&gt; Service Caller</pre>
<p>&nbsp;</p>
<h2>Node Graph: Beziehungen visualisieren</h2>
<p>Mit dem Node Graph Plugin kannst du die Verbindungen zwischen Nodes, Publishern und Subscribern grafisch darstellen lassen.<br />
Extrem hilfreich für das Verständnis komplexer ROS-Systeme.</p>
<h3><img decoding="async" src="https://creatronix.de/wp-content/uploads/2025/09/07-rqt-node-graph-1024x714.png" alt="" width="1024" height="714" class="alignnone size-large wp-image-7527" srcset="https://creatronix.de/wp-content/uploads/2025/09/07-rqt-node-graph-1024x714.png 1024w, https://creatronix.de/wp-content/uploads/2025/09/07-rqt-node-graph-300x209.png 300w, https://creatronix.de/wp-content/uploads/2025/09/07-rqt-node-graph-768x536.png 768w, https://creatronix.de/wp-content/uploads/2025/09/07-rqt-node-graph.png 1323w" sizes="(max-width: 1024px) 100vw, 1024px" /></h3>
<h3>Menüpunkt:</h3>
<pre>Plugins -&gt; Introspection -&gt; Node Graph</pre>
<p>&nbsp;</p>
<h2>Perspectives: Ansichten speichern</h2>
<p>Wenn du dir deine bevorzugten Plugins und Fenster einmal zusammengestellt hast, kannst du diese Ansicht als sogenannte Perspective speichern. Praktisch für verschiedene Projekte oder Aufgaben!</p>
<h3>Menüpunkt:</h3>
<pre>Perspectives -&gt; Create Perspective</pre>
<h2>Reset: Wenn mal etwas klemmt</h2>
<p>Falls RQt mal zickt oder die Fenster verschoben sind, kannst du die Konfiguration zurücksetzen:</p>
<div class="hcb_wrap">
<pre class="prism line-numbers lang-bash" data-lang="Bash"><code>rqt --clear-config</code></pre>
</div>
<h2>Fazit</h2>
<p>RQt ist mehr als nur ein GUI-Tool – es ist ein echter Allrounder für ROS2-Entwickler:innen. Es hilft beim Debuggen,<br />
Visualisieren, Kommunizieren mit Nodes und beim Service-Testen. Wer sich einmal eingearbeitet hat, will es nicht mehr missen.</p>
</div>
<p>The post <a href="https://creatronix.de/rqt-diese-ros-pakete-solltest-du-kennen/">RQt &#8211; Diese ROS Pakete solltest du kennen</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>So machst du deinen Line Follower schneller</title>
		<link>https://creatronix.de/so-machst-du-deinen-line-follower-schneller/</link>
		
		<dc:creator><![CDATA[Jörn]]></dc:creator>
		<pubDate>Wed, 03 Sep 2025 08:22:15 +0000</pubDate>
				<category><![CDATA[Robotics]]></category>
		<guid isPermaLink="false">https://creatronix.de/?p=7509</guid>

					<description><![CDATA[<p>The post <a href="https://creatronix.de/so-machst-du-deinen-line-follower-schneller/">So machst du deinen Line Follower schneller</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe title="So machst du deinen Line Follower schneller" width="1200" height="675" src="https://www.youtube.com/embed/pdxI4QOfZ6g?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
<p>The post <a href="https://creatronix.de/so-machst-du-deinen-line-follower-schneller/">So machst du deinen Line Follower schneller</a> appeared first on <a href="https://creatronix.de">Creatronix</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
