46 typedef ISAM2BayesTree This;
47 typedef std::shared_ptr<This> shared_ptr;
55class ISAM2JunctionTree
56 :
public JunctionTree<ISAM2BayesTree, GaussianFactorGraph> {
59 typedef ISAM2JunctionTree This;
60 typedef std::shared_ptr<This> shared_ptr;
63 :
Base(eliminationTree) {}
73 size_t nFullSystemVars;
74 enum { COLAMD } algorithm;
75 enum { NO_CONSTRAINT, CONSTRAIN_LAST } constrain;
76 std::optional<FastMap<Key, int> > constrainedKeys;
83 const KeySet& replacedKeys,
84 double wildfireThreshold,
92 const KeySet& replacedKeys,
109struct GTSAM_EXPORT UpdateImpl {
113 : params_(params), updateParams_(updateParams) {}
117 const ISAM2& isam2) {
118 gttic(pushBackFactors);
119 const bool debug = ISDEBUG(
"ISAM2 update");
120 const bool verbose = ISDEBUG(
"ISAM2 update verbose");
123 std::cout <<
"ISAM2::update\n";
124 isam2.
print(
"ISAM2: ");
127 if (debug || verbose) {
128 newFactors.
print(
"The new factors are: ");
134 bool relinarizationNeeded(
size_t update_count)
const {
135 return updateParams_.force_relinearize ||
136 (params_.enableRelinearization &&
137 update_count % params_.relinearizeSkip == 0);
146 KeySet* keysWithRemovedFactors)
const {
147 gttic(pushBackFactors);
153 *newFactorsIndices = nonlinearFactors->
add_factors(
154 newFactors, params_.findUnusedFactorSlots);
158 removedFactors.
reserve(updateParams_.removeFactorIndices.size());
159 for (
const auto index : updateParams_.removeFactorIndices) {
160 removedFactors.
push_back(nonlinearFactors->
at(index));
161 nonlinearFactors->
remove(index);
162 if (params_.cacheLinearizedFactors) linearFactors->
remove(index);
167 variableIndex->
remove(updateParams_.removeFactorIndices.begin(),
168 updateParams_.removeFactorIndices.end(),
170 *keysWithRemovedFactors = removedFactors.
keys();
177 const KeySet& keysWithRemovedFactors,
178 KeySet* unusedKeys)
const {
179 gttic(computeUnusedKeys);
181 if (keysWithRemovedFactors.empty())
return;
182 KeySet removedAndEmpty;
183 for (
Key key : keysWithRemovedFactors) {
184 if (variableIndex.
empty(key))
185 removedAndEmpty.insert(removedAndEmpty.end(), key);
187 KeySet newFactorSymbKeys = newFactors.
keys();
188 std::set_difference(removedAndEmpty.begin(), removedAndEmpty.end(),
189 newFactorSymbKeys.begin(), newFactorSymbKeys.end(),
190 std::inserter(*unusedKeys, unusedKeys->end()));
195 const Values& estimate, std::optional<double>* result)
const {
197 *result = nonlinearFactors.
error(estimate);
203 const KeySet& keysWithRemovedFactors,
204 KeySet* markedKeys)
const {
205 gttic(gatherInvolvedKeys);
206 *markedKeys = newFactors.
keys();
208 markedKeys->insert(keysWithRemovedFactors.begin(),
209 keysWithRemovedFactors.end());
212 if (updateParams_.extraReelimKeys) {
213 for (
Key key : *updateParams_.extraReelimKeys) {
214 markedKeys->insert(key);
220 if (updateParams_.newAffectedKeys) {
221 for (
const auto& factorAddedKeys : *updateParams_.newAffectedKeys) {
222 const auto factorIdx = factorAddedKeys.first;
223 const auto& affectedKeys = nonlinearFactors.
at(factorIdx)->keys();
224 markedKeys->insert(affectedKeys.begin(), affectedKeys.end());
230 void updateKeys(
const KeySet& markedKeys,
ISAM2Result* result)
const {
233 if (result->
detail && params_.enableDetailedResults) {
234 for (
Key key : markedKeys) {
235 result->
detail->variableStatus[key].isObserved =
true;
239 for (
Key index : markedKeys) {
247 static void CheckRelinearizationRecursiveMap(
251 bool relinearize =
false;
252 for (
Key var : *clique->conditional()) {
254 const Vector& threshold = thresholds.find(
Symbol(var).chr())->second;
256 const Vector& deltaVar = delta[var];
259 if (threshold.rows() != deltaVar.rows())
260 throw std::invalid_argument(
261 "Relinearization threshold vector dimensionality for '" +
262 std::string(1,
Symbol(var).chr()) +
263 "' passed into iSAM2 parameters does not match actual variable "
267 if ((deltaVar.array().abs() > threshold.array()).any()) {
268 relinKeys->insert(var);
276 CheckRelinearizationRecursiveMap(thresholds, delta, child, relinKeys);
281 static void CheckRelinearizationRecursiveDouble(
285 bool relinearize =
false;
286 for (
Key var : *clique->conditional()) {
287 double maxDelta = delta[var].lpNorm<Eigen::Infinity>();
288 if (maxDelta >= threshold) {
289 relinKeys->insert(var);
297 CheckRelinearizationRecursiveDouble(threshold, delta, child, relinKeys);
320 if (std::holds_alternative<double>(relinearizeThreshold)) {
321 CheckRelinearizationRecursiveDouble(
322 std::get<double>(relinearizeThreshold), delta, root, &relinKeys);
324 CheckRelinearizationRecursiveMap(
348 if (
const double* threshold = std::get_if<double>(&relinearizeThreshold)) {
350 double maxDelta = key_delta.second.lpNorm<Eigen::Infinity>();
351 if (maxDelta >= *threshold) relinKeys.insert(key_delta.first);
356 const Vector& threshold =
357 thresholds->find(
Symbol(key_delta.first).
chr())->second;
358 if (threshold.rows() != key_delta.second.rows())
359 throw std::invalid_argument(
360 "Relinearization threshold vector dimensionality for '" +
361 std::string(1,
Symbol(key_delta.first).
chr()) +
362 "' passed into iSAM2 parameters does not match actual variable "
364 if ((key_delta.second.array().abs() > threshold.array()).any())
365 relinKeys.insert(key_delta.first);
375 const KeySet& fixedVariables,
376 KeySet* markedKeys)
const {
377 gttic(gatherRelinearizeKeys);
380 params_.enablePartialRelinearizationCheck
381 ? CheckRelinearizationPartial(roots, delta,
382 params_.relinearizeThreshold)
383 : CheckRelinearizationFull(delta, params_.relinearizeThreshold);
385 relinKeys = CheckRelinearizationFull(delta, 0.0);
388 for (
Key key : fixedVariables) {
389 relinKeys.erase(key);
392 for (Key key : *updateParams_.noRelinKeys) {
393 relinKeys.erase(key);
398 markedKeys->insert(relinKeys.begin(), relinKeys.end());
403 void recordRelinearizeDetail(
const KeySet& relinKeys,
405 if (detail && params_.enableDetailedResults) {
406 for (
Key key : relinKeys) {
407 detail->variableStatus[key].isAboveRelinThreshold =
true;
408 detail->variableStatus[key].isRelinearized =
true;
415 void findFluid(
const ISAM2::Roots& roots,
const KeySet& relinKeys,
419 for (
const auto& root : roots)
421 root->findAll(relinKeys, markedKeys);
424 if (detail && params_.enableDetailedResults) {
425 KeySet involvedRelinKeys;
426 for (
const auto& root : roots)
427 root->findAll(relinKeys, &involvedRelinKeys);
428 for (
Key key : involvedRelinKeys) {
429 if (!detail->variableStatus[key].isAboveRelinThreshold) {
430 detail->variableStatus[key].isRelinearizeInvolved =
true;
431 detail->variableStatus[key].isRelinearized =
true;
439 const Values& theta,
size_t numNonlinearFactors,
442 gttic(linearizeNewFactors);
443 auto linearized = newFactors.linearize(theta);
444 if (params_.findUnusedFactorSlots) {
445 linearFactors->resize(numNonlinearFactors);
446 for (
size_t i = 0; i < newFactors.size(); ++i)
447 (*linearFactors)[newFactorsIndices[i]] = (*linearized)[i];
449 linearFactors->push_back(*linearized);
451 assert(linearFactors->size() == numNonlinearFactors);
457 gttic(augmentVariableIndex);
459 if (params_.findUnusedFactorSlots)
460 variableIndex->augment(newFactors, newFactorsIndices);
462 variableIndex->augment(newFactors);
467 const auto factorIdx = factorAddedKeys.first;
468 variableIndex->augmentExistingFactor(factorIdx, factorAddedKeys.second);
473 static void LogRecalculateKeys(
const ISAM2Result& result) {
474 const bool debug = ISDEBUG(
"ISAM2 recalculate");
477 std::cout <<
"markedKeys: ";
478 for (
const Key key : result.markedKeys) {
479 std::cout << key <<
" ";
481 std::cout << std::endl;
482 std::cout <<
"observedKeys: ";
483 for (
const Key key : result.observedKeys) {
484 std::cout << key <<
" ";
486 std::cout << std::endl;
490 static FactorIndexSet GetAffectedFactors(
const KeyList& keys,
492 gttic(GetAffectedFactors);
493 FactorIndexSet indices;
494 for (
const Key key : keys) {
496 indices.insert(factors.begin(), factors.end());
507 for (
const auto& orphan : orphans) {
509 cachedBoundary.push_back(orphan->cachedFactor());
512 return cachedBoundary;
The junction tree, template bodies.
Gaussian Bayes Tree, the result of eliminating a GaussianJunctionTree.
Incremental update functionality (ISAM2) for BayesTree, with fluid relinearization.
Class that stores detailed iSAM2 result.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
FastVector< FactorIndex > FactorIndices
Define collection types:
Definition Factor.h:37
std::uint64_t Key
Integer nonlinear key type.
Definition types.h:43
FastMap is a thin wrapper around std::map that uses the boost fast_pool_allocator instead of the defa...
Definition FastMap.h:40
KeySet keys() const
Potentially slow function to return all keys involved, sorted, as a set.
Definition FactorGraph-inst.h:85
FactorIndices add_factors(const CONTAINER &factors, bool useEmptySlots=false)
Add new factors to a factor graph and returns a list of new factor indices, optionally finding and re...
Definition FactorGraph-inst.h:109
IsDerived< DERIVEDFACTOR > push_back(std::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
Definition FactorGraph.h:147
void remove(size_t i)
delete factor without re-arranging indexes by inserting a nullptr pointer
Definition FactorGraph.h:371
const sharedFactor at(size_t i) const
Get a specific factor by index (this checks array bounds and may throw an exception,...
Definition FactorGraph.h:306
void reserve(size_t size)
Reserve space for the specified number of factors if you know in advance how many there will be (work...
Definition FactorGraph.h:143
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
print
Definition BayesTree-inst.h:253
FastVector< sharedClique > Roots
Definition BayesTree.h:105
JunctionTree(const EliminationTree< ETREE_BAYESNET, ETREE_GRAPH > &eliminationTree)
EliminatableClusterTree< ISAM2BayesTree, GaussianFactorGraph > Base
Definition JunctionTree.h:56
Character and index key used to refer to variables.
Definition Symbol.h:37
unsigned char chr() const
Retrieve key character.
Definition Symbol.h:75
The VariableIndex class computes and stores the block column structure of a factor graph.
Definition VariableIndex.h:41
void remove(ITERATOR firstFactor, ITERATOR lastFactor, const FG &factors)
Remove entries corresponding to the specified factors.
Definition VariableIndex-inl.h:53
bool empty(Key variable) const
Return true if no factors associated with a variable.
Definition VariableIndex.cpp:40
Definition GaussianEliminationTree.h:29
A Linear Factor Graph is a factor graph where all factors are Gaussian, i.e.
Definition GaussianFactorGraph.h:77
VectorValues represents a collection of vector-valued variables associated each with a unique integer...
Definition VectorValues.h:73
value_type KeyValuePair
Typedef to pair<Key, Vector>.
Definition VectorValues.h:84
Definition ISAM2-impl.h:67
static size_t UpdateGaussNewtonDelta(const ISAM2::Roots &roots, const KeySet &replacedKeys, double wildfireThreshold, VectorValues *delta)
Update the Newton's method step point, using wildfire.
Definition ISAM2-impl.cpp:48
static VectorValues ComputeGradientSearch(const VectorValues &gradAtZero, const VectorValues &RgProd)
Compute the gradient-search point.
Definition ISAM2-impl.cpp:146
static size_t UpdateRgProd(const ISAM2::Roots &roots, const KeySet &replacedKeys, const VectorValues &gradAtZero, VectorValues *RgProd)
Update the RgProd (R*g) incrementally taking into account which variables have been recalculated in r...
Definition ISAM2-impl.cpp:131
Definition ISAM2-impl.h:68
Definition ISAM2-impl.h:72
static KeySet CheckRelinearizationFull(const VectorValues &delta, const ISAM2Params::RelinearizationThreshold &relinearizeThreshold)
Find the set of variables to be relinearized according to relinearizeThreshold.
Definition ISAM2-impl.h:343
static KeySet CheckRelinearizationPartial(const ISAM2::Roots &roots, const VectorValues &delta, const ISAM2Params::RelinearizationThreshold &relinearizeThreshold)
Find the set of variables to be relinearized according to relinearizeThreshold.
Definition ISAM2-impl.h:315
Implementation of the full ISAM2 algorithm for incremental nonlinear optimization.
Definition ISAM2.h:45
BayesTree< ISAM2Clique > Base
The BayesTree base class.
Definition ISAM2.h:104
Base::Cliques Cliques
List of Cliques.
Definition ISAM2.h:107
Base::sharedClique sharedClique
Shared pointer to a clique.
Definition ISAM2.h:106
Definition ISAM2Params.h:199
std::variant< double, FastMap< char, Vector > > RelinearizationThreshold
Either a constant relinearization threshold or a per-variable-type set of thresholds.
Definition ISAM2Params.h:206
This struct is returned from ISAM2::update() and contains information about the update that is useful...
Definition ISAM2Result.h:39
std::optional< DetailedResults > detail
Detailed results, if enabled by ISAM2Params::enableDetailedResults.
Definition ISAM2Result.h:167
KeySet unusedKeys
Unused keys, and indices for unused keys, i.e., keys that are empty now and do not appear in the new ...
Definition ISAM2Result.h:111
KeyVector observedKeys
keys for variables that were observed, i.e., not unused.
Definition ISAM2Result.h:114
A struct holding detailed results, which must be enabled with ISAM2Params::enableDetailedResults.
Definition ISAM2Result.h:126
This struct is used by ISAM2::update() to pass additional parameters to give the user a fine-grained ...
Definition ISAM2UpdateParams.h:32
std::optional< FastList< Key > > noRelinKeys
An optional set of nonlinear keys that iSAM2 will hold at a constant linearization point,...
Definition ISAM2UpdateParams.h:44
std::optional< FastMap< FactorIndex, KeySet > > newAffectedKeys
An optional set of new Keys that are now affected by factors, indexed by factor indices (as returned ...
Definition ISAM2UpdateParams.h:66
bool forceFullSolve
By default, iSAM2 uses a wildfire update scheme that stops updating when the deltas become too small ...
Definition ISAM2UpdateParams.h:71
Definition NonlinearFactorGraph.h:57
void print(const std::string &str="NonlinearFactorGraph: ", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition NonlinearFactorGraph.cpp:56
virtual double error(const Values &values) const
unnormalized error, in the most common case
Definition NonlinearFactorGraph.cpp:171
A non-templated config holding any types of Manifold-group elements.
Definition Values.h:65