Project

General

Profile

Revision 913

Odometry works but the precision is awful. Angles are measured fairly accurately, but distance readings are consistently lower then expected.

View differences:

trunk/code/projects/mapping/odometry/odometry.c
1 1
#include "odometry.h"
2
#include "encoders.h"
2
#include <encoders.h>
3 3
#include <math.h>
4 4
#include <avr/interrupt.h>
5 5
#include <dragonfly_lib.h>
......
41 41
	angle = 0.0;
42 42
}
43 43

  
44
/*Currently assumes robot only goes forward.*/
44 45
void odometry_run(void){
45
	double v_l, v_r;
46
	double omega;
47
	long encoder_left, encoder_right, dl, dr;
46
	double theta;
47
	int encoder_left, encoder_right,dl,dr; 
48
	long distance_um;
49
	char buf[100];	
50
	//Relative to the inner wheel, the radius of its turn.
51
	double turning_radius;
48 52

  
49 53
	encoder_left = encoder_read(LEFT);	
50 54
	encoder_right = encoder_read(RIGHT);	
51

  
55
	
52 56
	dl = encoder_left - encoder_ltm1;
53 57
	dr = encoder_right - encoder_rtm1;
54 58

  
......
56 60
	dl = dl < -512 ? dl + 1024 :dl;
57 61
	dr = dr > 512 ? dr - 1024 :dr;
58 62
	dr = dr < -512 ? dr + 1024 :dr;
59
	
60 63

  
64
	//idle?
65
	if(dl < 2 && dr < 2) return;
66

  
61 67
	if(dl == dr){
62
		diff_x += (long)((double)(dl*CLICK_DISTANCE_UM) * cos(angle)); 
63
		diff_y += (long)((double)(dr*CLICK_DISTANCE_UM) * sin(angle));
68
		distance_um = dl*CLICK_DISTANCE_UM;
69
		//sprintf(buf,"Distance in um: %ld\n\r",distance_um);
70
		//usb_puts(buf);
71
		diff_x += distance_um*cos(angle)/1000; 
72
		diff_y += distance_um*sin(angle)/1000; 
64 73
		return;
65 74
	}
66 75
	
67
	//Relative to the center of the robot, the center of it's turn.
68
	double turning_radius;
69

  
70 76
	if(dr > dl){ //CCW positive.
71
		turning_radius = ROBOT_WIDTH_MM * dl / (dr - dl); //mm
72
		v_l = (CLICK_DISTANCE_UM * dl) / (ODOMETRY_CLK * 64l);  //m/s
73
		omega = v_l / (turning_radius/1000); //rad/s
77
		turning_radius = ROBOT_WIDTH_UM * dl / (dr - dl); //um
78
		theta = ((double)(dr-dl)*CLICK_DISTANCE_UM) / ((double)ROBOT_WIDTH_UM);
79
		distance_um = theta*((double)(turning_radius + ROBOT_WIDTH_UM/2)); 
80
		//sprintf(buf,"Distance in um: %d\n\r",distance_um);
81
		//usb_puts(buf);
74 82
	}
75 83
	
76 84
	else{ //CW negative.
77
		turning_radius = ROBOT_WIDTH_MM * dr / (dl - dr); //mm
78
		v_r = (CLICK_DISTANCE_UM * dr) / (ODOMETRY_CLK * 64l); //m/s
79
		omega = v_r / (turning_radius/1000); //rad/s
85
		turning_radius = ROBOT_WIDTH_UM * dr / (dl - dr); //um
86
		theta = -((double)(dl-dr)*CLICK_DISTANCE_UM) / ((double)ROBOT_WIDTH_UM);
87
		distance_um = -theta*((double)(turning_radius + ROBOT_WIDTH_UM/2)); 
88
		//sprintf(buf,"Distance in um: %d\n\r",distance_um);
89
		//usb_puts(buf);
90
		
80 91
	}
92

  
93
	diff_x += distance_um * cos(angle)/1000;
94
	diff_y += distance_um * sin(angle)/1000;
81 95
	
82
	//Omega positive whenever t_r is negative, vica versa.
83
	double vmag = omega * ((turning_radius + ROBOT_WIDTH_MM/2)/1000); //m/s
96
	angle += theta;
84 97

  
85
	angle += omega*ODOMETRY_CLK*64; //rad
86
	diff_x += 1000000 * vmag * cos(angle); //um
87
	diff_y += 1000000 * vmag * sin(angle); //um
98
	encoder_ltm1 = encoder_left;
99
	encoder_rtm1 = encoder_right;
88 100
}
89 101

  
90 102
ISR(TIMER2_COMP_vect){
trunk/code/projects/mapping/odometry/main.c
5 5
{
6 6
	dragonfly_init(ALL_ON);
7 7
	odometry_init();
8
	int angle;
8
	char buf[100];
9 9
	while(1){
10
		usb_puts("X: ");
11
		usb_puti(odometry_dx());	
12
		usb_puts(" Y: ");
13
		usb_puti(odometry_dy());	
14
		usb_puts(" Theta: ");
15
		angle = (int)(odometry_angle()*150.0);	
16
		usb_puti(angle);	
17
		usb_puts("\n\r");
10
		sprintf(buf,"X: %i, Y: %i, Theta: %f\n\r",odometry_dx(),odometry_dy(),odometry_angle());
11
		usb_puts(buf);
18 12
		delay_ms(500);
19 13
	}
20 14
	return 0;
trunk/code/projects/mapping/odometry/odometry.h
4 4

  
5 5
//Odometry resolution, *64 microseconds.
6 6
//= approx. 100 ms
7
#define ODOMETRY_CLK 1600  
7
#define ODOMETRY_CLK 255u 
8 8

  
9 9
//Wheel = 2.613 in.  
10 10
//Circumference = 208.508133 mm
11 11
//Distance per encoder click (circumference / 1024)  = 203.621224 um.
12 12
//Robot width = 5.3745 in. = 136.5123 mm
13 13

  
14
#define ROBOT_WIDTH_MM 137    //mm
14
#define ROBOT_WIDTH_UM 137000  //um
15 15
#define CLICK_DISTANCE_UM 204 //um
16 16

  
17 17
//Standard measures will be mm and us
trunk/code/projects/mapping/odometry/Makefile
155 155
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
156 156

  
157 157
# If this is left blank, then it will use the Standard printf version.
158
PRINTF_LIB = 
158
#PRINTF_LIB = 
159 159
#PRINTF_LIB = $(PRINTF_LIB_MIN)
160
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
160
PRINTF_LIB = $(PRINTF_LIB_FLOAT)
161 161

  
162 162

  
163 163
# Minimalistic scanf version

Also available in: Unified diff