-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrandomTrajectory.m
More file actions
149 lines (136 loc) · 5.99 KB
/
randomTrajectory.m
File metadata and controls
149 lines (136 loc) · 5.99 KB
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
142
143
144
145
146
147
148
149
function Pos = randomTrajectory(opt)
% randomTrajectory
% opt - Structure with the following fields:
% * dt - Step width in sec/step.
% * dTh - Below this distance threshold change speed
% and rotate away from the closest wall in cm.
% * sMin - Minimal speed in cm/sec.
% * sPeak - Target speed in cm/sec.
% * PosInit - Initial position with x,y coordinates in cm.
% * PosXInterval - Horizontal interval xMin and xMax in cm.
% * PosYInterval - Vertical interval yMin and yMax in cm.
% * DirInit - Initalization of direction, no UNIT.
% * nStep - Number of steps for this trajectory, no UNIT.
% * rayBeta - Beta parameter of Rayleigh distribution, in
% cm. This corresponds to the peak location of
% the distribution.
% * normMu - Mean value of normal distribution, in °/RAD.
% * normSimga - Standard deviation of normal distribution, in
% °/RAD.
%
% RETURN
% Pos - Position vector with x,y coordinates, which has the dimensions:
% nStep x 2.
%
% DESCRIPTION
% This script generates a random trajectory in the 2D plane within a box
% of the specified dimensions. The distribution of linear and rotational
% speeds follows that of data. Linear speed is modeled through a Rayleigh
% distribution and rotational speed is modeled through a normal
% distribution.
%
% Copyright (C) 2015 Florian Raudies, 05/02/2015, Palo Alto, CA.
% License, GNU GPL, free software, without any warranty.
%
if isfield(opt,'dt'), dt = opt.dt;
else dt = 0.02; end % sec/step
if isfield(opt,'dTh'), dTh = opt.dTh;
else dTh = 15; end % cm
if isfield(opt,'sMin'), sMin = opt.sMin;
else sMin = 5; end % cm/sec
if isfield(opt,'sPeak'), sPeak = opt.sPeak;
else sPeak = 20; end % cm/sec
if isfield(opt,'PosInit'), PosInit = opt.PosInit;
else PosInit = [0 0]; end % cm
if isfield(opt,'PosXInterval'), PosXInterval = opt.PosXInterval;
else PosXInterval = [-50 50]; end % cm
if isfield(opt,'PosYInterval'), PosYInterval = opt.PosYInterval;
else PosYInterval = [-50 50]; end % cm
if isfield(opt,'DirInit'), DirInit = opt.DirInit;
else DirInit = [0 1]; end % NONE
if isfield(opt,'nStep'), nStep = opt.nStep;
else nStep = 5*10^4; end % step
if isfield(opt,'rayBeta'), rayBeta = opt.rayBeta;
else rayBeta = 13.25; end % cm/sec
if isfield(opt,'normMu'), normMu = opt.normMu;
else normMu = 0.0; end % deg/sec
if isfield(opt,'normSigma'), normSigma = opt.normSigma;
else normSigma = 15.0; end % deg/sec
% Generate random turn speeds and linear speeds.
RandTurn = normMu/180*pi + randn(nStep,1)*normSigma/180*pi;
RandSpeed = raylrnd(rayBeta,[nStep 1]);
s = sPeak;
eta = 0.5;
Pos = zeros(nStep,2);
Pos(1,:) = PosInit';
Dir = DirInit;
% Define borders.
xMin = PosXInterval(1);
xMax = PosXInterval(2);
yMin = PosYInterval(1);
yMax = PosYInterval(2);
% Define the corners NorthEast, NorthWest, SouthEast, and SouthWest.
NE = [xMax yMax];
NW = [xMin yMax];
SE = [xMax yMin];
SW = [xMin yMin];
% Setup the walls. Points appear in this order to have always positive
% distances.
Wall = [wall2D(NW, NE); ... % top wall
wall2D(SW, NW); ... % left wall
wall2D(SE, SW); ... % bottom wall
wall2D(NE, SE)]; % right wall
for iStep = 2:nStep,
[dWall aWall] = minDistAngleWallInFoV2D(Wall, Pos(iStep-1,:), Dir, pi);
% Update speed and turn angle.
if dWall<dTh && abs(aWall)<pi/2,
s = s - eta*(s-sMin);
angle = sign(aWall)*(pi/2-abs(aWall)) + RandTurn(iStep,:);
else
s = RandSpeed(iStep);
angle = RandTurn(iStep,:);
end
% Move.
Pos(iStep,:) = Pos(iStep-1,:) + Dir*s*dt;
% Turn.
Dir = ([+cos(angle) -sin(angle); ...
+sin(angle) +cos(angle)]*Dir')';
end
function W = wall2D(P1, P2)
% Defines a wall by [nx ny d p1x p1y p2x p2y]
Delta = P2 - P1;
Delta = Delta/hypot(Delta(1), Delta(2));
d = - (P1(1)*Delta(2) - P1(2)*Delta(1));
W = [-Delta(2) Delta(1) d min(P1(1),P2(1)) min(P1(2),P2(2)) ...
max(P1(1),P2(1)) max(P1(2),P2(2))];
function [d a] = minDistAngleWallInFoV2D(Wall, Pos, Dir, foV)
NxWall = Wall(:,1);
NyWall = Wall(:,2);
DWall = Wall(:,3);
XMin = Wall(:,4);
YMin = Wall(:,5);
XMax = Wall(:,6);
YMax = Wall(:,7);
px = Pos(1);
py = Pos(2);
nx = Dir(1);
ny = Dir(2);
Valid = abs(NxWall*nx + NyWall*ny) > eps;
NxWall = NxWall(Valid);
NyWall = NyWall(Valid);
DWall = DWall(Valid);
D = (DWall - NxWall*px - NyWall*py)./(NxWall*nx + NyWall*ny);
Sx = px + D*nx;
Sy = py + D*ny;
% To avoid numerical problems need to add/sub 10^-5.
Valid = XMin(Valid) <= (Sx+10^-5) & (Sx-10^-5) <= XMax(Valid) ...
& YMin(Valid) <= (Sy+10^-5) & (Sy-10^-5) <= YMax(Valid);
NxWall = NxWall(Valid);
NyWall = NyWall(Valid);
D = D(Valid);
A = atan2(-NyWall*nx + NxWall*ny, NxWall*nx + NyWall*ny);
Valid = abs(A) <= foV/2;
D = D(Valid);
A = A(Valid);
[d,mi] = min(abs(D));
a = A(mi);