Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (3.67 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
        
117
        double dr,dl;
118
        
119
        char buf[40];        
120
        //Relative to the inner wheel, turn radius.
121

    
122
        //Get the change in wheel positions
123
        
124
        int encoder_right = encoder_read(RIGHT);        
125
        int encoder_left = encoder_read(LEFT);        
126
        
127
        dl = encoder_left - encoder_ltm1;
128
        dr = encoder_right - encoder_rtm1;
129
        
130
        //if(dl >=-1 && dl <= 1  && dr >= -1 && dr <= 1) return;
131
        
132
        encoder_ltm1 = encoder_left;
133
        encoder_rtm1 = encoder_right;
134
        
135
        // Try to avoid over/underflow.
136
        dl = dl > 512 ? dl - 1024 :dl;
137
        dl = dl < -512 ? dl + 1024 :dl;
138
        dr = dr > 512 ? dr - 1024 :dr;
139
        dr = dr < -512 ? dr + 1024 :dr;
140
        
141
        //Convert "clicks" to um
142
        dl *= CLICK_DISTANCE_UM; //um
143
        dr *= CLICK_DISTANCE_UM;
144

    
145
        if(dl == dr){
146
                //usb_putc('#');
147
                diff_x += dl*cos(angle)/1000; 
148
                diff_y += dl*sin(angle)/1000; 
149
                return;
150
        }
151
        
152
        //Call the left wheel 0, clockwise positive.
153
        rl = ((double)(ROBOT_WIDTH_UM*dl))/((double)(dl - dr)); //um
154
        
155
        theta = ((double)(dl - dr))/((double)ROBOT_WIDTH_UM); //rad
156

    
157
        dc = (rl - ROBOT_WIDTH_UM/2)*theta; //um
158

    
159
        diff_x += ((dc * cos(angle))/1000); //mm
160
        diff_y += ((dc * sin(angle))/1000); //mm
161
                
162
        //Change state variables.        
163
        
164
        //angle is necessarily CCW+, so subtract.
165
        angle -= theta; 
166
        
167
}
168

    
169
ISR(TIMER2_COMP_vect){
170
        odometry_run(); 
171
}
172

    
173