-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathMotionPlannerFrameworkOnline.m
169 lines (143 loc) · 5.35 KB
/
MotionPlannerFrameworkOnline.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
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
%MotionPlannerFrameworkOnline performs the online computation phase
% of a motion planning problem for a general system
%
% Ross Allen, ASL, Stanford University
%
% Started: June 26, 2015
%
% Inputs:
%
% Outputs:
% - exit condition:
% 1 = Successful plan
% 2 = Goal Satisfaction
% 0 = Accept existing plan
% -1 = FMT failure
% -2 = Smoother failure
% -3 = Other failure
%
% Notes:
% - Matlab 2012b or later should be used as certain Matlab functions
% experience adverse 'legacy' effects that will cause erros if older
% versions are used (e.g. svmtrain, intersect, ismember, etc)
% - 'mpinfo' stands for motion planning information and holds all
% relevant data for a motion planning problem (i.e. sampling info, robot
% info, machine learning info, etc.)
% - This has been generalized to a system-agnostic function
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [mpinfo, exitCond] = MotionPlannerFrameworkOnline(mpinfo)
% Run profiler if requested and not in MPC loop
if (~mpinfo.onlineOptions.runMPC)
if (mpinfo.profiler)
profile on
end
end
% start clock
onlineCompTimer = tic;
% initialize exit condition
exitCond = 1;
% Generate passive obstacles and encode in message to ViconWifiComm
[mpinfo, tcpSendBuf] = ObstacleHandlerPassive(mpinfo);
% Access active obstacle and termState data on ViconWifiComm TCP server
[mpinfo, continuePlanning] = ViconTCPHandler(mpinfo, tcpSendBuf);
if ~continuePlanning
disp('Planning terminated by ViconTCPHandler due to goal satisfaction');
exitCond = 2;
return;
end
% Extract active obstacles from TCP connection to ViconWifiComm
mpinfo = ObstacleHandlerActive(mpinfo);
if (~isfield(mpinfo.obstacles, 'spheres'))
mpinfo.obstacles.spheres = [];
end
% Estimate planning start state based on current state
[mpinfo, continuePlanning] = EstimatePlannerStartState(mpinfo);
if ~continuePlanning
disp('Planning terminated because existing plan valid');
exitCond = 0;
return;
end
mpinfo.stateMat(1,:) = mpinfo.termStates.Xstart;
% Sample Goal Region
mpinfo = GoalRegionSampler(mpinfo);
mpinfo.stateMat(2:mpinfo.sampling.nGoalSamples+1,:) = mpinfo.termStates.Xgoal;
% Perform error check
mpinfo.onlineError = OnlineErrorCheck(mpinfo);
if mpinfo.inputError.flag > 0
disp('User input invalid at online initiation. Check onlineError code');
exitCond = -3;
return;
end
% Classify neighborhoods of start and goal states
mpinfo = ClassifyTerminalNeighborhoods(mpinfo);
% Approximate cost of outgoing neighborhood of start state
mpinfo.termStates.startEstOutNeighbors = ...
Estimate2PBVPCosts(mpinfo.termStates.reachableFromXstart,...
1, [1:mpinfo.nTotSamples]', mpinfo);
% Approximate cost of incoming neighborhoods of goal region
mpinfo.termStates.goalEstInNeighbors = cell(...
mpinfo.sampling.nGoalSamples, 1);
for i = 1:mpinfo.sampling.nGoalSamples
mpinfo.termStates.goalEstInNeighbors{i} = ...
Estimate2PBVPCosts(mpinfo.termStates.XgoalReachableFrom(:,i),...
[1:mpinfo.nTotSamples]', i, mpinfo);
end
clear i
% Optimally connect start and state to its approximate out-neighboorhood
mpinfo = Solve2PBVPsNeighborhoodSet(...
ones(size(mpinfo.termStates.startEstOutNeighbors,1),1),...
mpinfo.termStates.startEstOutNeighbors(:,1),...
mpinfo.onlineOptions.maxNeighbors, mpinfo);
if isempty(mpinfo.outNeighborCell{1})
disp('NEIGHBOR FAILURE: No neighbors found for Xstart');
mpinfo.fmtFailure = true;
exitCond = -1;
return;
end
% Optimally connect goal region samples to approximate in-neighboorhoods
for i = 2:mpinfo.sampling.nGoalSamples+1
mpinfo = Solve2PBVPsNeighborhoodSet(...
mpinfo.termStates.goalEstInNeighbors{i-1}(:,1),...
i*ones(size(mpinfo.termStates.goalEstInNeighbors{i-1},1),1),...
mpinfo.onlineOptions.maxNeighbors, mpinfo);
end
clear i
% Run Kinodynamic Fast Marching Trees
mpinfo = RunKinoFMT_MEX(mpinfo);
% Smooth plan and/or communicate solution
if (~mpinfo.fmtFailure && isfield(mpinfo, 'optCost') && ~isnan(mpinfo.optCost))
% Run smoothing function if it exist
if (isfield(mpinfo.systemDefs, 'TrajectorySmoother') && ...
isfield(mpinfo, 'smoother') && mpinfo.smoother.applySmoothing)
mpinfo = mpinfo.systemDefs.TrajectorySmoother(mpinfo);
if ~mpinfo.smoother.valid
disp('FAILURE: Smoother')
exitCond = -2;
end
end
else
disp('FAILURE: Planner')
exitCond = -1;
end
% Run communicator
if (isfield(mpinfo,'comms') && mpinfo.comms.xmitTrajectory)
mpinfo.systemDefs.CommsWriter(mpinfo);
end
% log computation time
mpinfo.onlineCompTime = toc(onlineCompTimer);
% Run exit protocol if not in an MPC loop
if (~mpinfo.onlineOptions.runMPC)
% Profiler
if (mpinfo.profiler)
profile viewer
profsave(profile('info'), [mpinfo.savefile, '_profiler'])
end
% Close communications
if (isfield(mpinfo.comms, 'tcpClient') && strcmp(mpinfo.comms.tcpClient.Status, 'open'))
fclose(mpinfo.comms.tcpClient);
delete(mpinfo.comms.tcpClient);
end
% Save data
save([mpinfo.savefile, '_complete']);
end
end