Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (2.2 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
long encoder_ltm1, encoder_rtm1;
8

    
9
long diff_x,diff_y;
10
double angle;
11

    
12

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

    
17
int 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
        encoders_init();
27
        odometry_reset();
28
        
29
        //CTC Mode. CLK / 1024
30
        TCCR2 = 0; // (Fully disconnected)
31
        TCCR2 = _BV(WGM21) | _BV(CS22) | _BV(CS20); //CLK/1024 , CTC Mode.
32

    
33
        TIMSK |= _BV(OCIE2);
34

    
35
        OCR2 = ODOMETRY_CLK;
36
}
37

    
38
void odometry_reset(void){
39
        diff_x = 0;
40
        diff_y = 0;
41
        angle = 0.0;
42
}
43

    
44
/*Currently assumes robot only goes forward.*/
45
void odometry_run(void){
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;
52

    
53
        encoder_left = encoder_read(LEFT);        
54
        encoder_right = encoder_read(RIGHT);        
55
        
56
        dl = encoder_left - encoder_ltm1;
57
        dr = encoder_right - encoder_rtm1;
58

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

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

    
67
        if(dl == dr){
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; 
73
                return;
74
        }
75
        
76
        if(dr > dl){ //CCW positive.
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);
82
        }
83
        
84
        else{ //CW negative.
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
                
91
        }
92

    
93
        diff_x += distance_um * cos(angle)/1000;
94
        diff_y += distance_um * sin(angle)/1000;
95
        
96
        angle += theta;
97

    
98
        encoder_ltm1 = encoder_left;
99
        encoder_rtm1 = encoder_right;
100
}
101

    
102
ISR(TIMER2_COMP_vect){
103
        odometry_run();
104
}
105

    
106