45 bool update(
const gtsam::NonlinearFactorGraph& newGraphFactors,
const gtsam::Values& newGraphValues,
46 const std::map<gtsam::Key, double>& newGraphKeysTimeStampMap,
const int depth = 0) {
50 <<
" Maximum recursion depth reached (" << depth <<
"). Aborting optimization."
63 catch (
const std::out_of_range& outOfRangeException) {
64 std::cerr <<
YELLOW_START <<
"GMsf-ISAM2" <<
RED_START <<
" OutOfRange-Exception while optimizing graph: '"
65 << outOfRangeException.what() <<
"'." <<
COLOR_END << std::endl;
67 <<
" This happens if the FixedLagSmoother tries to marginalize out states that have never been optimized before. This e.g. "
68 "happens if the graph hasn't been optimized for the duration of the smoother lag. Increase the lag or optimization "
69 "frequency in this case."
73 double latestTimeStamp = 0.0;
74 for (
auto factor : newGraphFactors) {
75 for (
auto key : factor->keys()) {
77 if (newGraphKeysTimeStampMap.find(key) != newGraphKeysTimeStampMap.end()) {
78 if (newGraphKeysTimeStampMap.at(key) > latestTimeStamp) {
79 latestTimeStamp = newGraphKeysTimeStampMap.at(key);
84 std::cout <<
YELLOW_START <<
"GMsf-ISAM2" <<
RED_START <<
" Latest timestamp in new factors: " << std::setprecision(14)
85 << latestTimeStamp <<
COLOR_END << std::endl;
87 bool filteredOutAtLeastOneKey =
false;
89 gtsam::NonlinearFactorGraph newGraphFactorsFiltered = gtsam::NonlinearFactorGraph();
91 std::map<gtsam::Key, double> newGraphKeysTimeStampMapFiltered = newGraphKeysTimeStampMap;
93 for (
auto factor : newGraphFactors) {
94 bool factorOnlyContainsExistentKeys =
true;
95 for (
auto key : factor->keys()) {
97 if (newGraphKeysTimeStampMap.find(key) != newGraphKeysTimeStampMap.end()) {
98 double timestampAtKey = newGraphKeysTimeStampMap.at(key);
100 if (latestTimeStamp - timestampAtKey >
graphConfigPtr_->realTimeSmootherLag_) {
102 <<
" Factor contains key older than smoother lag: " << gtsam::Symbol(key) <<
", which is "
103 << latestTimeStamp - timestampAtKey <<
"s old." <<
COLOR_END << std::endl;
104 factorOnlyContainsExistentKeys =
false;
105 filteredOutAtLeastOneKey =
true;
108 else if (timestampAtKey > latestTimeStamp) {
109 std::cout <<
YELLOW_START <<
"GMsf-ISAM2" <<
RED_START <<
" Factor contains key from the future: " << gtsam::Symbol(key)
110 <<
", which is " << timestampAtKey <<
"s in the future." <<
COLOR_END << std::endl;
111 factorOnlyContainsExistentKeys =
false;
112 filteredOutAtLeastOneKey =
true;
117 if (factorOnlyContainsExistentKeys) {
118 newGraphFactorsFiltered.add(factor);
124 if (filteredOutAtLeastOneKey) {
126 <<
" Filtered out factors that are either older than the smoother lag or coming from the future. Trying to optimize "
129 return update(newGraphFactorsFiltered, newGraphValues, newGraphKeysTimeStampMapFiltered);
135 <<
" Could not filter out any factors that are either older than the smoother lag or coming from the future. Aborting "
142 catch (
const gtsam::ValuesKeyDoesNotExist& valuesKeyDoesNotExistException) {
143 std::cout <<
"----------------------------------------------------------" << std::endl;
145 << valuesKeyDoesNotExistException.what() <<
"'" << std::endl;
147 <<
" This happens if a factor is added to the graph that contains a non-existent state. The most common case is a factor "
148 "containing a graph state that was marginalized out before. To avoid this, increase the factor graph lag or reduce "
149 "the delay of your measurements."
153 gtsam::NonlinearFactorGraph newGraphFactorsFiltered;
154 gtsam::Key valuesKeyNotExistent = valuesKeyDoesNotExistException.key();
155 bool removedAtLeastOneFactorOrKey =
false;
156 for (
auto factor : newGraphFactors) {
157 bool factorContainsExistentKeys =
true;
158 for (
auto key : factor->keys()) {
159 if (key == valuesKeyNotExistent) {
160 std::cout <<
YELLOW_START <<
"GMsf-ISAM2" <<
RED_START <<
" Factor contains non-existent key: " << gtsam::Symbol(key)
161 <<
". -> Removed." <<
COLOR_END << std::endl;
162 factorContainsExistentKeys =
false;
163 removedAtLeastOneFactorOrKey =
true;
167 if (factorContainsExistentKeys) {
168 newGraphFactorsFiltered.add(factor);
173 std::map<gtsam::Key, double> newGraphKeysTimeStampMapFiltered;
174 for (
auto keyTimeStamp : newGraphKeysTimeStampMap) {
175 if (keyTimeStamp.first != valuesKeyNotExistent) {
176 newGraphKeysTimeStampMapFiltered.insert(keyTimeStamp);
179 <<
" GraphKeysTimeStampMap contains non-existent key: " << gtsam::Symbol(keyTimeStamp.first) <<
". -> Removed."
181 removedAtLeastOneFactorOrKey =
true;
186 for (
auto key : newGraphValues.keys()) {
187 if (key == valuesKeyNotExistent) {
188 std::cout <<
YELLOW_START <<
"GMsf-ISAM2" <<
RED_START <<
" Values contains non-existent key: " << gtsam::Symbol(key)
189 <<
". -> Removed." <<
COLOR_END << std::endl;
190 removedAtLeastOneFactorOrKey =
true;
195 if (removedAtLeastOneFactorOrKey) {
197 <<
" Filtered out the factor or key that caused the error (i.e. containing the key "
198 << gtsam::Symbol(valuesKeyNotExistent) <<
"). Trying to optimize again." <<
COLOR_END << std::endl;
199 std::cout <<
"----------------------------------------------------------" << std::endl;
203 return update(newGraphFactorsFiltered, newGraphValues, newGraphKeysTimeStampMapFiltered);
206 <<
" Could not filter out any factors that caused the error (i.e. containing the key "
207 << gtsam::Symbol(valuesKeyNotExistent) <<
"). Aborting optimization." <<
COLOR_END << std::endl;
208 std::cout <<
"----------------------------------------------------------" << std::endl;
213 catch (
const gtsam::ValuesKeyAlreadyExists& valuesKeyAlreadyExistsException) {
214 std::cerr <<
YELLOW_START <<
"GMsf-ISAM2" <<
RED_START <<
" ValuesKeyAlreadyExists exception while optimizing graph: '"
215 << valuesKeyAlreadyExistsException.what() <<
"'" <<
COLOR_END << std::endl;
217 <<
" This happens if a factor is added to the graph that contains a state that already exists. This is usually a sign of "
218 "a bug in the code. Please check the factor graph construction."
220 throw std::runtime_error(valuesKeyAlreadyExistsException.what());
223 catch (
const std::runtime_error& runtimeError) {
224 std::cout <<
YELLOW_START <<
"GMsf-ISAM2" <<
RED_START <<
" Runtime error while optimizing graph: " << runtimeError.what()
226 throw std::runtime_error(runtimeError.what());
229 catch (
const gtsam::IndeterminateSystemException& indeterminantLinearSystemException) {
230 std::cerr <<
YELLOW_START <<
"GMsf-ISAM2" <<
RED_START <<
" IndeterminantLinearSystem exception while optimizing graph: '"
231 << indeterminantLinearSystemException.what() <<
"'" <<
COLOR_END << std::endl;
233 <<
" This happens if the linear system is indeterminant, which usually indicates that there are not enough constraints to "
234 "solve for all variables."
238 gtsam::Key key = indeterminantLinearSystemException.nearbyVariable();
239 std::cout <<
YELLOW_START <<
"GMsf-ISAM2" <<
COLOR_END <<
" The key causing the issue is: " << gtsam::Symbol(key) << std::endl;
242 const gtsam::Symbol symbol(key);
243 const char stateCategory = symbol.chr();
244 if (stateCategory ==
'b') {
245 const gtsam::Key& biasKey = key;
246 std::cout <<
YELLOW_START <<
"GMsf-ISAM2" <<
COLOR_END <<
" Latest estimated bias for key " << symbol <<
": "
249 const int symbolNumber = symbol.index();
250 gtsam::Key poseKey = gtsam::symbol_shorthand::X(symbolNumber);
251 std::cout <<
YELLOW_START <<
"GMsf-ISAM2" <<
COLOR_END <<
" Latest estimated pose for key " << gtsam::Symbol(poseKey) <<
": "
254 const auto priorBiasNoise =
255 gtsam::noiseModel::Diagonal::Sigmas((gtsam::Vector(6) <<
graphConfigPtr_->initialAccBiasStdDev_,
263 const auto priorPoseNoise =
264 gtsam::noiseModel::Diagonal::Sigmas((gtsam::Vector(6) <<
graphConfigPtr_->initialOrientationStdDev_,
272 gtsam::NonlinearFactorGraph newGraphFactorsExtended = newGraphFactors;
273 newGraphFactorsExtended.add(gtsam::PriorFactor<gtsam::imuBias::ConstantBias>(biasKey, this->
latestImuBias_, priorBiasNoise));
274 newGraphFactorsExtended.add(gtsam::PriorFactor<gtsam::Pose3>(poseKey, this->
latestPose_, priorPoseNoise));
278 return update(newGraphFactorsExtended, newGraphValues, newGraphKeysTimeStampMap, depth + 1);
281 <<
" The key causing the issue is not a bias key. Currently, only bias keys can be fixed automatically. Aborting "
286 throw std::runtime_error(indeterminantLinearSystemException.what());