Corso di Robotica: 3 Sensori e Percezione
3 Sensori e Percezione
📌 Panoramica rapida
Obiettivo generale: capire come i robot percepiscono l’ambiente, collegare sensori a microcontrollori, leggere dati e usarli per decisioni (es. fermarsi davanti a un ostacolo).
Prerequisiti: basi di elettronica, programmazione Arduino/Python, nozioni minime di trigonometria.
🎯 Obiettivi didattici
- Descrivere funzionamento e limiti dei sensori (ultrasuoni, IR, encoder, LIDAR, IMU, camera).
- Cablarli a un Arduino o Raspberry Pi e acquisire misure ripetibili.
- Calcolare distanza da tempo di volo e spostamento lineare da encoder.
- Applicare filtri semplici e comprendere principio del filtro di Kalman.
- Integrare più sensori per decisioni robuste.
- Realizzare un esperimento completo: robot che si ferma davanti a un ostacolo.
1 — Sensori base
🔊 Ultrasuoni (HC-SR04)
Equazione:
$$d = \frac{v_{suono} \cdot t}{2}$$
Esempio numerico:
$$t = 0.005\ s,\quad v_{suono} = 343\ m/s$$
$$d = \frac{343 \cdot 0.005}{2} = 0.8575\ m$$
🌈 Infrarossi (IR)
Rilevamento ostacoli ravvicinati. Limitazioni: colore/superficie, luce ambientale.
⚙️ Encoder
Equazione:
$$\text{distanza} = \frac{\text{impulsi}}{\text{PPR}} \cdot 2 \pi r$$
2 — Sensori avanzati
📐 IMU (MPU6050)
Filtro complementare:
$$\theta_{est} = \alpha (\theta_{est} + \omega \Delta t) + (1-\alpha)\theta_{acc}$$
📡 LIDAR
Conversione polare → cartesiana:
$$x = r \cos\theta,\quad y = r \sin\theta$$
👁️ Visione artificiale
Esempio riconoscimento oggetto rosso:
- Converti BGR → HSV
- Applica soglia H-S-V
- Trova contorno più grande
- Estrai bounding box
- Usa centro per guida/stop
3 — Calibrazione e accuratezza
🔧 Ultrasuoni
$$v_{eff} = \frac{2 \cdot d}{t}$$
⚙️ Encoder
$$\text{PPR}_{eff} = \frac{\text{impulsi totali}}{\text{giri effettivi}}$$
📐 IMU
Determinare bias giroscopio e offset accelerometro.
4 — Filtri e sensor fusion (concetti pratici)
Filtri semplici
- Media mobile: elimina rumore impulsivo, reattività lenta.
- Mediana: rimuove outlier.
Complementary filter (IMU)
- sintetizza gyro (buono su breve termine) e accelerometro (buono su lungo termine). Formula sopra.
Kalman filter (idea essenziale)
- Modello statistico: stima stato , predizione (A·x + B·u), aggiornamento con misura .
- Due fasi: predict (stima e covarianza) e update (Kalman gain K e nuova stima).
- Per il corso: spiegare concetti e mostrare codice Matlab/Python per 1-D KF su velocità/distanza.
Sensor fusion pratico (esempio: fermarsi)
- Regola semplice robusta: se (ultrasuoni.distance < soglia) OR (camera.detectedObstacle==True) → stop.
- Migliore: pesare misure con incertezza (es. Kalman/particle filter).
5 — Laboratorio dettagliato: HC-SR04 + Arduino (stop su ostacolo)
Hardware
- HC-SR04 pinout: Vcc (5V), Trig, Echo, GND.
- Motor driver (TB6612/L298N) con motori DC e Arduino Uno.
- Collegamenti essenziali:
- HC-SR04 Vcc → 5V Arduino
- HC-SR04 GND → GND Arduino
- HC-SR04 Trig → Arduino pin D8
- HC-SR04 Echo → Arduino pin D7 (attenzione se Arduino 3.3V vs 5V)
- Motori → driver → alimentazione motori (separata)
- GND motori ↔ GND Arduino (fondamentale)
Codice Arduino (HC-SR04 + stop motori)
// HC-SR04 + stop motori (TB6612 example)
const int trigPin = 8;
const int echoPin = 7;
const int AIN1 = 2; // motor driver pins (left example)
const int AIN2 = 3;
const int PWMA = 5; // PWM pin
long readUltrasoundMicros(){
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH, 30000); // timeout 30ms
return duration; // microseconds
}
float microsToMeters(long duration_us){
// d = v * t / 2 ; v=343 m/s ; duration_us -> seconds
return (343.0f * (duration_us / 1e6f)) / 2.0f;
}
void stopMotors(){
analogWrite(PWMA, 0);
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, LOW);
}
void avanc(int pwm){
digitalWrite(AIN1, HIGH);
digitalWrite(AIN2, LOW);
analogWrite(PWMA, pwm);
}
void setup(){
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(AIN1, OUTPUT);
pinMode(AIN2, OUTPUT);
pinMode(PWMA, OUTPUT);
Serial.begin(115200);
}
void loop(){
long d_us = readUltrasoundMicros();
if(d_us == 0){ // timeout
Serial.println("no echo");
// decide fallback (slow down)
avanc(100);
} else {
float dist_m = microsToMeters(d_us);
Serial.print("dist [m]: ");
Serial.println(dist_m, 3);
if(dist_m < 0.10){ // soglia 10 cm
stopMotors();
Serial.println("STOP - ostacolo vicino");
delay(1000);
} else {
avanc(200); // marcia avanti
}
}
delay(100);
}
Note: pulseIn ritorna 0 se timeout; microsToMeters calcola distanza. Usa un filtro (es. media mobile sui 5 ultimi campioni) per stabilizzare la soglia.
Esercizio di laboratorio
- Monta e testa il sensore a varie distanze (0.1, 0.3, 0.6, 1.0 m) e registra 20 misure per ogni distanza.
- Calcola media e deviazione standard per ogni target; costruisci tabella e grafico.
- Implementa media mobile a N=5 e confronta i risultati.
6 — Laboratorio: Encoder e misura spostamento
Principio
Conteggio impulsi via interrupt → conversione a distanza:
\text{distanza} = \frac{\text{pulses}}{\text{PPR}} \cdot 2\pi r
Codice Arduino (contatore encoder incrementale)
volatile long pulses = 0;
const int encoderPin = 2; // must be interrupt pin on Uno
void isrEncoder(){
pulses++;
}
void setup(){
pinMode(encoderPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(encoderPin), isrEncoder, RISING);
Serial.begin(115200);
}
void loop(){
noInterrupts();
long p = pulses;
interrupts();
float r = 0.03; // m
int PPR = 64;
float dist = (p/(float)PPR) * 2.0 * 3.1415926 * r;
Serial.print("pulses=");
Serial.print(p);
Serial.print(" dist_m=");
Serial.println(dist,6);
delay(200);
}
Attività: far girare la ruota di una distanza nota (es. 1 m), verificare pulses ottenuti → calcolare PPR_eff.
7 — Laboratorio: IMU (MPU6050) e filtro complementare
- Leggi gyro e accel su due assi; calcola angolo accelerometrico:
\theta_{acc} = \arctan2(a_x, a_z)
\theta_{est} = \alpha (\theta_{est} + \omega_y \Delta t) + (1-\alpha)\theta_{acc}
Sketch Arduino (pseudo — usare libreria MPU6050)
// pseudocode: leggere gyro/acc, complementary filter
float alpha = 0.98;
float theta = 0.0; // initial
unsigned long last = micros();
void loop(){
unsigned long now = micros();
float dt = (now - last) / 1e6f;
last = now;
// read gyro.y in rad/s and accel.x, accel.z in g
float gyro_y = readGyroY(); // deg/s or rad/s consistent
float ax = readAccX();
float az = readAccZ();
float theta_acc = atan2(ax, az); // rad
theta = alpha * (theta + gyro_y * dt) + (1.0 - alpha) * theta_acc;
}
Attività: confrontare theta_est con inclinometro di riferimento; sperimentare α.
8 — Raspberry Pi + OpenCV: fermare con visione
Esempio base Python (Raspberry Pi) per rilevare area rossa e fermare motori via GPIO.
# detect_red_stop.py (Python 3)
import cv2
import numpy as np
import RPi.GPIO as GPIO
import time
MOTOR_PIN = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(MOTOR_PIN, GPIO.OUT)
pwm = GPIO.PWM(MOTOR_PIN, 100)
pwm.start(50) # duty = 50% to move
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# HSV range for red (two ranges)
lower1 = np.array([0, 120, 70])
upper1 = np.array([10, 255, 255])
lower2 = np.array([170, 120, 70])
upper2 = np.array([180, 255, 255])
mask1 = cv2.inRange(hsv, lower1, upper1)
mask2 = cv2.inRange(hsv, lower2, upper2)
mask = mask1 | mask2
# morphological ops
mask = cv2.medianBlur(mask, 5)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
c = max(contours, key=cv2.contourArea)
area = cv2.contourArea(c)
if area > 2000:
# big red object: stop motor
pwm.ChangeDutyCycle(0)
print("STOP detected by vision")
else:
pwm.ChangeDutyCycle(50)
else:
pwm.ChangeDutyCycle(50)
# optional: visualize
cv2.imshow("frame", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
GPIO.cleanup()
Nota: per controllare motori reali su Raspberry Pi, spesso si usa un controller intermedio (I²C/PWM driver) o un microcontroller che riceve comandi via seriale/ROS.
9 — SLAM & mappatura (introduzione operativa)
- Approccio semplice: usare LIDAR o depth camera per costruire occupacy grid (2D), usare algoritmi off-the-shelf (GMapping, Hector SLAM con ROS).
- Output pratico: mappa 2D in formato image; usata per path planning e localizzazione (AMCL).
10 — Errori comuni e troubleshooting (pratico)
- HC-SR04: echo floating → usare pull-down, filtrare misure troppo basse/alte, evitare superfici assorbenti.
- Encoder: dimenticare GND comune → conteggi errati.
- IMU: bias non rimosso → integrazione giroscopio diverge.
- Visione: illuminazione troppo bassa/forte → usare exposure control o illuminazione costante.
11 — Raccolta dati e analisi
- Log CSV: timestamp, sensore1, sensore2, stato_motore.
- Analisi: grafico distanza nel tempo, istogramma errori, deviazione standard.
- Strumenti: Python (pandas, matplotlib), Jupyter notebook.
12 — Valutazione e deliverable
Deliverable richiesti (per gruppo):
- Robot che si ferma con affidabilità ≥ 95% su 20 test con ostacolo a 10 cm ±2 cm.
- Relazione tecnica (3–4 pagine): schema elettrico, codice, tabelle misure, grafici, discussione errori.
- Video dimostrativo (1–2 min).
Rubrica di valutazione (0–4):
- Funzionalità: 0–4 (non funziona → perfetto)
- Robustezza (gestione timeout/outlier): 0–4
- Correttezza analisi dati: 0–4
- Documentazione: 0–4
13 — Materiali, componenti e budget indicativo
- HC-SR04 (ultrasuoni) — €2–5
- IR line sensors kit — €5–15
- MPU6050 (IMU) — €3–8
- Small encoder wheel kit — €6–15
- RPLIDAR A1 (entry LIDAR) — €150–250 (opzionale)
- Raspberry Pi 4 (4GB) + camera — €80–120
- Arduino Uno/Nano — €5–20
- Motor driver TB6612, L298N — €3–12
- Motori DC + ruote — €10–30 per coppia
14 — Slide-outline e attività per l’insegnante
Slide consigliate:
- Introduzione ai sensori (classificazione)
- Ultrasuoni: principio e formule (d = v·t/2)
- Encoder: conversione impulsi→distanza
- IMU: drift e filtro complementare
- LIDAR e visione: polar→cartesiano
- Schema laboratorio HC-SR04 (wiring)
- Codice Arduino (spiegazione step by step)
- Data logging e analisi
- Sensor fusion: esempi e demo
- Valutazione e compiti
Attività in classe:
- Esperimento di calibrazione HC-SR04 (tabella misure)
- Implementare stop con HC-SR04 (Arduino)
- Implementare stop con visione (Raspberry + OpenCV)
- Confronto: quale soluzione è più robusta? perché?

Commenti
Posta un commento