-
Notifications
You must be signed in to change notification settings - Fork 0
/
ballEstimator.m
104 lines (94 loc) · 4.17 KB
/
ballEstimator.m
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
function [position, velocity] = ballEstimator(t, s_5link, s_ball, C)
% Take in current ODE time and state vector (5_link)
% outputs position and velocity in world frame
% Position is the LIDAR measured position, but velocity is an estimated
% velocity
%
% There are 4 cases:
% Case 1: Ball has never been in range
% Case 2: First measurement of ball in range
% Case 3: Ball has been in range for at least 2 measurements
% Case 4: Ball has previously been in range, but went out of range
% Ouputs for each case
% Case | Position Output | Velocity Output
%-------------------------------------------------------------------
% Case 1 | EMPTY | EMPTY
% Case 2 | LIDAR measurement | EMPTY
% Case 3 | LIDAR measurement | velocity estimator
% Case 4 | position predictor | velocity predictor
% properties
g = C.g;
% keeps track of past ball states
persistent position_prev velocity_prev time_prev t_array v_array;
% Always read lidar in any case
% Read lidar
[angles, ranges] = readLIDAR(s_5link, s_ball, C);
% Estimate position of ball in the sensor frame
[p_sensor, radius] = estimateBallPosition(angles, ranges, C);
% Transform position of ball into world frame
position = transformBall(s_5link, p_sensor);
% Ball has never been in range, or ball has only been in range once
% -> Case 1 and 2
if isempty(position_prev)
position_prev = position;
velocity = velocity_prev;
% If previous position is not empty, meaning that this is the first
% time the ball is being detected, guess an initial ball velocity.
if ~isempty(position_prev)
velocity_prev = [0; 0]; % Assume an initial ball velocity
v_array = [v_array, [0; 0]];
t_array = [t_array, t];
end
time_prev = t;
return;
end
if abs(t - time_prev) >= 0.01
% Catch if ODE45 decreases the time
if t < time_prev
position_prev = position;
% Erase future time of velocity array "Re-write time"
future_ind = t_array >= t;
t_array(future_ind) = [];
v_array(:,future_ind) = [];
% Obtain a guess for the current time based on our prev. guesses
velocity = interp1(t_array', v_array', t, 'linear', 'extrap')';
% Record previous guesses and extend array
velocity_prev = v_array(:,end);
time_prev = t;
v_array = [v_array, velocity];
t_array = [t_array, t];
return;
end
% If ball is in range -> Case 3
if ~isempty(position)
% Velocity state estimator
% Differentiate from position measurement
vel_meas = (position - position_prev) ./ (t - time_prev);
% Predict ball velocity by modeling as free fall dynamics
vel_pred = [velocity_prev(1); velocity_prev(2)-g*(t - time_prev)];
vel_mixing = 0.5; % 0->full measured, 1->full predicted
velocity = (1-vel_mixing)*vel_meas + vel_mixing*(vel_pred);
% update stored variables
position_prev = position;
velocity_prev = velocity;
time_prev = t;
v_array = [v_array, velocity];
t_array = [t_array, t];
% If the ball was previously in range, but went out -> Case 4
else
% Predict position
position = position_prev + velocity_prev.*(t - time_prev);
% Predict velocity
velocity = [velocity_prev(1); velocity_prev(2)-g*(t - time_prev)];
% Update stored variables
position_prev = position;
velocity_prev = velocity;
time_prev = t;
v_array = [v_array, velocity];
t_array = [t_array, t];
end
else
position = position_prev;
velocity = velocity_prev;
end
end