Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / libdragonfly / odometry.c @ 948

History | View | Annotate | Download (2.77 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 lround(double d);
8

    
9

    
10
int encoder_ltm1, encoder_rtm1;
11

    
12
//Measure mm displacement in x and y from starting position. (+x:theta=0 +y:theta=M_PI/2)
13
long diff_x,diff_y;
14

    
15
//Measures radian angle displacement from starting position. (initially 0)
16
double angle;
17

    
18
/**
19
 * Retrieve the estimated x position. [millimeters]
20
 */
21
long odometry_dx(void){
22
        return diff_x;
23
}
24

    
25
/**
26
 * Retrieve the estimated y position. [millimeters]
27
 */
28
long odometry_dy(void){
29
        return diff_y;
30
}
31

    
32
/**
33
 * Retrieve the estimated angle [radians]
34
 */
35
double odometry_angle(void){
36
        return angle;
37
}
38

    
39
/**
40
 * Initializes odometry to run on timer 2.
41
 * Also resets all values so that the center of the robot is 
42
 * considered to be at the origin facing the x direction.
43
 */
44
void odometry_init(void){
45
        
46
        encoders_init();
47
        
48
        delay_ms(100);
49

    
50
        odometry_reset();
51

    
52
        
53
        //CTC Mode. CLK / 1024
54
        TCCR2 = 0; // (Fully disconnected)
55
        TCCR2 = _BV(WGM21) | _BV(CS22) | _BV(CS20); //CLK/1024 , CTC Mode.
56

    
57
        TIMSK |= _BV(OCIE2);
58

    
59
        OCR2 = ODOMETRY_CLK;
60
}
61
/**
62
 * Resets all values so that the center of the robot is 
63
 * considered to be at the origin facing the x direction.
64
 */
65
void odometry_reset(void){
66
        diff_x = 0;
67
        diff_y = 0;
68
        encoder_ltm1 = encoder_read(LEFT);
69
        encoder_rtm1 = encoder_read(RIGHT);
70
        angle = 0.0;
71
}
72

    
73

    
74
void odometry_run(void){
75
        //Angle swept through in a time step CCW-
76
        double theta, rl, dc;
77
        long dr,dl;
78
        
79
        //Get the change in wheel positions
80
        {        
81
                int encoder_right = encoder_read(RIGHT);        
82
                int encoder_left = encoder_read(LEFT);        
83
        
84
                dl = encoder_left - encoder_ltm1;
85
                dr = encoder_right - encoder_rtm1;
86
                
87
                //No motion.
88
                if(dl == 0 && dr == 0) return;
89

    
90
                encoder_ltm1 = encoder_left;
91
                encoder_rtm1 = encoder_right;
92
        
93
                // Try to avoid over/underflow.
94
                dl = dl > 512 ? dl - 1024 :dl;
95
                dl = dl < -512 ? dl + 1024 :dl;
96
                dr = dr > 512 ? dr - 1024 :dr;
97
                dr = dr < -512 ? dr + 1024 :dr;
98
        
99
                //Convert "clicks" to um
100
                dl *= CLICK_DISTANCE_UM; //um
101
                dr *= CLICK_DISTANCE_UM;
102
        }
103
        
104

    
105
        if(dl == dr){
106
                diff_x += lround(dl*cos(angle)/1000.0); //mm
107
                diff_y += lround(dl*sin(angle)/1000.0); //mm
108
                return;
109
        }
110
        
111
        //Call the left wheel 0, clockwise positive.
112
        rl = ((double)(ROBOT_WIDTH_UM*dl))/((double)(dl - dr)); //um
113
        theta = ((double)(dl - dr))/((double)ROBOT_WIDTH_UM);   //rad
114
        
115
        //Distance the center has traveled.
116
        dc = lround( (theta * (rl - ROBOT_WIDTH_UM)) / 2.0 ); //um
117
        
118
        //angle is necessarily CCW+, so subtract.
119
        angle -= ANGLE_SCALE * theta; 
120
        
121
        //Change state variables.        
122
        diff_x += lround((DISTANCE_SCALE * dc * cos(angle))/1000.0); //mm
123
        diff_y += lround((DISTANCE_SCALE * dc * sin(angle))/1000.0); //mm
124
}
125

    
126
ISR(TIMER2_COMP_vect){
127
        odometry_run(); 
128
}
129

    
130
long lround(double d){
131
        double f = floor(d);
132
        return (long)(d - f > 0.5 ? f + 1 : f);
133
}
134

    
135