Advanced Sensor Integration & Data Processing
🤖 Second Semester Begins - Advanced Robotics Concepts
Sometimes one sensor is more reliable than another. Instead of a simple average, we can give more "weight" to the better sensor. For example, if sensor A is very accurate, we might use 80% of its reading and only 20% from sensor B.
We can program our robot to make smart decisions about which sensors to trust. If one sensor gives a reading that seems way off compared to the others, the robot can ignore it or give it less importance.
// Combining multiple distance sensors
class SimpleSensorFusion {
private:
float lastGoodReading = 0;
public:
// Simple average of two sensors
float averageTwoSensors(float sensor1, float sensor2) {
return (sensor1 + sensor2) / 2.0;
}
// Weighted average - give sensor1 more importance
float weightedAverage(float sensor1, float sensor2) {
return (sensor1 * 0.8) + (sensor2 * 0.2);
}
// Choose the best reading (closest to previous good reading)
float chooseBestReading(float sensor1, float sensor2) {
float diff1 = abs(sensor1 - lastGoodReading);
float diff2 = abs(sensor2 - lastGoodReading);
if (diff1 < diff2) {
lastGoodReading = sensor1;
return sensor1;
} else {
lastGoodReading = sensor2;
return sensor2;
}
}
}; Sometimes a sensor gives a really bad reading (like measuring 1000cm when everything else is around 20cm). We can detect these "outliers" and ignore them, using the previous good reading instead.
Instead of sudden jumps in readings, we can make changes gradually. If a sensor reading changes from 20 to 30, we might update slowly: 21, 22, 23... until we reach 30. This prevents jerky robot movements.
// Simple data cleaning for sensor readings
class DataCleaner {
private:
static const int BUFFER_SIZE = 5;
float readings[BUFFER_SIZE];
int currentIndex = 0;
float lastGoodReading = 0;
public:
float cleanReading(float newReading) {
// Step 1: Check if reading seems reasonable
if (isBadReading(newReading)) {
Serial.println("Bad reading detected, using last good value");
return lastGoodReading;
}
// Step 2: Add to our buffer of recent readings
readings[currentIndex] = newReading;
currentIndex = (currentIndex + 1) % BUFFER_SIZE;
// Step 3: Calculate average of recent readings
float average = calculateAverage();
// Step 4: Make gradual changes to prevent jumps
float smoothReading = makeGradualChange(average);
lastGoodReading = smoothReading;
return smoothReading;
}
private:
bool isBadReading(float reading) {
// Check if reading is way different from last good reading
float difference = abs(reading - lastGoodReading);
return difference > 50; // Adjust this threshold as needed
}
float calculateAverage() {
float sum = 0;
for (int i = 0; i < BUFFER_SIZE; i++) {
sum += readings[i];
}
return sum / BUFFER_SIZE;
}
float makeGradualChange(float targetReading) {
// Don't change too quickly - move 20% toward target
float change = (targetReading - lastGoodReading) * 0.2;
return lastGoodReading + change;
}
}; Just like you might adjust your approach when something isn't working right, we can program robots to detect problems and fix them automatically. This makes them more reliable and easier to use.
Sensors can drift over time or be affected by temperature changes. We can program the robot to notice these changes and adjust automatically, like how your eyes adjust to different lighting conditions.
// Simple sensor calibration and error handling
class SmartSensorManager {
private:
struct SensorCalibration {
float offset = 0;
float scale = 1.0;
float confidence = 1.0;
unsigned long lastCalibration = 0;
int errorCount = 0;
};
SensorCalibration ultrasonicCal;
SensorCalibration imuCal;
SensorCalibration compassCal;
static const int CALIBRATION_INTERVAL = 300000; // 5 minutes
public:
void performSystemCalibration() {
Serial.println("Starting intelligent calibration...");
// Ultrasonic calibration using known reference
calibrateUltrasonic();
// IMU calibration using gravity reference
calibrateIMU();
// Compass calibration using magnetic declination
calibrateCompass();
Serial.println("Calibration complete!");
}
float getCalibratedReading(int sensorType, float rawValue) {
SensorCalibration* cal = getSensorCalibration(sensorType);
// Apply calibration
float calibratedValue = (rawValue + cal->offset) * cal->scale;
// Validate reading
if (validateReading(sensorType, calibratedValue)) {
cal->confidence = min(cal->confidence + 0.01, 1.0);
cal->errorCount = 0;
return calibratedValue;
} else {
cal->confidence = max(cal->confidence - 0.05, 0.1);
cal->errorCount++;
// Trigger recalibration if too many errors
if (cal->errorCount > 10) {
triggerRecalibration(sensorType);
}
return -1; // Error value
}
}
private:
void calibrateUltrasonic() {
// Multi-point calibration using known distances
float knownDistances[] = {10, 20, 50, 100}; // cm
float measurements[4];
for (int i = 0; i < 4; i++) {
Serial.print("Place object at ");
Serial.print(knownDistances[i]);
Serial.println("cm and press button...");
waitForButtonPress();
measurements[i] = getUltrasonicReading();
delay(1000);
}
// Calculate linear calibration coefficients
calculateLinearCalibration(knownDistances, measurements, 4, &ultrasonicCal);
}
bool validateReading(int sensorType, float value) {
// Implement sensor-specific validation logic
switch (sensorType) {
case ULTRASONIC:
return (value > 2 && value < 400); // Valid range for HC-SR04
case IMU_ACCEL:
return (abs(value) <= 16); // ±16g range
case COMPASS:
return (value >= 0 && value <= 360); // Degree range
default:
return true;
}
}
}; Create a comprehensive sensor data logging and analysis system that demonstrates advanced integration techniques.
// Complete multi-sensor data logging system
#include <Wire.h>
#include <MPU6050.h>
#include <HMC5883L.h>
class AdvancedSensorSystem {
private:
MPU6050 mpu;
HMC5883L compass;
SensorFusion fusion;
DataProcessor processor;
SmartSensorManager calibration;
// Data logging
struct SensorReading {
unsigned long timestamp;
float ultrasonic;
float accelX, accelY, accelZ;
float gyroX, gyroY, gyroZ;
float compass;
float temperature;
float fusedHeading;
};
SensorReading readings[100]; // Circular buffer
int readingIndex = 0;
public:
void initialize() {
Serial.begin(115200);
Wire.begin();
// Initialize sensors
mpu.initialize();
compass.initialize();
// Perform initial calibration
calibration.performSystemCalibration();
Serial.println("Advanced Sensor System Ready!");
}
void loop() {
// Collect raw sensor data
SensorReading current;
current.timestamp = millis();
// Ultrasonic reading with processing
float rawUltrasonic = getUltrasonicDistance();
current.ultrasonic = processor.processReading(rawUltrasonic);
// IMU readings with calibration
int16_t ax, ay, az, gx, gy, gz;
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
current.accelX = calibration.getCalibratedReading(IMU_ACCEL, ax / 16384.0);
current.accelY = calibration.getCalibratedReading(IMU_ACCEL, ay / 16384.0);
current.accelZ = calibration.getCalibratedReading(IMU_ACCEL, az / 16384.0);
// Compass reading
Vector mag = compass.readNormalize();
current.compass = atan2(mag.YAxis, mag.XAxis) * 180 / PI;
if (current.compass < 0) current.compass += 360;
// Sensor fusion
float accelAngle = atan2(current.accelY, current.accelZ) * 180 / PI;
float gyroRate = gx / 131.0; // Convert to degrees/second
current.fusedHeading = fusion.fuseIMUData(gyroRate, accelAngle, current.compass);
// Store reading
readings[readingIndex] = current;
readingIndex = (readingIndex + 1) % 100;
// Output data for visualization
outputTelemetry(current);
delay(50); // 20Hz update rate
}
private:
void outputTelemetry(const SensorReading& reading) {
Serial.print("TIME:");
Serial.print(reading.timestamp);
Serial.print(",ULTRA:");
Serial.print(reading.ultrasonic);
Serial.print(",ACCEL:");
Serial.print(reading.accelX); Serial.print(",");
Serial.print(reading.accelY); Serial.print(",");
Serial.print(reading.accelZ);
Serial.print(",COMPASS:");
Serial.print(reading.compass);
Serial.print(",FUSED:");
Serial.println(reading.fusedHeading);
}
};
AdvancedSensorSystem sensorSystem;
void setup() {
sensorSystem.initialize();
}
void loop() {
sensorSystem.loop();
} Research and write a 2-page report on "Advanced Sensor Technologies in Modern Robotics." Include examples of LIDAR, computer vision, and AI-enhanced sensor systems. Due next class.
Document your multi-sensor data logger implementation, including calibration procedures, performance metrics, and analysis of sensor fusion accuracy under different conditions.