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

  1. Descrivere funzionamento e limiti dei sensori (ultrasuoni, IR, encoder, LIDAR, IMU, camera).
  2. Cablarli a un Arduino o Raspberry Pi e acquisire misure ripetibili.
  3. Calcolare distanza da tempo di volo e spostamento lineare da encoder.
  4. Applicare filtri semplici e comprendere principio del filtro di Kalman.
  5. Integrare più sensori per decisioni robuste.
  6. 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:

  1. Converti BGR → HSV
  2. Applica soglia H-S-V
  3. Trova contorno più grande
  4. Estrai bounding box
  5. 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

  1. Monta e testa il sensore a varie distanze (0.1, 0.3, 0.6, 1.0 m) e registra 20 misure per ogni distanza.
  2. Calcola media e deviazione standard per ogni target; costruisci tabella e grafico.
  3. 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):

  1. Robot che si ferma con affidabilità ≥ 95% su 20 test con ostacolo a 10 cm ±2 cm.
  2. Relazione tecnica (3–4 pagine): schema elettrico, codice, tabelle misure, grafici, discussione errori.
  3. 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:

  1. Introduzione ai sensori (classificazione)
  2. Ultrasuoni: principio e formule (d = v·t/2)
  3. Encoder: conversione impulsi→distanza
  4. IMU: drift e filtro complementare
  5. LIDAR e visione: polar→cartesiano
  6. Schema laboratorio HC-SR04 (wiring)
  7. Codice Arduino (spiegazione step by step)
  8. Data logging e analisi
  9. Sensor fusion: esempi e demo
  10. 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

Post popolari in questo blog

La scienza delle piccole grandi cose: Teoria della doppia copia: gravità e gauge a confronto

Corso di Algebra Elementare e Strutture Algebriche: 1 Polinomi

CORSO DI MECCANICA QUANTISTICA: 2 Misura Quantistica Sovrapposizione e Spin