BSE Moderne Tracking Systeme (SoSe 2026): Unterschied zwischen den Versionen
| (46 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 20: | Zeile 20: | ||
Der Autonome Mobile Roboter (AMR, AlphaBot) soll wie im Video gezeigt möglichst exakt die Ränder eines Quadrats abfahren. | Der Autonome Mobile Roboter (AMR, AlphaBot) soll wie im Video gezeigt möglichst exakt die Ränder eines Quadrats abfahren. | ||
{{#ev:youtube|https://www.youtube.com/watch?v=PWdxnERpynU | 720 | | Video: Mobile Robot Localisation |frame}} | {{#ev:youtube|https://www.youtube.com/watch?v=PWdxnERpynU | 720 | | Video: Mobile Robot Localisation |frame}} | ||
URL: https://www.youtube.com/watch?v=PWdxnERpynU | |||
Im Rahmen dieser Hausarbeit soll eine Sensorfusionslösung zur Navigation eines mobilen Roboters entwickelt und untersucht werden. | Im Rahmen dieser Hausarbeit soll eine Sensorfusionslösung zur Navigation eines mobilen Roboters entwickelt und untersucht werden. | ||
| Zeile 28: | Zeile 29: | ||
* Extended Kalman-Filter (EKF) | * Extended Kalman-Filter (EKF) | ||
* Unscented Kalman-Filter (UKF) | * Unscented Kalman-Filter (UKF) | ||
Die Verfahren sollen hinsichtlich Genauigkeit, Robustheit und Rechenaufwand verglichen werden. | Die Verfahren sollen hinsichtlich Genauigkeit, Robustheit und Rechenaufwand verglichen werden. | ||
| Zeile 45: | Zeile 45: | ||
* Arbeiten Sie sich anhand dieses Artikels in den [[AlphaBot]] ein. Sie benötigen lediglich die Ansteuerung der Motoren, das Auslesen der Inkrementalgeber und die Daten der [[IMU_MPU-9250/6500|IMU MPU 9250]]. | * Arbeiten Sie sich anhand dieses Artikels in den [[AlphaBot]] ein. Sie benötigen lediglich die Ansteuerung der Motoren, das Auslesen der Inkrementalgeber und die Daten der [[IMU_MPU-9250/6500|IMU MPU 9250]]. | ||
* Leihen Sie sich die Hardware für die Hausarbeit bei Prof. Schneider oder Marc Ebmeyer aus. | * Leihen Sie sich die Hardware für die Hausarbeit bei Prof. Schneider oder Marc Ebmeyer aus. | ||
* | * Machen Sie bei Fragen frühzeitig einen Termin mit Prof Schneider. | ||
* Binden Sie den Arduino Uno R4 Wifi in Ihre Wifi-Umgebung ein. Sie dürfen hierfür gern unser Labor verwenden. | * Binden Sie den Arduino Uno R4 Wifi in Ihre Wifi-Umgebung ein. Sie dürfen hierfür gern unser Labor verwenden. | ||
* Tragen Sie die WLAN-Zugangsdaten und die IP-Adresse des MATLAB-Rechners in die entsprechende Zeile ein. | * Tragen Sie die WLAN-Zugangsdaten und die IP-Adresse des MATLAB-Rechners in die entsprechende Zeile ein. | ||
| Zeile 51: | Zeile 51: | ||
* Versorgen Sie den Arduino Uno R4 mit Spannung (6 V-24 V). Die Daten werden nun gesendet. Die TX-LED blinkt kontinuierlich. | * Versorgen Sie den Arduino Uno R4 mit Spannung (6 V-24 V). Die Daten werden nun gesendet. Die TX-LED blinkt kontinuierlich. | ||
* Starten Sie <code>DemoUnoR4Wifi.m</code> auf dem PC. Die Daten <code>Zeit in s;Zähler</code> müssten nun empfangen und im <code>Command Window</code> dargestellt werden. | * Starten Sie <code>DemoUnoR4Wifi.m</code> auf dem PC. Die Daten <code>Zeit in s;Zähler</code> müssten nun empfangen und im <code>Command Window</code> dargestellt werden. | ||
* Sie sind nun startbereit! | * Gratulation! Sie sind nun startbereit! | ||
= Demos = | = Demos = | ||
{| class="wikitable" | |||
|+ Tabelle 1: Übersicht der Demos | |||
|- | |||
! Demo !! Funktion | |||
|- | |||
| DemoUnoR4Wifi.ino || Demo zum Senden von Sensordaten via Wifi für die Arduino IDE | |||
|- | |||
| DemoUnoR4Wifi.m || Demo zum Empfangen von Sensordaten via Wifi mit MATLAB<sup>®</sup> | |||
|- | |||
| GetDate.ino || Demo zum Auslesen der IMU-Daten des Sensors MPU 9250 | |||
|- | |||
| E15_RadInkrementalgeberFahrt.ino || Demo zum Ansteuern der Motoren und auslesen der Odometrie des AlphaBot | |||
|} | |||
{| role="presentation" class="wikitable mw-collapsible mw-collapsed" | |||
| <strong>DemoUnoR4Wifi.ino  </strong> | |||
|- | |||
| <source line lang="matlab" style="font-size:medium"> | |||
clear all; clc; | |||
port = 7000; % UDP Port, auf dem MATLAB lauscht | |||
u = udpport("IPV4", "LocalPort", port); | |||
disp("Warte auf UDP-Daten vom Arduino ...") | |||
while true | |||
nBytes = u.NumBytesAvailable; | |||
if nBytes > 0 % Prüfen, ob Daten vorhanden sind | |||
data = read(u, nBytes, "string"); | |||
disp(data) | |||
end | |||
end | |||
</source> | |||
|} | |||
{| role="presentation" class="wikitable mw-collapsible mw-collapsed" | |||
| <strong>GetDate.ino</strong> aus der Bibliothek MPU9250_asukiaaa  | |||
|- | |||
| <source line lang="C" style="font-size:medium">#include <MPU9250_asukiaaa.h> | |||
#ifdef _ESP32_HAL_I2C_H_ | |||
#define SDA_PIN 21 | |||
#define SCL_PIN 22 | |||
#endif | |||
MPU9250_asukiaaa mySensor; | |||
float aX, aY, aZ, aSqrt, gX, gY, gZ, mDirection, mX, mY, mZ; | |||
void setup() { | |||
Serial.begin(115200); | |||
while(!Serial); | |||
Serial.println("started"); | |||
#ifdef _ESP32_HAL_I2C_H_ // For ESP32 | |||
Wire.begin(SDA_PIN, SCL_PIN); | |||
mySensor.setWire(&Wire); | |||
#endif | |||
mySensor.beginAccel(); | |||
mySensor.beginGyro(); | |||
mySensor.beginMag(); | |||
// You can set your own offset for mag values | |||
// mySensor.magXOffset = -50; | |||
// mySensor.magYOffset = -55; | |||
// mySensor.magZOffset = -10; | |||
} | |||
void loop() { | |||
uint8_t sensorId; | |||
int result; | |||
result = mySensor.readId(&sensorId); | |||
if (result == 0) { | |||
Serial.println("sensorId: " + String(sensorId)); | |||
} else { | |||
Serial.println("Cannot read sensorId " + String(result)); | |||
} | |||
result = mySensor.accelUpdate(); | |||
if (result == 0) { | |||
aX = mySensor.accelX(); | |||
aY = mySensor.accelY(); | |||
aZ = mySensor.accelZ(); | |||
aSqrt = mySensor.accelSqrt(); | |||
Serial.println("accelX: " + String(aX)); | |||
Serial.println("accelY: " + String(aY)); | |||
Serial.println("accelZ: " + String(aZ)); | |||
Serial.println("accelSqrt: " + String(aSqrt)); | |||
} else { | |||
Serial.println("Cannod read accel values " + String(result)); | |||
} | |||
result = mySensor.gyroUpdate(); | |||
if (result == 0) { | |||
gX = mySensor.gyroX(); | |||
gY = mySensor.gyroY(); | |||
gZ = mySensor.gyroZ(); | |||
Serial.println("gyroX: " + String(gX)); | |||
Serial.println("gyroY: " + String(gY)); | |||
Serial.println("gyroZ: " + String(gZ)); | |||
} else { | |||
Serial.println("Cannot read gyro values " + String(result)); | |||
} | |||
result = mySensor.magUpdate(); | |||
if (result != 0) { | |||
Serial.println("cannot read mag so call begin again"); | |||
mySensor.beginMag(); | |||
result = mySensor.magUpdate(); | |||
} | |||
if (result == 0) { | |||
mX = mySensor.magX(); | |||
mY = mySensor.magY(); | |||
mZ = mySensor.magZ(); | |||
mDirection = mySensor.magHorizDirection(); | |||
Serial.println("magX: " + String(mX)); | |||
Serial.println("maxY: " + String(mY)); | |||
Serial.println("magZ: " + String(mZ)); | |||
Serial.println("horizontal direction: " + String(mDirection)); | |||
} else { | |||
Serial.println("Cannot read mag values " + String(result)); | |||
} | |||
Serial.println("at " + String(millis()) + "ms"); | |||
Serial.println(""); // Add an empty line | |||
delay(500); | |||
} | |||
</source> | |||
{| role="presentation" class="wikitable mw-collapsible mw-collapsed" | {| role="presentation" class="wikitable mw-collapsible mw-collapsed" | ||
| <strong>DemoUnoR4Wifi.m  </strong> | | <strong>DemoUnoR4Wifi.m  </strong> | ||
| Zeile 123: | Zeile 251: | ||
</source> | </source> | ||
|} | |} | ||
|} | |||
{| role="presentation" class="wikitable mw-collapsible mw-collapsed" | {| role="presentation" class="wikitable mw-collapsible mw-collapsed" | ||
| <strong> | | <strong>E15_RadInkrementalgeberFahrt.ino </strong> | ||
|- | |- | ||
| <source line lang=" | | <source line lang="C" style="font-size:medium">/* Bibliotheken einbinden */ | ||
#include "AlphaBot.h" | |||
/* Globale KONSTANTEN deklarieren */ | |||
AlphaBot R2D2 = AlphaBot(); // Instanz des Alphabot wird erzeugt. */ | |||
const byte PORT_ENC_L_u8 = 2; // Die linke Lichtschranke (CNTL) liegt an Arduino D2 | |||
const byte PORT_ENC_R_u8 = 3; // Die rechte Lichtschranke (CNTR) liegt an Arduino D3 | |||
const byte ANZAHL_INCREMENTE_u8 = 40; // Die Encoderscheibe hat 20 Löcher und somit 40 Zustände | |||
const int MOTOR_POWER_s16 = 80; // Motorleistung | |||
const unsigned long BAUDRATE_u32 = 9600; // Serielle Übertragungsgeschwindigkeit in Baud | |||
const unsigned long DELAY_MS_u32 = 1000; // Delay in ms | |||
/* Globale Variablen */ | |||
volatile byte valEncL_u8 = 0; // https://www.arduino.cc/reference/de/language/variables/data-types/byte/ | |||
volatile byte valEncR_u8 = 0; // Inkrementzähler | |||
volatile long int RadumdrehungenL_s32 = 0; // https://www.arduino.cc/reference/de/language/variables/data-types/long/ | |||
volatile long int RadumdrehungenR_s32 = 0; // Zähler für die kompletten Radumdrehungen | |||
/* Einmalige Systeminitialisierung */ | |||
void setup() { | |||
Serial.begin(BAUDRATE_u32); // Seriellen Monitor starten | |||
pinMode(PORT_ENC_L_u8, INPUT); // Eingangsport D2 definieren | |||
pinMode(PORT_ENC_R_u8, INPUT); // Eingangsport D3 definieren | |||
attachInterrupt(0, updateEncoderL, CHANGE); // 0: D2 Auslösen des Interrupts bei Signalwechsel | |||
attachInterrupt(1, updateEncoderR, CHANGE); // 1: D3 https://www.arduino.cc/reference/de/language/functions/external-interrupts/attachinterrupt/ | |||
} | |||
/* Zyklusschleife */ | |||
void loop() { | |||
/* Ausgaben im Seriellen Monitor */ | |||
Serial.print(valEncL_u8); | |||
Serial.print(" :-: "); | |||
Serial.print(valEncR_u8); | |||
Serial.print(" :-: "); | |||
Serial.print(RadumdrehungenL_s32); | |||
Serial.print(" :-: "); | |||
Serial.print(RadumdrehungenR_s32); | |||
Serial.print("\n"); | |||
delay(DELAY_MS_u32); | |||
R2D2.MotorRun(MOTOR_POWER_s16, MOTOR_POWER_s16); // Fahrt starten | |||
delay(DELAY_MS_u32); // Fahrzeit | |||
R2D2.Brake(); // Alle Motoren stoppen | |||
} | |||
/* Unterfunktionen */ | |||
void updateEncoderL(){ // Inkrementalgeber Links | |||
valEncL_u8++; | |||
if (valEncL_u8 > ANZAHL_INCREMENTE_u8)// 40 Zustandswechsel = 1 Radumdrehung | |||
{ | |||
valEncL_u8 = 0; // Reset Inkrementzähler | |||
RadumdrehungenL_s32++; // Umdrehungen inkrementieren | |||
} | |||
} | |||
void updateEncoderR(){ // Inkrementalgeber Rechts | |||
valEncR_u8++; | |||
if (valEncR_u8 > ANZAHL_INCREMENTE_u8)// 40 Zustandswechsel = 1 Radumdrehung | |||
{ | |||
valEncR_u8 = 0; // Reset Inkrementzähler | |||
RadumdrehungenR_s32++; // Umdrehungen inkrementieren | |||
} | |||
} | |||
</source> | </source> | ||
|} | |} | ||
| Zeile 181: | Zeile 355: | ||
# Dokumentieren Sie die Abtastrate, Datenqualität und mögliche Messfehler. | # Dokumentieren Sie die Abtastrate, Datenqualität und mögliche Messfehler. | ||
= 2 | = Aufgabe 2: Analyse der Sensorsignale = | ||
Untersuchen Sie die Eigenschaften der verfügbaren Sensordaten. | Untersuchen Sie die Eigenschaften der verfügbaren Sensordaten. | ||
| Zeile 200: | Zeile 374: | ||
* Schlupf der Räder | * Schlupf der Räder | ||
= Aufgabe 3: Bewegungsmodell des Roboters = | |||
= 3 | |||
Entwickeln Sie ein geeignetes Bewegungsmodell für den AlphaBot. | Entwickeln Sie ein geeignetes Bewegungsmodell für den AlphaBot. | ||
| Zeile 227: | Zeile 400: | ||
* Modellfehler | * Modellfehler | ||
= Aufgabe 4: Navigation ohne Filter = | |||
= 4 | |||
Implementieren Sie zunächst eine reine Zustandsschätzung ohne Sensorfusion. | Implementieren Sie zunächst eine reine Zustandsschätzung ohne Sensorfusion. | ||
Der Zustand des Roboters wird beschrieben durch: | |||
<math> | |||
\mathbf{x}_k = | |||
\begin{bmatrix} | |||
x_k\\ | |||
y_k\\ | |||
\psi_k\\ | |||
v_k\\ | |||
b_{\omega,k} | |||
\end{bmatrix} | |||
</math> | |||
* | mit: | ||
* | * <math>x,y</math>: Position des Roboters in der Ebene | ||
* <math>\psi</math>: Orientierung (Yaw-Winkel) | |||
* <math>v</math>: Geschwindigkeit | |||
* <math>b_\omega</math>: Gyro-Bias | |||
Untersuchen Sie: | Untersuchen Sie: | ||
* Drift | * Drift | ||
* Positionsfehler | * Positionsfehler | ||
* Einfluss von Sensorausfällen | * Einfluss von Sensorausfällen | ||
= Aufgabe 5: Kalman-Filter (KF) = | |||
Entwickeln Sie ein lineares Zustandsmodell. Begründen Sie die Wahl des Zustandsmodells. | |||
Entwickeln Sie ein lineares Zustandsmodell. | |||
Die Zustandsschätzung soll mit einem klassischen Kalman-Filter erfolgen. | Die Zustandsschätzung soll mit einem klassischen Kalman-Filter erfolgen. | ||
Bestimmen Sie: | Bestimmen Sie: | ||
* Zustandsvektor | * Zustandsvektor | ||
* Systemmatrix | * Systemmatrix | ||
* Messmatrix | * Messmatrix | ||
* Prozessrauschen <math>Q</math> | * Prozessrauschen <math>Q</math> | ||
* Messrauschen <math>R</math> | * Messrauschen <math>R</math> | ||
| Zeile 260: | Zeile 442: | ||
Untersuchen Sie den Einfluss der Filterparameter auf das Ergebnis. | Untersuchen Sie den Einfluss der Filterparameter auf das Ergebnis. | ||
= Aufgabe 6: Extended Kalman-Filter (EKF) = | |||
= 6 | |||
Erweitern Sie das System auf das nichtlineare Robotermodell. | Erweitern Sie das System auf das nichtlineare Robotermodell. | ||
Implementieren Sie: | Implementieren Sie: | ||
* Prediction-Schritt | * Prediction-Schritt | ||
* Berechnung der Jacobi-Matrix | * Berechnung der Jacobi-Matrix | ||
* Update-Schritt | * Update-Schritt | ||
* Innovation und Innovationskovarianz | * Innovation und Innovationskovarianz | ||
Bewerten Sie: | Bewerten Sie: | ||
* Genauigkeit | * Genauigkeit | ||
* Stabilität | * Stabilität | ||
* Verhalten bei Kurvenfahrt | * Verhalten bei Kurvenfahrt | ||
= Aufgabe 7: Unscented Kalman-Filter (UKF) = | |||
Im Gegensatz zum Extended Kalman-Filter wird keine Linearisierung des Bewegungs- oder Messmodells durch Berechnung einer Jacobi-Matrix durchgeführt. Stattdessen wird die Wahrscheinlichkeitsverteilung des Zustands durch eine Menge von Sigma-Punkten approximiert. | |||
Erweitern Sie die bisher implementierte Zustandsschätzung des AlphaBots um einen Unscented Kalman-Filter (UKF). | |||
Vergleichen Sie UKF und EKF hinsichtlich: | Vergleichen Sie UKF und EKF hinsichtlich: | ||
* Positionsfehler | * Positionsfehler | ||
* Winkelfehler | * Winkelfehler | ||
* Verhalten bei Kurvenfahrt | |||
* Einfluss des Parameters <math>\kappa</math> | |||
* Rechenaufwand | * Rechenaufwand | ||
Diskutieren Sie: | |||
# Welche Vorteile bietet die Unscented Transformation gegenüber der Linearisierung des EKF? | |||
# Wann liefert der UKF bessere Ergebnisse als der EKF? | |||
# Welche Grenzen besitzt der verwendete UKF-Ansatz? | |||
= 8 | = Aufgabe 8: Experimentelle Untersuchung = | ||
Führen Sie, wie im Video dargestellt, verschiedene Fahrversuche auf einem vorgegebenen Quadrat durch. | |||
Nutzen Sie als Referenz das Videobild oder die Referenzstation im Labor. Machen Sie mit Prof. Schneider frühzeitig einen Termin, wenn Sie im Labor messen möchten. | |||
Bewerten Sie die Filter anhand von: | Bewerten Sie die Filter anhand von: | ||
{| class="wikitable" | {| class="wikitable" | ||
! Kriterium !! KF !! EKF !! UKF | ! Kriterium !! KF !! EKF !! UKF | ||
|- | |- | ||
| Positionsfehler | | Positionsfehler || || || | ||
|- | |- | ||
| Winkelfehler | | Winkelfehler || || || | ||
|- | |- | ||
| Robustheit | | Robustheit || || || | ||
|- | |- | ||
| Rechenzeit | | Rechenzeit || || || | ||
|} | |} | ||
= Aufgabe 9: Diskussion und Bewertung = | |||
= | |||
Beantworten Sie folgende Fragen: | Beantworten Sie folgende Fragen: | ||
# Welche Annahmen treffen KF, EKF und UKF? | |||
# Welche Annahmen treffen KF, EKF | |||
# Wann versagen lineare Filter? | # Wann versagen lineare Filter? | ||
# Welche Vorteile bietet | # Welche Vorteile bietet das UKF gegenüber dem EKF? | ||
# Welche zusätzlichen Sensoren würden die Navigation verbessern? | # Welche zusätzlichen Sensoren würden die Navigation verbessern? | ||
Diskutieren Sie abschließend, welches Verfahren für die Navigation des AlphaBots am besten geeignet ist und begründen Sie Ihre Entscheidung. | Diskutieren Sie abschließend, welches Verfahren für die Navigation des AlphaBots am besten geeignet ist und begründen Sie Ihre Entscheidung. | ||
= Abgabe = | = Abgabe = | ||
Die Hausarbeit soll enthalten: | |||
Die | |||
* Beschreibung des Systemaufbaus | * Beschreibung des Systemaufbaus | ||
* MATLAB-Programme | * PAP der MATLAB-Programme | ||
* Arduino- | * PAP des Arduino-Programms | ||
* Messdatenanalyse | * Messdatenanalyse | ||
* Herleitung der verwendeten Modelle | * Herleitung der verwendeten Modelle | ||
* Vergleich der Filterverfahren | * Vergleich der Filterverfahren | ||
* Diskussion der Ergebnisse | * Diskussion der Ergebnisse | ||
= Abgabeordner = | = Abgabeordner = | ||
Nachdem Sie zur Prüfung angemeldet sind, lege ich für Sie einen Sciebo-Arbeitsordner an. Bitte legen Sie darin Ihre Ergebnisse ab | Nachdem Sie zur Prüfung angemeldet sind, lege ich für Sie einen Sciebo-Arbeitsordner an. Bitte legen Sie darin Ihre Ergebnisse ab | ||
* Arduino-Datei, | |||
* MATLAB<sup>®</sup>-Dateien, | |||
* Referenzmessung oder Referenzvideo und | |||
* Hausarbeit als .pdf | |||
und organisieren Sie sich ggf. in Unterordnern. | |||
= Bewertung = | = Bewertung = | ||
| Zeile 405: | Zeile 546: | ||
| '''Summe:''' || '''40''' | | '''Summe:''' || '''40''' | ||
|} | |} | ||
= Tutorial = | |||
* [[AlphaBot]] | |||
* [[IMU_MPU-9250/6500|IMU MPU 9250]] | |||
Aktuelle Version vom 12. Juli 2026, 11:04 Uhr
| Dozent: | Prof. Dr.-Ing. Schneider |
| Lehrveranstaltung: | Moderne Tracking Systeme |
| Modul | Business and Systems Engineering, Systemintegration |
| Modulbezeichnung: | BSE-M-2-2.01 |
| Modulverantwortung: | Prof. UlrichSchneider |
| Prüfungsform: | Hausarbeit |
| Abgabetermin: | 19.07.2026 |
Der Autonome Mobile Roboter (AMR, AlphaBot) soll wie im Video gezeigt möglichst exakt die Ränder eines Quadrats abfahren.
URL: https://www.youtube.com/watch?v=PWdxnERpynU
Im Rahmen dieser Hausarbeit soll eine Sensorfusionslösung zur Navigation eines mobilen Roboters entwickelt und untersucht werden.
Als Versuchsplattform dient ein Waveshare AlphaBot, der mit einer MPU9250-Inertialsensoreinheit ausgestattet ist. Die Sensordaten werden erfasst, verarbeitet und zur Schätzung der Roboterpose verwendet.
Ziel ist die Entwicklung und Bewertung verschiedener Bayes-basierter Schätzverfahren:
- Kalman-Filter (KF)
- Extended Kalman-Filter (EKF)
- Unscented Kalman-Filter (UKF)
Die Verfahren sollen hinsichtlich Genauigkeit, Robustheit und Rechenaufwand verglichen werden.
Notwendige Hardware
- AlphaBot mit
- Arduino R4 Wifi und
- MPU 9250 IMU
- USB-C Kabel
Notwendige Software
- Arduino IDE 2.3.10
- MATLAB® (z. B. R2025b) mit Arduino Support Package
Vorbereitung
- Arbeiten Sie sich anhand dieses Artikels in den AlphaBot ein. Sie benötigen lediglich die Ansteuerung der Motoren, das Auslesen der Inkrementalgeber und die Daten der IMU MPU 9250.
- Leihen Sie sich die Hardware für die Hausarbeit bei Prof. Schneider oder Marc Ebmeyer aus.
- Machen Sie bei Fragen frühzeitig einen Termin mit Prof Schneider.
- Binden Sie den Arduino Uno R4 Wifi in Ihre Wifi-Umgebung ein. Sie dürfen hierfür gern unser Labor verwenden.
- Tragen Sie die WLAN-Zugangsdaten und die IP-Adresse des MATLAB-Rechners in die entsprechende Zeile ein.
- Übertragen Sie das Programm
DemoUnoR4Wifi.inoauf den Arduino uno R4 Wifi. - Versorgen Sie den Arduino Uno R4 mit Spannung (6 V-24 V). Die Daten werden nun gesendet. Die TX-LED blinkt kontinuierlich.
- Starten Sie
DemoUnoR4Wifi.mauf dem PC. Die DatenZeit in s;Zählermüssten nun empfangen und imCommand Windowdargestellt werden. - Gratulation! Sie sind nun startbereit!
Demos
| Demo | Funktion |
|---|---|
| DemoUnoR4Wifi.ino | Demo zum Senden von Sensordaten via Wifi für die Arduino IDE |
| DemoUnoR4Wifi.m | Demo zum Empfangen von Sensordaten via Wifi mit MATLAB® |
| GetDate.ino | Demo zum Auslesen der IMU-Daten des Sensors MPU 9250 |
| E15_RadInkrementalgeberFahrt.ino | Demo zum Ansteuern der Motoren und auslesen der Odometrie des AlphaBot |
| DemoUnoR4Wifi.ino |
clear all; clc;
port = 7000; % UDP Port, auf dem MATLAB lauscht
u = udpport("IPV4", "LocalPort", port);
disp("Warte auf UDP-Daten vom Arduino ...")
while true
nBytes = u.NumBytesAvailable;
if nBytes > 0 % Prüfen, ob Daten vorhanden sind
data = read(u, nBytes, "string");
disp(data)
end
end
|
| GetDate.ino aus der Bibliothek MPU9250_asukiaaa | ||
#include <MPU9250_asukiaaa.h>
#ifdef _ESP32_HAL_I2C_H_
#define SDA_PIN 21
#define SCL_PIN 22
#endif
MPU9250_asukiaaa mySensor;
float aX, aY, aZ, aSqrt, gX, gY, gZ, mDirection, mX, mY, mZ;
void setup() {
Serial.begin(115200);
while(!Serial);
Serial.println("started");
#ifdef _ESP32_HAL_I2C_H_ // For ESP32
Wire.begin(SDA_PIN, SCL_PIN);
mySensor.setWire(&Wire);
#endif
mySensor.beginAccel();
mySensor.beginGyro();
mySensor.beginMag();
// You can set your own offset for mag values
// mySensor.magXOffset = -50;
// mySensor.magYOffset = -55;
// mySensor.magZOffset = -10;
}
void loop() {
uint8_t sensorId;
int result;
result = mySensor.readId(&sensorId);
if (result == 0) {
Serial.println("sensorId: " + String(sensorId));
} else {
Serial.println("Cannot read sensorId " + String(result));
}
result = mySensor.accelUpdate();
if (result == 0) {
aX = mySensor.accelX();
aY = mySensor.accelY();
aZ = mySensor.accelZ();
aSqrt = mySensor.accelSqrt();
Serial.println("accelX: " + String(aX));
Serial.println("accelY: " + String(aY));
Serial.println("accelZ: " + String(aZ));
Serial.println("accelSqrt: " + String(aSqrt));
} else {
Serial.println("Cannod read accel values " + String(result));
}
result = mySensor.gyroUpdate();
if (result == 0) {
gX = mySensor.gyroX();
gY = mySensor.gyroY();
gZ = mySensor.gyroZ();
Serial.println("gyroX: " + String(gX));
Serial.println("gyroY: " + String(gY));
Serial.println("gyroZ: " + String(gZ));
} else {
Serial.println("Cannot read gyro values " + String(result));
}
result = mySensor.magUpdate();
if (result != 0) {
Serial.println("cannot read mag so call begin again");
mySensor.beginMag();
result = mySensor.magUpdate();
}
if (result == 0) {
mX = mySensor.magX();
mY = mySensor.magY();
mZ = mySensor.magZ();
mDirection = mySensor.magHorizDirection();
Serial.println("magX: " + String(mX));
Serial.println("maxY: " + String(mY));
Serial.println("magZ: " + String(mZ));
Serial.println("horizontal direction: " + String(mDirection));
} else {
Serial.println("Cannot read mag values " + String(result));
}
Serial.println("at " + String(millis()) + "ms");
Serial.println(""); // Add an empty line
delay(500);
}
|
| E15_RadInkrementalgeberFahrt.ino |
/* Bibliotheken einbinden */
#include "AlphaBot.h"
/* Globale KONSTANTEN deklarieren */
AlphaBot R2D2 = AlphaBot(); // Instanz des Alphabot wird erzeugt. */
const byte PORT_ENC_L_u8 = 2; // Die linke Lichtschranke (CNTL) liegt an Arduino D2
const byte PORT_ENC_R_u8 = 3; // Die rechte Lichtschranke (CNTR) liegt an Arduino D3
const byte ANZAHL_INCREMENTE_u8 = 40; // Die Encoderscheibe hat 20 Löcher und somit 40 Zustände
const int MOTOR_POWER_s16 = 80; // Motorleistung
const unsigned long BAUDRATE_u32 = 9600; // Serielle Übertragungsgeschwindigkeit in Baud
const unsigned long DELAY_MS_u32 = 1000; // Delay in ms
/* Globale Variablen */
volatile byte valEncL_u8 = 0; // https://www.arduino.cc/reference/de/language/variables/data-types/byte/
volatile byte valEncR_u8 = 0; // Inkrementzähler
volatile long int RadumdrehungenL_s32 = 0; // https://www.arduino.cc/reference/de/language/variables/data-types/long/
volatile long int RadumdrehungenR_s32 = 0; // Zähler für die kompletten Radumdrehungen
/* Einmalige Systeminitialisierung */
void setup() {
Serial.begin(BAUDRATE_u32); // Seriellen Monitor starten
pinMode(PORT_ENC_L_u8, INPUT); // Eingangsport D2 definieren
pinMode(PORT_ENC_R_u8, INPUT); // Eingangsport D3 definieren
attachInterrupt(0, updateEncoderL, CHANGE); // 0: D2 Auslösen des Interrupts bei Signalwechsel
attachInterrupt(1, updateEncoderR, CHANGE); // 1: D3 https://www.arduino.cc/reference/de/language/functions/external-interrupts/attachinterrupt/
}
/* Zyklusschleife */
void loop() {
/* Ausgaben im Seriellen Monitor */
Serial.print(valEncL_u8);
Serial.print(" :-: ");
Serial.print(valEncR_u8);
Serial.print(" :-: ");
Serial.print(RadumdrehungenL_s32);
Serial.print(" :-: ");
Serial.print(RadumdrehungenR_s32);
Serial.print("\n");
delay(DELAY_MS_u32);
R2D2.MotorRun(MOTOR_POWER_s16, MOTOR_POWER_s16); // Fahrt starten
delay(DELAY_MS_u32); // Fahrzeit
R2D2.Brake(); // Alle Motoren stoppen
}
/* Unterfunktionen */
void updateEncoderL(){ // Inkrementalgeber Links
valEncL_u8++;
if (valEncL_u8 > ANZAHL_INCREMENTE_u8)// 40 Zustandswechsel = 1 Radumdrehung
{
valEncL_u8 = 0; // Reset Inkrementzähler
RadumdrehungenL_s32++; // Umdrehungen inkrementieren
}
}
void updateEncoderR(){ // Inkrementalgeber Rechts
valEncR_u8++;
if (valEncR_u8 > ANZAHL_INCREMENTE_u8)// 40 Zustandswechsel = 1 Radumdrehung
{
valEncR_u8 = 0; // Reset Inkrementzähler
RadumdrehungenR_s32++; // Umdrehungen inkrementieren
}
}
|
Weitere AlphaBot und Arduino Demos finden Sie im SVN-Repositorium
https://svn.hshl.de/svn/Informatikpraktikum_1/trunk/Arduino/ArduinoLibOrdner/
Aufgabe 1: Systemaufbau und Datenerfassung
Der AlphaBot wird über eine ebene Fläche bewegt. Während der Fahrt werden Sensordaten aufgezeichnet.
Folgende Sensoren stehen zur Verfügung:
| Sensor | Messgröße | Verwendung |
|---|---|---|
| MPU9250 Gyroskop | Gierrate | Orientierung |
| MPU9250 Beschleunigungssensor | Bewegungsdynamik | |
| MPU9250 Magnetometer | Magnetfeldrichtung | absolute Orientierung |
| Radencoder | Raddrehzahlen | Geschwindigkeit und Weg |
Die Messdaten werden über eine WLAN-Verbindung vom Arduino Uno R4 WiFi an MATLAB übertragen.
Das Datenformat soll mindestens enthalten:
Zeitstempel in s;Messnummer;Sensordaten
Beispiel:
1.25;2300;0.012;-0.034;9.812;0.01;0.02;-0.01
Aufgaben
- Implementieren Sie eine Messdatenübertragung zwischen Arduino Uno R4 WiFi und MATLAB®.
- Erfassen und speichern Sie die Sensordaten des AlphaBots.
- Dokumentieren Sie die Abtastrate, Datenqualität und mögliche Messfehler.
Aufgabe 2: Analyse der Sensorsignale
Untersuchen Sie die Eigenschaften der verfügbaren Sensordaten.
Führen Sie folgende Analysen durch:
- Bestimmung der Abtastrate
- Darstellung der Sensorsignale im Zeitbereich
- Frequenzanalyse mittels FFT
- Untersuchung von Offset und Drift
- Bestimmung der Messunsicherheit
Bewerten Sie insbesondere:
- Gyro-Bias und Drift
- Rauschen des Beschleunigungssensors
- Störungen des Magnetometers
- Schlupf der Räder
Aufgabe 3: Bewegungsmodell des Roboters
Entwickeln Sie ein geeignetes Bewegungsmodell für den AlphaBot.
Der Roboter kann als Differentialantrieb modelliert werden.
Beispiel:
Diskutieren Sie:
- Wahl der Zustandsgrößen
- Modellannahmen
- Modellfehler
Implementieren Sie zunächst eine reine Zustandsschätzung ohne Sensorfusion.
Der Zustand des Roboters wird beschrieben durch:
mit:
- : Position des Roboters in der Ebene
- : Orientierung (Yaw-Winkel)
- : Geschwindigkeit
- : Gyro-Bias
Untersuchen Sie:
- Drift
- Positionsfehler
- Einfluss von Sensorausfällen
Aufgabe 5: Kalman-Filter (KF)
Entwickeln Sie ein lineares Zustandsmodell. Begründen Sie die Wahl des Zustandsmodells.
Die Zustandsschätzung soll mit einem klassischen Kalman-Filter erfolgen.
Bestimmen Sie:
- Zustandsvektor
- Systemmatrix
- Messmatrix
- Prozessrauschen
- Messrauschen
Untersuchen Sie den Einfluss der Filterparameter auf das Ergebnis.
Aufgabe 6: Extended Kalman-Filter (EKF)
Erweitern Sie das System auf das nichtlineare Robotermodell.
Implementieren Sie:
- Prediction-Schritt
- Berechnung der Jacobi-Matrix
- Update-Schritt
- Innovation und Innovationskovarianz
Bewerten Sie:
- Genauigkeit
- Stabilität
- Verhalten bei Kurvenfahrt
Aufgabe 7: Unscented Kalman-Filter (UKF)
Im Gegensatz zum Extended Kalman-Filter wird keine Linearisierung des Bewegungs- oder Messmodells durch Berechnung einer Jacobi-Matrix durchgeführt. Stattdessen wird die Wahrscheinlichkeitsverteilung des Zustands durch eine Menge von Sigma-Punkten approximiert.
Erweitern Sie die bisher implementierte Zustandsschätzung des AlphaBots um einen Unscented Kalman-Filter (UKF).
Vergleichen Sie UKF und EKF hinsichtlich:
- Positionsfehler
- Winkelfehler
- Verhalten bei Kurvenfahrt
- Einfluss des Parameters
- Rechenaufwand
Diskutieren Sie:
- Welche Vorteile bietet die Unscented Transformation gegenüber der Linearisierung des EKF?
- Wann liefert der UKF bessere Ergebnisse als der EKF?
- Welche Grenzen besitzt der verwendete UKF-Ansatz?
Aufgabe 8: Experimentelle Untersuchung
Führen Sie, wie im Video dargestellt, verschiedene Fahrversuche auf einem vorgegebenen Quadrat durch.
Nutzen Sie als Referenz das Videobild oder die Referenzstation im Labor. Machen Sie mit Prof. Schneider frühzeitig einen Termin, wenn Sie im Labor messen möchten.
Bewerten Sie die Filter anhand von:
| Kriterium | KF | EKF | UKF |
|---|---|---|---|
| Positionsfehler | |||
| Winkelfehler | |||
| Robustheit | |||
| Rechenzeit |
Aufgabe 9: Diskussion und Bewertung
Beantworten Sie folgende Fragen:
- Welche Annahmen treffen KF, EKF und UKF?
- Wann versagen lineare Filter?
- Welche Vorteile bietet das UKF gegenüber dem EKF?
- Welche zusätzlichen Sensoren würden die Navigation verbessern?
Diskutieren Sie abschließend, welches Verfahren für die Navigation des AlphaBots am besten geeignet ist und begründen Sie Ihre Entscheidung.
Abgabe
Die Hausarbeit soll enthalten:
- Beschreibung des Systemaufbaus
- PAP der MATLAB-Programme
- PAP des Arduino-Programms
- Messdatenanalyse
- Herleitung der verwendeten Modelle
- Vergleich der Filterverfahren
- Diskussion der Ergebnisse
Abgabeordner
Nachdem Sie zur Prüfung angemeldet sind, lege ich für Sie einen Sciebo-Arbeitsordner an. Bitte legen Sie darin Ihre Ergebnisse ab
- Arduino-Datei,
- MATLAB®-Dateien,
- Referenzmessung oder Referenzvideo und
- Hausarbeit als .pdf
und organisieren Sie sich ggf. in Unterordnern.
Bewertung
Die Bewertung der Hausarbeit erfolgt anhand der Kriterien in Tabelle 1. Diese Bewertung wird in Ihrem Abgabeordner publiziert. Dieses gilt als Klausureinsicht. Melden Sie sich bitte bei Rückfragen frühzeitig.
| Kriterium | Punkte |
|---|---|
| Dokumentation und Qualität der Recherche | 5 |
| Qualität und Quantität der Auswahlkriterien | 5 |
| Systematik bei der Auswahl des Ansatzes | 5 |
| Darstellung des Lösungsansatzes | 5 |
| Umsetzung des Lösungsansatzes | 5 |
| Anwendung und Optimierung des Partikelfilters zur Spurverfolgung | 5 |
| Qualität des Ergebnisses | 5 |
| Qualität der Ergebnisdiskussion | 5 |
| Summe: | 40 |