This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
rc2007-soccer/source/ct-Bot/sensor.c

348 lines
13 KiB
C
Raw Permalink Normal View History

/*
* c't-Sim - Robotersimulator fuer den c't-Bot
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your
* option) any later version.
* This program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307, USA.
*
*/
/*! @file sensor.c
* @brief Architekturunabhaengiger Teil der Sensorsteuerung
* @author Benjamin Benz (bbe@heise.de)
* @date 15.01.05
*/
#include <stdio.h>
#include "ct-Bot.h"
#include "timer.h"
#include "bot-local.h"
#include "math.h"
#include "sensor_correction.h"
#ifdef SRF10_AVAILABLE
#include "srf10.h"
#endif
// Defines einiger, haeufiger benoetigter Konstanten
#define DEG2RAD (2*M_PI/360)
int16 sensLDRL=0; /*!< Lichtsensor links */
int16 sensLDRR=0; /*!< Lichtsensor rechts */
int16 sensDistL=1023; /*!< Distanz linker IR-Sensor in [mm], wenn korrekt umgerechnet wird */
int16 sensDistR=1023; /*!< Distanz rechter IR-Sensor in [mm], wenn korrekt umgerechnet wird */
int16 sensBorderL=0; /*!< Abgrundsensor links */
int16 sensBorderR=0; /*!< Abgrundsensor rechts */
int16 sensLineL=0; /*!< Lininensensor links */
int16 sensLineR=0; /*!< Lininensensor rechts */
uint8 sensTrans=0; /*!< Sensor Ueberwachung Transportfach */
uint8 sensDoor=0; /*!< Sensor Ueberwachung Klappe */
uint8 sensError=0; /*!< Ueberwachung Motor oder Batteriefehler */
#ifdef MAUS_AVAILABLE
int8 sensMouseDX; /*!< Maussensor Delta X, positive Werte zeigen querab der Fahrtrichtung nach rechts */
int8 sensMouseDY; /*!< Maussensor Delta Y, positive Werte zeigen in Fahrtrichtung */
int16 sensMouseX; /*!< Mausposition X, positive Werte zeigen querab der Fahrtrichtung nach rechts */
int16 sensMouseY; /*!< Mausposition Y, positive Werte zeigen in Fahrtrichtung */
#endif
volatile int16 sensEncL=0; /*!< Encoder linkes Rad */
volatile int16 sensEncR=0; /*!< Encoder rechtes Rad */
float heading_enc=0; /*!< Blickrichtung aus Encodern */
float x_enc=0; /*!< X-Koordinate aus Encodern [mm] */
float y_enc=0; /*!< Y-Koordinate aus Encodern [mm] */
float v_enc_left=0; /*!< Abrollgeschwindigkeit des linken Rades in [mm/s] [-128 bis 127] relaisitisch [-50 bis 50] */
float v_enc_right=0; /*!< Abrollgeschwindigkeit des linken Rades in [mm/s] [-128 bis 127] relaisitisch [-50 bis 50] */
float v_enc_center=0; /*!< Schnittgeschwindigkeit ueber beide Raeder */
#ifdef PC
uint16 simultime=0; /*! Simulierte Zeit */
#endif
#ifdef MEASURE_MOUSE_AVAILABLE
float heading_mou=0; /*!< Aktuelle Blickrichtung relativ zur Startposition aus Mausmessungen */
float x_mou=0; /*!< Aktuelle X-Koordinate in mm relativ zur Startposition aus Mausmessungen */
float y_mou=0; /*!< Aktuelle Y-Koordinate in mm relativ zur Startposition aus Mausmessungen */
float v_mou_center=0; /*!< Geschwindigkeit in mm/s ausschliesslich aus den Maussensorwerten berechnet */
float v_mou_left=0; /*!< ...aufgeteilt auf linkes Rad */
float v_mou_right=0; /*!< ...aufgeteilt auf rechtes Rad */
#endif
float heading=0; /*!< Aktuelle Blickrichtung aus Encoder-, Maus- oder gekoppelten Werten */
float x_pos=0; /*!< Aktuelle X-Position aus Encoder-, Maus- oder gekoppelten Werten */
float y_pos=0; /*!< Aktuelle Y-Position aus Encoder-, Maus- oder gekoppelten Werten */
float v_left=0; /*!< Geschwindigkeit linkes Rad aus Encoder-, Maus- oder gekoppelten Werten */
float v_right=0; /*!< Geschwindigkeit rechtes Rad aus Encoder-, Maus- oder gekoppelten Werten */
float v_center=0; /*!< Geschwindigkeit im Zentrum des Bots aus Encoder-, Maus- oder gekoppelten Werten */
int8 sensors_initialized = 0; /*!< Wird 1 sobald die Sensorwerte zur Verfügung stehen */
#ifdef SRF10_AVAILABLE
uint16 sensSRF10; /*!< Messergebniss Ultraschallsensor */
#endif
/*! Linearisiert die Sensorwerte
* @param left Linker Rohwert [0-1023]
* @param right Rechter Rohwert [0-1023]
*/
void sensor_abstand(uint16 left, uint16 right){
if (left == SENSDISTOFFSETLEFT) // Vermeidet Div/0
left++;
sensDistL = SENSDISTSLOPELEFT / (left - SENSDISTOFFSETLEFT);
// Korrigieren, wenn ungueltiger Wert
if (sensDistL > SENS_IR_MAX_DIST || sensDistL<=0)
sensDistL=SENS_IR_INFINITE;
if (right == SENSDISTOFFSETRIGHT) // Vermeidet Div/0
right++;
sensDistR = SENSDISTSLOPERIGHT / (right - SENSDISTOFFSETRIGHT);
// Korrigieren, wenn ungueltiger Wert
if (sensDistR > SENS_IR_MAX_DIST || sensDistR<=0)
sensDistR=SENS_IR_INFINITE;
}
/*! Sensor_update
* Kuemmert sich um die Weiterverarbeitung der rohen Sensordaten
*/
void sensor_update(void){
static uint16 old_pos=0; /*!< Ticks fuer Positionsberechnungsschleife */
static uint16 old_speed=0; /*!< Ticks fuer Geschwindigkeitsberechnungsschleife */
#ifdef MEASURE_MOUSE_AVAILABLE
static int16 lastMouseX=0; /*!< letzter Mauswert X fuer Positionsberechnung */
static int16 lastMouseY=0; /*!< letzter Mauswert Y fuer Positionsberechnung */
static float lastDistance=0; /*!< letzte gefahrene Strecke */
static float lastHead=0; /*!< letzter gedrehter Winkel */
static float oldHead=0; /*!< Winkel aus dem letzten Durchgang */
static float old_x=0; /*!< Position X aus dem letzten Durchgang */
static float old_y=0; /*!< Position Y aus dem letzten Durchgang */
float radius=0; /*!< errechneter Radius des Drehkreises */
float s1=0; /*!< Steigung der Achsengerade aus dem letzten Durchgang */
float s2=0; /*!< Steigung der aktuellen Achsengerade */
float a1=0; /*!< Y-Achsenabschnitt der Achsengerade aus dem letzten Durchgang */
float a2=0; /*!< Y-Achsenabschnitt der aktuellen Achsengerade */
float xd=0; /*!< X-Koordinate Drehpunkt */
float yd=0; /*!< Y-Koordinate Drehpunkt */
float right_radius=0; /*!< Radius des Drehkreises des rechten Rads */
float left_radius=0; /*!< Radius des Drehkreises des linken Rads */
#endif
static int16 lastEncL =0; /*!< letzter Encoderwert links fuer Positionsberechnung */
static int16 lastEncR =0; /*!< letzter Encoderwert rechts fuer Positionsberechnung */
static int16 lastEncL1=0; /*!< letzter Encoderwert links fuer Geschwindigkeitsberechnung */
static int16 lastEncR1=0; /*!< letzter Encoderwert rechts fuer Geschwindigkeitsberechnung */
float dHead=0; /*!< Winkeldifferenz aus Encodern */
float deltaY=0; /*!< errechneter Betrag Richtungsvektor aus Encodern */
int16 diffEncL; /*!< Differenzbildung linker Encoder */
int16 diffEncR; /*!< Differenzbildung rechter Encoder */
float sl; /*!< gefahrene Strecke linkes Rad */
float sr; /*!< gefahrene Strecke rechtes Rad */
#ifdef MEASURE_MOUSE_AVAILABLE
int16 dX; /*!< Differenz der X-Mauswerte */
int16 dY; /*!< Differenz der Y-Mauswerte */
int8 modifiedAngles=False; /*!< Wird True, wenn aufgrund 90 Grad oder 270 Grad die Winkel veraendert werden mussten */
sensMouseY += sensMouseDY; /*!< Mausdelta Y aufaddieren */
sensMouseX += sensMouseDX; /*!< Mausdelta X aufaddieren */
#endif
register uint16 ticks = TIMER_GET_TICKCOUNT_16;
if (ticks-old_pos > MS_TO_TICKS(50)){
old_pos = ticks;
/* Gefahrene Boegen aus Encodern berechnen */
diffEncL=sensEncL-lastEncL;
diffEncR=sensEncR-lastEncR;
lastEncL=sensEncL;
lastEncR=sensEncR;
sl=(float)diffEncL*WHEEL_PERIMETER/ENCODER_MARKS;
sr=(float)diffEncR*WHEEL_PERIMETER/ENCODER_MARKS;
/* Winkel berechnen */
dHead=(float)(sr-sl)/(2*WHEEL_DISTANCE);
/* Winkel ist hier noch im Bogenmass */
/* Position berechnen */
/* dazu Betrag des Vektors berechnen */
if (dHead==0) {
/* Geradeausfahrt, deltaY=diffEncL=diffEncR */
deltaY=sl;
} else {
/* Laenge berechnen aus alpha/2 */
deltaY=(sl+sr)*sin(dHead/2)/dHead;
}
/* Winkel in Grad umrechnen */
dHead=dHead/DEG2RAD;
/* neue Positionen berechnen */
heading_enc+=dHead;
while (heading_enc>=360) heading_enc=heading_enc-360;
while (heading_enc<0) heading_enc=heading_enc+360;
x_enc+=(float)deltaY*cos(heading_enc*DEG2RAD);
y_enc+=(float)deltaY*sin(heading_enc*DEG2RAD);
#ifdef MEASURE_MOUSE_AVAILABLE
dX=sensMouseX-lastMouseX;
/* heading berechnen */
dHead=(float)dX*360/MOUSE_FULL_TURN;
heading_mou+=dHead;
lastHead+=dHead;
if (heading_mou>=360) heading_mou=heading_mou-360;
if (heading_mou<0) heading_mou=heading_mou+360;
/* x/y pos berechnen */
dY=sensMouseY-lastMouseY;
x_mou+=(float)dY*cos(heading_mou*DEG2RAD)*25.4/MOUSE_CPI;
lastDistance+=dY*25.4/MOUSE_CPI;
y_mou+=(float)dY*sin(heading_mou*DEG2RAD)*25.4/MOUSE_CPI;
lastMouseX=sensMouseX;
lastMouseY=sensMouseY;
#endif
#ifdef MEASURE_COUPLED_AVAILABLE
/* Werte der Encoder und der Maus mit dem Faktor G_POS verrechnen */
x_pos=G_POS*x_mou+(1-G_POS)*x_enc;
y_pos=G_POS*y_mou+(1-G_POS)*y_enc;
/* Korrektur, falls mou und enc zu unterschiedlichen Seiten zeigen */
if (fabs(heading_mou-heading_enc) > 180) {
/* wir nutzen zum Rechnen zwei Drehrichtungen */
heading = heading_mou<=180 ? heading_mou*G_POS : (heading_mou-360)*G_POS;
heading += heading_enc<=180 ? heading_enc*(1-G_POS) : (heading_enc-360)*(1-G_POS);
/* wieder auf eine Drehrichtung zurueck */
if (heading < 0) heading += 360;
} else
heading = G_POS*heading_mou + (1-G_POS)*heading_enc;
if (heading >= 360) heading -= 360;
#else
#ifdef MEASURE_MOUSE_AVAILABLE
/* Mauswerte als Standardwerte benutzen */
heading=heading_mou;
x_pos=x_mou;
y_pos=y_mou;
#else
/* Encoderwerte als Standardwerte benutzen */
heading=heading_enc;
x_pos=x_enc;
y_pos=y_enc;
#endif
#endif
}
ticks = TIMER_GET_TICKCOUNT_16;
if (ticks-old_speed > MS_TO_TICKS(250)){
old_speed=ticks;
v_enc_left= (((sensEncL - lastEncL1) * WHEEL_PERIMETER) / ENCODER_MARKS)*4;
v_enc_right= (((sensEncR - lastEncR1) * WHEEL_PERIMETER) / ENCODER_MARKS)*4;
v_enc_center=(v_enc_left+v_enc_right)/2;
lastEncL1= sensEncL;
lastEncR1= sensEncR;
#ifdef MEASURE_MOUSE_AVAILABLE
/* Speed aufgrund Maussensormessungen */
v_mou_center=lastDistance*4;
/* Aufteilung auf die Raeder zum Vergleich mit den Radencodern */
/* Sonderfaelle pruefen */
if (oldHead==90 || oldHead==270 || heading_mou==90 || heading_mou==270) {
float temp;
/* winkel um 90 Grad vergroessern */
oldHead+=90;
heading_mou+=90;
// Koordinaten anpassen
temp=old_x;
old_x=old_y;
old_y=-temp;
temp=x_mou;
x_mou=y_mou;
y_mou=-temp;
modifiedAngles=True;
}
/* Steigungen berechnen */
s1=-tan(oldHead*DEG2RAD);
s2=-tan(heading_mou*DEG2RAD);
/* Geradeausfahrt? (s1==s2) */
if (s1==s2) {
/* Bei Geradeausfahrt ist v_left==v_right==v_center */
v_mou_left=v_mou_right=v_mou_center;
} else {
/* y-Achsenabschnitte berechnen */
a1=old_x-s1*old_y;
a2=x_mou-s2*y_mou;
/* Schnittpunkt berechnen */
yd=(a2-a1)/(s1-s2);
xd=s2*yd+a2;
/* Radius ermitteln */
radius=sqrt((x_mou-xd)*(x_mou-xd)+(y_mou-yd)*(y_mou-yd));
/* Vorzeichen des Radius feststellen */
if (lastHead<0) {
/* Drehung rechts, Drehpunkt liegt rechts vom Mittelpunkt
* daher negativer Radius */
radius=-radius;
}
if (v_mou_center<0) {
/* rueckwaerts => links und rechts vertauscht, daher VZ vom Radius umdrehen */
radius=-radius;
}
/* Geschwindigkeiten berechnen */
right_radius=radius+WHEEL_DISTANCE;
left_radius=radius-WHEEL_DISTANCE;
v_mou_right=lastHead/360*2*M_PI*right_radius*4;
v_mou_left=lastHead/360*2*M_PI*left_radius*4;
}
/* Falls Koordinaten/Winkel angepasst wurden, nun wieder korrigieren */
if (modifiedAngles){
float temp;
/* Winkel wieder um 90 Grad reduzieren */
oldHead-=90;
heading_mou-=90;
/* Koordinaten wieder korrigieren */
temp=old_x;
old_x=-old_y;
old_y=temp;
temp=x_mou;
x_mou=-y_mou;
y_mou=temp;
}
lastDistance=0;
lastHead=0;
old_x=x_mou;
old_y=y_mou;
oldHead=heading_mou;
#endif
#ifdef MEASURE_COUPLED_AVAILABLE
v_left=G_SPEED*v_mou_left+(1-G_SPEED)*v_enc_left;
v_right=G_SPEED*v_mou_right+(1-G_SPEED)*v_enc_left;
v_center=G_SPEED*v_mou_center+(1-G_SPEED)*v_enc_center;
#else
#ifdef MEASURE_MOUSE_AVAILABLE
/* Mauswerte als Standardwerte benutzen */
v_left=v_mou_left;
v_right=v_mou_right;
v_center=v_mou_center;
#else
/* Encoderwerte als Standardwerte benutzen */
v_left=v_enc_left;
v_right=v_enc_right;
v_center=v_enc_center;
#endif
#endif
#ifdef SRF10_AVAILABLE
sensSRF10 = srf10_get_measure(); /*!< Messung Ultraschallsensor */
#endif
}
sensors_initialized=1;
}