Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / mapping / odometry / odometry.c @ 929

History | View | Annotate | Download (3.56 KB)

1
#include "odometry.h"
2
#include <encoders.h>
3
#include <math.h>
4
#include <avr/interrupt.h>
5
#include <dragonfly_lib.h>
6

    
7
int encoder_ltm1, encoder_rtm1;
8

    
9
long diff_x,diff_y;
10
double angle;
11

    
12

    
13
long odometry_dx(void){
14
        return diff_x;
15
}
16

    
17
long odometry_dy(void){
18
        return diff_y;
19
}
20

    
21
double odometry_angle(void){
22
        return angle;
23
}
24

    
25
void odometry_init(void){
26
        
27
        encoders_init();
28
        
29
        delay_ms(100);
30

    
31
        odometry_reset();
32

    
33
        
34
        //CTC Mode. CLK / 1024
35
        TCCR2 = 0; // (Fully disconnected)
36
        TCCR2 = _BV(WGM21) | _BV(CS22) | _BV(CS20); //CLK/1024 , CTC Mode.
37

    
38
        TIMSK |= _BV(OCIE2);
39

    
40
        OCR2 = ODOMETRY_CLK;
41
}
42

    
43
void odometry_reset(void){
44
        char buf[40];
45
        diff_x = 0;
46
        diff_y = 0;
47
        encoder_ltm1 = encoder_read(LEFT);
48
        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
        angle = 0.0;
52
}
53

    
54
/*Currently assumes robot only goes forward.
55
void odometry_run(void){
56
        double theta;
57
        int encoder_left, encoder_right,dl,dr; 
58
        long distance_um;
59
        char buf[100];        
60
        //Relative to the inner wheel, the radius of its turn.
61
        double turning_radius;
62

63
        encoder_left = encoder_read(LEFT);        
64
        encoder_right = encoder_read(RIGHT);        
65
        
66
        dl = encoder_left - encoder_ltm1;
67
        dr = encoder_right - encoder_rtm1;
68

69
        dl = dl > 512 ? dl - 1024 :dl;
70
        dl = dl < -512 ? dl + 1024 :dl;
71
        dr = dr > 512 ? dr - 1024 :dr;
72
        dr = dr < -512 ? dr + 1024 :dr;
73

74
        //idle?
75
        if(dl < 2 && dr < 2) return;
76

77
        if(dl == dr){
78
                distance_um = dl*CLICK_DISTANCE_UM;
79
                //sprintf(buf,"Distance in um: %ld\n\r",distance_um);
80
                //usb_puts(buf);
81
                diff_x += distance_um*cos(angle)/1000; 
82
                diff_y += distance_um*sin(angle)/1000; 
83
                return;
84
        }
85
        
86
        if(dr > dl){ //CCW positive.
87
                turning_radius = ROBOT_WIDTH_UM * dl / (dr - dl); //um
88
                theta = ((double)(dr-dl)*CLICK_DISTANCE_UM) / ((double)ROBOT_WIDTH_UM);
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
        }
93
        
94
        else{ //CW negative.
95
                turning_radius = ROBOT_WIDTH_UM * dr / (dl - dr); //um
96
                theta = -((double)(dl-dr)*CLICK_DISTANCE_UM) / ((double)ROBOT_WIDTH_UM);
97
                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
                
101
        }
102

103
        diff_x += distance_um * cos(angle)/1000;
104
        diff_y += distance_um * sin(angle)/1000;
105
        
106
        angle += theta;
107

108
        encoder_ltm1 = encoder_left;
109
        encoder_rtm1 = encoder_right;
110
}*/
111

    
112
/*Generalized version of odometry.*/
113
void odometry_run(void){
114
        //Angle swept through in a time step CCW-
115
        double theta, rl, dc;
116
        long dr,dl;
117
        char buf[40];        
118
        
119
        //Get the change in wheel positions
120
        {        
121
                int encoder_right = encoder_read(RIGHT);        
122
                int encoder_left = encoder_read(LEFT);        
123
        
124
                dl = encoder_left - encoder_ltm1;
125
                dr = encoder_right - encoder_rtm1;
126
        
127
                encoder_ltm1 = encoder_left;
128
                encoder_rtm1 = encoder_right;
129
        
130
                // Try to avoid over/underflow.
131
                dl = dl > 512 ? dl - 1024 :dl;
132
                dl = dl < -512 ? dl + 1024 :dl;
133
                dr = dr > 512 ? dr - 1024 :dr;
134
                dr = dr < -512 ? dr + 1024 :dr;
135
        
136
                //Convert "clicks" to um
137
                dl *= CLICK_DISTANCE_UM; //um
138
                dr *= CLICK_DISTANCE_UM;
139
        }
140

    
141
        if(dl == dr){
142
                diff_x += dl*cos(angle)/1000; 
143
                diff_y += dl*sin(angle)/1000; 
144
                return;
145
        }
146
        
147
        //Call the left wheel 0, clockwise positive.
148
        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
152
        
153
        //Change state variables.        
154
        diff_x += ((dc * cos(angle))/1000); //mm
155
        diff_y += ((dc * sin(angle))/1000); //mm
156

    
157
        //angle is necessarily CCW+, so subtract.
158
        angle -= theta; 
159
        
160
}
161

    
162
ISR(TIMER2_COMP_vect){
163
        odometry_run(); 
164
}
165

    
166