Revision 947
Odometry works!!
trunk/code/projects/mapping/odometry/odometry.c | ||
---|---|---|
6 | 6 |
|
7 | 7 |
int encoder_ltm1, encoder_rtm1; |
8 | 8 |
|
9 |
//Measures mm displacement in x and y from starting position. (+x:theta=0 +y:theta=M_PI/2) |
|
9 | 10 |
long diff_x,diff_y; |
11 |
|
|
12 |
//Measures radian angle displacement from starting position. (initially 0) |
|
10 | 13 |
double angle; |
11 | 14 |
|
12 | 15 |
|
... | ... | |
41 | 44 |
} |
42 | 45 |
|
43 | 46 |
void odometry_reset(void){ |
44 |
char buf[40]; |
|
45 | 47 |
diff_x = 0; |
46 | 48 |
diff_y = 0; |
47 | 49 |
encoder_ltm1 = encoder_read(LEFT); |
48 | 50 |
encoder_rtm1 = encoder_read(RIGHT); |
49 |
//sprintf(buf,"(en_right,en_left) in um: (%d,%d)\n\r",encoder_ltm1,encoder_rtm1); |
|
50 |
//usb_puts(buf); |
|
51 | 51 |
angle = 0.0; |
52 | 52 |
} |
53 | 53 |
|
54 |
/*Currently assumes robot only goes forward. |
|
54 |
/*Currently assumes robot only goes forward (neither wheel goes backward).
|
|
55 | 55 |
void odometry_run(void){ |
56 | 56 |
double theta; |
57 | 57 |
int encoder_left, encoder_right,dl,dr; |
... | ... | |
76 | 76 |
|
77 | 77 |
if(dl == dr){ |
78 | 78 |
distance_um = dl*CLICK_DISTANCE_UM; |
79 |
//sprintf(buf,"Distance in um: %ld\n\r",distance_um); |
|
80 |
//usb_puts(buf); |
|
81 | 79 |
diff_x += distance_um*cos(angle)/1000; |
82 | 80 |
diff_y += distance_um*sin(angle)/1000; |
81 |
//sprintf(buf,"Distance in um: %d\n\r",distance_um); |
|
82 |
//usb_puts(buf); |
|
83 | 83 |
return; |
84 | 84 |
} |
85 | 85 |
|
... | ... | |
87 | 87 |
turning_radius = ROBOT_WIDTH_UM * dl / (dr - dl); //um |
88 | 88 |
theta = ((double)(dr-dl)*CLICK_DISTANCE_UM) / ((double)ROBOT_WIDTH_UM); |
89 | 89 |
distance_um = theta*((double)(turning_radius + ROBOT_WIDTH_UM/2)); |
90 |
//sprintf(buf,"Distance in um: %d\n\r",distance_um); |
|
91 |
//usb_puts(buf); |
|
92 | 90 |
} |
93 |
|
|
94 | 91 |
else{ //CW negative. |
95 | 92 |
turning_radius = ROBOT_WIDTH_UM * dr / (dl - dr); //um |
96 | 93 |
theta = -((double)(dl-dr)*CLICK_DISTANCE_UM) / ((double)ROBOT_WIDTH_UM); |
97 | 94 |
distance_um = -theta*((double)(turning_radius + ROBOT_WIDTH_UM/2)); |
98 |
//sprintf(buf,"Distance in um: %d\n\r",distance_um); |
|
99 |
//usb_puts(buf); |
|
100 | 95 |
|
101 | 96 |
} |
97 |
|
|
98 |
//sprintf(buf,"Distance in um: %d\n\r",distance_um); |
|
99 |
//usb_puts(buf); |
|
102 | 100 |
|
103 | 101 |
diff_x += distance_um * cos(angle)/1000; |
104 | 102 |
diff_y += distance_um * sin(angle)/1000; |
... | ... | |
109 | 107 |
encoder_rtm1 = encoder_right; |
110 | 108 |
}*/ |
111 | 109 |
|
110 |
|
|
112 | 111 |
/*Generalized version of odometry.*/ |
113 | 112 |
void odometry_run(void){ |
114 | 113 |
//Angle swept through in a time step CCW- |
115 | 114 |
double theta, rl, dc; |
116 | 115 |
long dr,dl; |
117 |
char buf[40]; |
|
118 | 116 |
|
119 | 117 |
//Get the change in wheel positions |
120 | 118 |
{ |
... | ... | |
123 | 121 |
|
124 | 122 |
dl = encoder_left - encoder_ltm1; |
125 | 123 |
dr = encoder_right - encoder_rtm1; |
126 |
|
|
124 |
|
|
125 |
//No motion. |
|
126 |
if(dl == 0 && dr == 0) return; |
|
127 |
|
|
127 | 128 |
encoder_ltm1 = encoder_left; |
128 | 129 |
encoder_rtm1 = encoder_right; |
129 | 130 |
|
... | ... | |
137 | 138 |
dl *= CLICK_DISTANCE_UM; //um |
138 | 139 |
dr *= CLICK_DISTANCE_UM; |
139 | 140 |
} |
141 |
|
|
140 | 142 |
|
141 | 143 |
if(dl == dr){ |
142 |
diff_x += dl*cos(angle)/1000;
|
|
143 |
diff_y += dl*sin(angle)/1000;
|
|
144 |
diff_x += lround(dl*cos(angle)/1000.0); //mm
|
|
145 |
diff_y += lround(dl*sin(angle)/1000.0); //mm
|
|
144 | 146 |
return; |
145 | 147 |
} |
146 | 148 |
|
147 | 149 |
//Call the left wheel 0, clockwise positive. |
148 | 150 |
rl = ((double)(ROBOT_WIDTH_UM*dl))/((double)(dl - dr)); //um |
149 |
theta = ((double)(dl - dr))/((double)ROBOT_WIDTH_UM); //rad |
|
150 |
|
|
151 |
dc = (rl - ROBOT_WIDTH_UM/2)*theta; //um |
|
151 |
theta = ((double)(dl - dr))/((double)ROBOT_WIDTH_UM); //rad |
|
152 | 152 |
|
153 |
//Change state variables. |
|
154 |
diff_x += ((dc * cos(angle))/1000); //mm |
|
155 |
diff_y += ((dc * sin(angle))/1000); //mm |
|
156 |
|
|
153 |
//Distance the center has traveled. |
|
154 |
dc = lround( (theta * (rl - ROBOT_WIDTH_UM)) / 2.0 ); //um |
|
155 |
|
|
157 | 156 |
//angle is necessarily CCW+, so subtract. |
158 |
angle -= theta; |
|
157 |
angle -= ANGLE_SCALE * theta;
|
|
159 | 158 |
|
159 |
//Change state variables. |
|
160 |
diff_x += lround((DISTANCE_SCALE * dc * cos(angle))/1000.0); //mm |
|
161 |
diff_y += lround((DISTANCE_SCALE * dc * sin(angle))/1000.0); //mm |
|
160 | 162 |
} |
161 | 163 |
|
162 | 164 |
ISR(TIMER2_COMP_vect){ |
163 | 165 |
odometry_run(); |
164 | 166 |
} |
165 | 167 |
|
168 |
long lround(double d){ |
|
169 |
double f = floor(d); |
|
170 |
return (long)(d - f > 0.5 ? f + 1 : f); |
|
171 |
} |
|
166 | 172 |
|
173 |
|
trunk/code/projects/mapping/odometry/main.c | ||
---|---|---|
1 | 1 |
#include <dragonfly_lib.h> |
2 | 2 |
#include "odometry.h" |
3 |
#include <math.h> |
|
3 | 4 |
|
4 | 5 |
int main(void) |
5 | 6 |
{ |
trunk/code/projects/mapping/odometry/odometry.h | ||
---|---|---|
14 | 14 |
#define ROBOT_WIDTH_UM 137000 //um |
15 | 15 |
#define CLICK_DISTANCE_UM 204 //um |
16 | 16 |
|
17 |
#define DISTANCE_SCALE 2.10526316 |
|
18 |
#define ANGLE_SCALE 1.12823207 |
|
19 |
|
|
17 | 20 |
//Standard measures will be mm and us |
18 | 21 |
|
19 | 22 |
long odometry_dx(void); |
Also available in: Unified diff