@@ -68,12 +68,15 @@ class Experiment {
68
68
69
69
size_t maxNrHypotheses = 10 ;
70
70
71
+ size_t reLinearizationFrequency = 10 ;
72
+
73
+ double marginalThreshold = 0.9999 ;
74
+
71
75
private:
72
76
std::string filename_;
73
77
HybridSmoother smoother_;
74
- HybridNonlinearFactorGraph graph_ ;
78
+ HybridNonlinearFactorGraph newFactors_, allFactors_ ;
75
79
Values initial_;
76
- Values result_;
77
80
78
81
/* *
79
82
* @brief Write the result of optimization to file.
@@ -83,7 +86,7 @@ class Experiment {
83
86
* @param filename The file name to save the result to.
84
87
*/
85
88
void writeResult (const Values& result, size_t numPoses,
86
- const std::string& filename = " Hybrid_city10000.txt" ) {
89
+ const std::string& filename = " Hybrid_city10000.txt" ) const {
87
90
std::ofstream outfile;
88
91
outfile.open (filename);
89
92
@@ -100,9 +103,9 @@ class Experiment {
100
103
* @brief Create a hybrid loop closure factor where
101
104
* 0 - loose noise model and 1 - loop noise model.
102
105
*/
103
- HybridNonlinearFactor hybridLoopClosureFactor (size_t loopCounter, size_t keyS,
104
- size_t keyT,
105
- const Pose2& measurement) {
106
+ HybridNonlinearFactor hybridLoopClosureFactor (
107
+ size_t loopCounter, size_t keyS, size_t keyT,
108
+ const Pose2& measurement) const {
106
109
DiscreteKey l (L (loopCounter), 2 );
107
110
108
111
auto f0 = std::make_shared<BetweenFactor<Pose2>>(
@@ -119,7 +122,7 @@ class Experiment {
119
122
// / @brief Create hybrid odometry factor with discrete measurement choices.
120
123
HybridNonlinearFactor hybridOdometryFactor (
121
124
size_t numMeasurements, size_t keyS, size_t keyT, const DiscreteKey& m,
122
- const std::vector<Pose2>& poseArray) {
125
+ const std::vector<Pose2>& poseArray) const {
123
126
auto f0 = std::make_shared<BetweenFactor<Pose2>>(
124
127
X (keyS), X (keyT), poseArray[0 ], kPoseNoiseModel );
125
128
auto f1 = std::make_shared<BetweenFactor<Pose2>>(
@@ -132,25 +135,59 @@ class Experiment {
132
135
}
133
136
134
137
// / @brief Perform smoother update and optimize the graph.
135
- void smootherUpdate (HybridSmoother& smoother,
136
- HybridNonlinearFactorGraph& graph, const Values& initial,
137
- size_t maxNrHypotheses, Values* result) {
138
- HybridGaussianFactorGraph linearized = *graph.linearize (initial);
139
- smoother.update (linearized, maxNrHypotheses);
140
- // throw if x0 not in hybridBayesNet_:
141
- const KeySet& keys = smoother.hybridBayesNet ().keys ();
142
- if (keys.find (X (0 )) == keys.end ()) {
143
- throw std::runtime_error (" x0 not in hybridBayesNet_" );
138
+ auto smootherUpdate (size_t maxNrHypotheses) {
139
+ std::cout << " Smoother update: " << newFactors_.size () << std::endl;
140
+ gttic_ (SmootherUpdate);
141
+ clock_t beforeUpdate = clock ();
142
+ auto linearized = newFactors_.linearize (initial_);
143
+ smoother_.update (*linearized, maxNrHypotheses);
144
+ allFactors_.push_back (newFactors_);
145
+ newFactors_.resize (0 );
146
+ clock_t afterUpdate = clock ();
147
+ return afterUpdate - beforeUpdate;
148
+ }
149
+
150
+ // / @brief Re-linearize, solve ALL, and re-initialize smoother.
151
+ auto reInitialize () {
152
+ std::cout << " ================= Re-Initialize: " << allFactors_.size ()
153
+ << std::endl;
154
+ clock_t beforeUpdate = clock ();
155
+ allFactors_ = allFactors_.restrict (smoother_.fixedValues ());
156
+ auto linearized = allFactors_.linearize (initial_);
157
+ auto bayesNet = linearized->eliminateSequential ();
158
+ HybridValues delta = bayesNet->optimize ();
159
+ initial_ = initial_.retract (delta.continuous ());
160
+ smoother_.reInitialize (std::move (*bayesNet));
161
+ clock_t afterUpdate = clock ();
162
+ std::cout << " Took " << (afterUpdate - beforeUpdate) / CLOCKS_PER_SEC
163
+ << " seconds." << std::endl;
164
+ return afterUpdate - beforeUpdate;
165
+ }
166
+
167
+ // Parse line from file
168
+ std::pair<std::vector<Pose2>, std::pair<size_t , size_t >> parseLine (
169
+ const std::string& line) const {
170
+ std::vector<std::string> parts;
171
+ split (parts, line, is_any_of (" " ));
172
+
173
+ size_t keyS = stoi (parts[1 ]);
174
+ size_t keyT = stoi (parts[3 ]);
175
+
176
+ int numMeasurements = stoi (parts[5 ]);
177
+ std::vector<Pose2> poseArray (numMeasurements);
178
+ for (int i = 0 ; i < numMeasurements; ++i) {
179
+ double x = stod (parts[6 + 3 * i]);
180
+ double y = stod (parts[7 + 3 * i]);
181
+ double rad = stod (parts[8 + 3 * i]);
182
+ poseArray[i] = Pose2 (x, y, rad);
144
183
}
145
- graph.resize (0 );
146
- // HybridValues delta = smoother.hybridBayesNet().optimize();
147
- // result->insert_or_assign(initial.retract(delta.continuous()));
184
+ return {poseArray, {keyS, keyT}};
148
185
}
149
186
150
187
public:
151
188
// / Construct with filename of experiment to run
152
189
explicit Experiment (const std::string& filename)
153
- : filename_(filename), smoother_(0.99 ) {}
190
+ : filename_(filename), smoother_(marginalThreshold ) {}
154
191
155
192
// / @brief Run the main experiment with a given maxLoopCount.
156
193
void run () {
@@ -162,49 +199,34 @@ class Experiment {
162
199
}
163
200
164
201
// Initialize local variables
165
- size_t discreteCount = 0 , index = 0 ;
166
- size_t loopCount = 0 ;
202
+ size_t discreteCount = 0 , index = 0 , loopCount = 0 , updateCount = 0 ;
167
203
168
204
std::list<double > timeList;
169
205
170
206
// Set up initial prior
171
- double x = 0.0 ;
172
- double y = 0.0 ;
173
- double rad = 0.0 ;
174
-
175
- Pose2 priorPose (x, y, rad);
207
+ Pose2 priorPose (0 , 0 , 0 );
176
208
initial_.insert (X (0 ), priorPose);
177
- graph_.push_back (PriorFactor<Pose2>(X (0 ), priorPose, kPriorNoiseModel ));
209
+ newFactors_.push_back (
210
+ PriorFactor<Pose2>(X (0 ), priorPose, kPriorNoiseModel ));
178
211
179
212
// Initial update
180
- clock_t beforeUpdate = clock ();
181
- smootherUpdate (smoother_, graph_, initial_, maxNrHypotheses, &result_);
182
- clock_t afterUpdate = clock ();
213
+ auto time = smootherUpdate (maxNrHypotheses);
183
214
std::vector<std::pair<size_t , double >> smootherUpdateTimes;
184
- smootherUpdateTimes.push_back ({index , afterUpdate - beforeUpdate });
215
+ smootherUpdateTimes.push_back ({index , time });
185
216
186
217
// Flag to decide whether to run smoother update
187
218
size_t numberOfHybridFactors = 0 ;
188
219
189
220
// Start main loop
221
+ Values result;
190
222
size_t keyS = 0 , keyT = 0 ;
191
223
clock_t startTime = clock ();
192
224
std::string line;
193
225
while (getline (in, line) && index < maxLoopCount) {
194
- std::vector<std::string> parts;
195
- split (parts, line, is_any_of (" " ));
196
-
197
- keyS = stoi (parts[1 ]);
198
- keyT = stoi (parts[3 ]);
199
-
200
- int numMeasurements = stoi (parts[5 ]);
201
- std::vector<Pose2> poseArray (numMeasurements);
202
- for (int i = 0 ; i < numMeasurements; ++i) {
203
- x = stod (parts[6 + 3 * i]);
204
- y = stod (parts[7 + 3 * i]);
205
- rad = stod (parts[8 + 3 * i]);
206
- poseArray[i] = Pose2 (x, y, rad);
207
- }
226
+ auto [poseArray, keys] = parseLine (line);
227
+ keyS = keys.first ;
228
+ keyT = keys.second ;
229
+ size_t numMeasurements = poseArray.size ();
208
230
209
231
// Take the first one as the initial estimate
210
232
Pose2 odomPose = poseArray[0 ];
@@ -215,13 +237,13 @@ class Experiment {
215
237
DiscreteKey m (M (discreteCount), numMeasurements);
216
238
HybridNonlinearFactor mixtureFactor =
217
239
hybridOdometryFactor (numMeasurements, keyS, keyT, m, poseArray);
218
- graph_ .push_back (mixtureFactor);
240
+ newFactors_ .push_back (mixtureFactor);
219
241
discreteCount++;
220
242
numberOfHybridFactors += 1 ;
221
243
std::cout << " mixtureFactor: " << keyS << " " << keyT << std::endl;
222
244
} else {
223
- graph_ .add (BetweenFactor<Pose2>(X (keyS), X (keyT), odomPose,
224
- kPoseNoiseModel ));
245
+ newFactors_ .add (BetweenFactor<Pose2>(X (keyS), X (keyT), odomPose,
246
+ kPoseNoiseModel ));
225
247
}
226
248
// Insert next pose initial guess
227
249
initial_.insert (X (keyT), initial_.at <Pose2>(X (keyS)) * odomPose);
@@ -231,21 +253,20 @@ class Experiment {
231
253
hybridLoopClosureFactor (loopCount, keyS, keyT, odomPose);
232
254
// print loop closure event keys:
233
255
std::cout << " Loop closure: " << keyS << " " << keyT << std::endl;
234
- graph_ .add (loopFactor);
256
+ newFactors_ .add (loopFactor);
235
257
numberOfHybridFactors += 1 ;
236
258
loopCount++;
237
259
}
238
260
239
261
if (numberOfHybridFactors >= updateFrequency) {
240
- // print the keys involved in the smoother update
241
- std::cout << " Smoother update: " << graph_.size () << std::endl;
242
- gttic_ (SmootherUpdate);
243
- beforeUpdate = clock ();
244
- smootherUpdate (smoother_, graph_, initial_, maxNrHypotheses, &result_);
245
- afterUpdate = clock ();
246
- smootherUpdateTimes.push_back ({index , afterUpdate - beforeUpdate});
247
- gttoc_ (SmootherUpdate);
262
+ auto time = smootherUpdate (maxNrHypotheses);
263
+ smootherUpdateTimes.push_back ({index , time });
248
264
numberOfHybridFactors = 0 ;
265
+ updateCount++;
266
+
267
+ if (updateCount % reLinearizationFrequency == 0 ) {
268
+ reInitialize ();
269
+ }
249
270
}
250
271
251
272
// Record timing for odometry edges only
@@ -270,17 +291,15 @@ class Experiment {
270
291
}
271
292
272
293
// Final update
273
- beforeUpdate = clock ();
274
- smootherUpdate (smoother_, graph_, initial_, maxNrHypotheses, &result_);
275
- afterUpdate = clock ();
276
- smootherUpdateTimes.push_back ({index , afterUpdate - beforeUpdate});
294
+ time = smootherUpdate (maxNrHypotheses);
295
+ smootherUpdateTimes.push_back ({index , time });
277
296
278
297
// Final optimize
279
298
gttic_ (HybridSmootherOptimize);
280
299
HybridValues delta = smoother_.optimize ();
281
300
gttoc_ (HybridSmootherOptimize);
282
301
283
- result_ .insert_or_assign (initial_.retract (delta.continuous ()));
302
+ result .insert_or_assign (initial_.retract (delta.continuous ()));
284
303
285
304
std::cout << " Final error: " << smoother_.hybridBayesNet ().error (delta)
286
305
<< std::endl;
@@ -291,7 +310,7 @@ class Experiment {
291
310
<< std::endl;
292
311
293
312
// Write results to file
294
- writeResult (result_ , keyT + 1 , " Hybrid_City10000.txt" );
313
+ writeResult (result , keyT + 1 , " Hybrid_City10000.txt" );
295
314
296
315
// TODO Write to file
297
316
// for (size_t i = 0; i < smoother_update_times.size(); i++) {
0 commit comments