-
Notifications
You must be signed in to change notification settings - Fork 0
/
odometry.ino
141 lines (118 loc) · 2.81 KB
/
odometry.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "asserv_uc.h"
#include "config.h"
#include "odometry.h"
#include "utils.h"
// settings
volatile double ticks_per_meters=DEFAULT_TICK_PER_METERS;
volatile double ticks_per_rads=DEFAULT_TICK_PER_RADS;
volatile double offset_angle; //radians
//mutex, to avoid changing values when odo is running
volatile boolean mutex_odo_is_running=0;
volatile boolean odo_enabled = 0;
//position of the robot, calculated values
volatile double odo_X = 0; //metres
volatile double odo_Y = 0; //metres
volatile double odo_angle = 0; //radians
static void wait_for_odo();
/*
Set the ratio between ticks and real world units (meters and radians)
*/
void odo_setTickRatio(double new_ticks_per_meters,double new_ticks_per_rads)
{
boolean enable_save = odo_enabled;
odo_disable();
wait_for_odo();
if(new_ticks_per_meters>0)
ticks_per_meters=new_ticks_per_meters;
if(new_ticks_per_rads>0)
ticks_per_rads=new_ticks_per_rads;
if(enable_save)
odo_enable();
}
/*
Force the current X coordinate
*/
void odo_setX(double new_x)
{
odo_disable();
wait_for_odo();
odo_X=new_x;
odo_enable();
}
/*
Force the current Y coordinate
*/
void odo_setY(double new_y)
{
odo_disable();
wait_for_odo();
odo_Y=new_y;
odo_enable();
}
/*
Force the current angle to be new_angle.
For that we calculate an offset that will be used later
by the odometry calculation.
*/
void odo_setAngle(double new_angle_rad)
{
odo_disable();
wait_for_odo();
int32_t dist_right=coderRight.read();
int32_t dist_left=coderLeft.read();
int32_t current_angle_tick=dist_right-dist_left;
double current_angle_rad = current_angle_tick/ticks_per_rads;
offset_angle=new_angle_rad-current_angle_rad;
odo_enable();
}
void odo_enable()
{
odo_enabled=true;
}
void odo_disable()
{
odo_enabled=false;
}
static void wait_for_odo()
{
while (mutex_odo_is_running)
{
//wait
}
}
int32_t odo_meters2ticks(double meters)
{
return meters*ticks_per_meters;
}
int32_t odo_rads2ticks(double rads)
{
return rads*ticks_per_rads;
}
/*
This is the real stuff
*/
void odo_update()
{
if (!odo_enabled)
return;
//acquire the mutex
mutex_odo_is_running = 1;
static int32_t old_dist_tick = 0;
int32_t dist_right=coderRight.read();
int32_t dist_left=coderLeft.read();
//The relative distance since the last time whe updated the postion
int32_t new_dist_tick=(dist_left+dist_right)/2;
double delta_dist=((double)(new_dist_tick-old_dist_tick))/ticks_per_meters;
//The absolute robot angle, corrected with the offset
int32_t new_angle_tick=dist_right-dist_left;
odo_angle=offset_angle+new_angle_tick/ticks_per_rads;
//Compute the absolute position of the robot
double dX = cos(odo_angle) * delta_dist;
double dY = sin(odo_angle) * delta_dist;
odo_X += dX;
odo_Y += dY;
//we save that for the next time we update
old_dist_tick=new_dist_tick;
//free the mutex
mutex_odo_is_running = 0;
}