My Project 1.0
Holistic Fusion: A Generic Framework for Multimodal Sensor Fusion
Loading...
Searching...
No Matches
DynamicTransformDictionary.h
Go to the documentation of this file.
1/*
2Copyright 2024 by Julian Nubert, Robotic Systems Lab, ETH Zurich.
3All rights reserved.
4This file is released under the "BSD-3-Clause License".
5Please see the LICENSE file that has been included as part of this package.
6*/
7
8#ifndef TRANSFORMS_EXPRESSION_KEYS_H
9#define TRANSFORMS_EXPRESSION_KEYS_H
10
11// Output
12#define REGULAR_COUT std::cout << YELLOW_START << "GMSF-TransformExpressionKeys" << COLOR_END
13
14// C++
15#include <mutex>
16
17// Workspace
22
23namespace holistic_fusion {
24
25// Explanation:
26// 1) global variables are constant along the entire operation, hence they are not removed and will get the same gtsam key upon return
27// 2) reference frames can change, but are modelled according to random walk, hence they are only removed once a successor is initialized
28// 3) landmarks are initialized and removed as needed, hence they are removed once they are not needed anymore
29// Frames that are not needed but also not removed are set to be "inactive"
30
31// Class Definition
32template <class GTSAM_DYNAMIC_STATE_TYPE> // e.g. gtsam::Pose3, gtsam::Point3
33class DynamicTransformDictionary : public TransformsDictionary<DynamicFactorGraphStateKey<GTSAM_DYNAMIC_STATE_TYPE>> {
34 public:
35 // Constructor
37 : TransformsDictionary<DynamicFactorGraphStateKey<GTSAM_DYNAMIC_STATE_TYPE>>(DynamicFactorGraphStateKey<GTSAM_DYNAMIC_STATE_TYPE>()) {
38 REGULAR_COUT << " Instance created." << std::endl;
39 }
40
41 // Destructor
43
44 // Cleanup
45 bool removeTransform(const std::string& frame1, const std::string& frame2,
47 // Removed main element
48 bool removedTransformFlag =
50 // If found, we also remove the key from the key-to-frame pair map
51 if (removedTransformFlag) {
52 auto keyFramePairMapIterator = transformGtsamKeyToFramePairMap_.find(returnRemovedKey.key());
53 // Still in map --> remove
54 if (keyFramePairMapIterator != transformGtsamKeyToFramePairMap_.end()) {
55 // transformGtsamKeyToFramePairMap_.erase(keyFramePairMapIterator);
56 // TODO: Remove if offline optimization is disabled, keep otherwise
57 }
58 // Not in map --> throw error
59 else {
60 REGULAR_COUT << RED_START << " Key " << gtsam::Symbol(returnRemovedKey.key()) << " not found in map." << COLOR_END << std::endl;
61 throw std::runtime_error("Key not found in map.");
62 }
63 }
64 return removedTransformFlag;
65 }
66
67 // Same but with only two arguments
68 bool removeOrDeactivateTransform(const std::string& frame1, const std::string& frame2) {
69 // Check if key is in map
70 const bool isFramePairInDictionary =
72
73 // Case: Frame pair is in dictionary
75 // Retrieve key and variable type
78 const DynamicVariableTypeEnum& variableTypeEnum = keyToRemoveOrDeactivate.getVariableTypeEnum();
79
80 // Three different cases
81 switch (variableTypeEnum) {
82 // Case 1: Global Measurement --> Never remove, only deactivate, as it might come back
84 // Currently active, so we can deactivate
85 if (keyToRemoveOrDeactivate.isVariableActive()) {
86 keyToRemoveOrDeactivate.deactivateVariable();
87 return true;
88 }
89 // Already deactivated, so we do not need to do anything
90 else {
91 return false;
92 }
93 // Case 2: Reference Frame --> Do not remove for now, as we will need it for creating the random walk
95 // Currently active, so we can deactivate
96 if (keyToRemoveOrDeactivate.isVariableActive()) {
97 keyToRemoveOrDeactivate.deactivateVariable();
98 return true;
99 }
100 // Already deactivated, so we do not need to do anything
101 else {
102 return false;
103 }
104 // Case 3: Landmark --> Remove, as the landmark is not needed anymore
106 return removeTransform(frame1, frame2, keyToRemoveOrDeactivate);
107 // Has to be one of the three cases
108 default:
109 throw std::logic_error("Variable Type not found.");
110 }
111 }
112 // Case: Frame pair is not in dictionary
113 else {
114 return false;
115 }
116 }
117
118 // Getters ------------------------------------------------------------
119 // Get transform key to frame pair map
120 bool getFramePairFromGtsamKey(std::pair<std::string, std::string>& framePairRef, const gtsam::Key& gtsamKey) const {
121 // Check if key is in map
122 auto keyFramePairMapIterator = transformGtsamKeyToFramePairMap_.find(gtsamKey);
123 if (keyFramePairMapIterator == transformGtsamKeyToFramePairMap_.end()) {
124 return false;
125 }
126 // Retrieve frame pair
127 framePairRef = keyFramePairMapIterator->second;
128 return true;
129 }
130
131 // Get transform key to keyframe position
132 bool getKeyframePositionFromGtsamKey(Eigen::Vector3d& keyframePositionRef, const gtsam::Key& gtsamKey) const {
133 // Check if key is in map
134 auto keyFramePositionMapIterator = transformGtsamKeyToKeyframePositionMap_.find(gtsamKey);
135 if (keyFramePositionMapIterator == transformGtsamKeyToKeyframePositionMap_.end()) {
136 return false;
137 }
138 // Retrieve keyframe position
139 keyframePositionRef = keyFramePositionMapIterator->second;
140 return true;
141 }
142
143 // Get transform to frame pair map
144 [[nodiscard]] const std::map<gtsam::Key, std::pair<std::string, std::string>>& getTransformGtsamKeyToFramePairMap() const {
146 }
147
148 // Returns of key
149 template <char SYMBOL_CHAR>
150 DynamicFactorGraphStateKey<GTSAM_DYNAMIC_STATE_TYPE> getTransformationKey(bool& newGraphKeyAdded, const std::string& frame1,
151 const std::string& frame2, const double timeK,
152 const gtsam::Pose3& approximateTransformationBeforeOptimization,
153 const DynamicVariableType& variableType) {
154 // Retrieve key and insert information to map
156 // Case: The dynamically allocated key is not yet in the graph
157 newGraphKeyAdded = this->addNewFramePairSafelyToDictionary<SYMBOL_CHAR>(stateKey, frame1, frame2, timeK,
158 approximateTransformationBeforeOptimization, variableType);
159 return stateKey;
160 }
161
162 // Get initial guess for a specific frame pair
163 bool getInitialGuessForFramePair(const std::string& frame1, const std::string& frame2, GTSAM_DYNAMIC_STATE_TYPE& initialGuessRef) const {
164 auto it = transformGtsamKeyToInitialGuessMap_.find(std::make_pair(frame1, frame2));
165 if (it != transformGtsamKeyToInitialGuessMap_.end()) {
166 initialGuessRef = it->second;
167 return true;
168 }
169 return false;
170 }
171
172 // Safe addition of new frame pair to dictionary --> checks whether already present
173 template <char SYMBOL_CHAR>
175 const std::string& frame2, const double timeK,
176 const gtsam::Pose3& approximateTransformationBeforeOptimization,
177 const DynamicVariableType& variableType) {
178 // Check and modify content --> acquire lock
179 std::lock_guard<std::mutex> lock(internalDictionaryModifierMutex_);
180
181 // Logic
182 // CASE 1: Frame pair is already in dictionary, hence keyframe is not new (measurement either active or not)
186 // Update Timestamp and approximate transformation if newer
187 if (timeK > factorGraphStateKey.getTime()) {
188 // std::cout << " Updating timestamp of key " << gtsam::Symbol(factorGraphStateKey.key()) << " from " <<
189 // std::setprecision(14)
190 // << factorGraphStateKey.getTime() << " to " << timeK << "." << std::endl;
191 factorGraphStateKey.setTimeStamp(timeK);
192 factorGraphStateKey.setApproximateTransformationBeforeOptimization(approximateTransformationBeforeOptimization);
193 }
194 returnStateKey = factorGraphStateKey;
195 return false;
196 }
197 // CASE 2: Frame pair is not in dictionary --> Newly added
198 else {
199 returnStateKey =
200 addNewFactorGraphStateKey<SYMBOL_CHAR>(frame1, frame2, timeK, approximateTransformationBeforeOptimization, variableType);
201 return true;
202 }
203 }
204
205 // Set initial guess for a specific frame pair
206 void setInitialGuessForFramePair(const std::string& frame1, const std::string& frame2, const GTSAM_DYNAMIC_STATE_TYPE& initialGuess) {
207 transformGtsamKeyToInitialGuessMap_[std::make_pair(frame1, frame2)] = initialGuess;
208 }
209
210 // Remove initial guess for a specific frame pair
211 void removeInitialGuessForFramePair(const std::string& frame1, const std::string& frame2) {
212 std::cout << "Removing initial guess for frame pair: " << frame1 << ", " << frame2 << std::endl;
213 transformGtsamKeyToInitialGuessMap_.erase(std::make_pair(frame1, frame2));
214 }
215
216 // Functionality ------------------------------------------------------------
217 template <char SYMBOL_CHAR>
219 const std::string& frame1, const std::string& frame2, const double timeK,
220 const gtsam::Pose3& approximateTransformationBeforeOptimization, const DynamicVariableType& variableType) {
221 // Compile Time Checks and Variables
223 constexpr int symbolIndex = getSymbolIndex<SYMBOL_CHAR>();
224 static_assert(symbolIndex >= 0, "Symbol not found in admissible symbols.");
225
226 // Create New Key
227 gtsam::Key gtsamKey = gtsam::Symbol(SYMBOL_CHAR, numStoredTransformsPerSymbol_[symbolIndex]);
228
229 // Print out for calibrations and reference frames
231 REGULAR_COUT << GREEN_START << " New key " << gtsam::Symbol(gtsamKey) << " created for frame pair " << frame1 << " and " << frame2
232 << "." << COLOR_END << std::endl;
233 }
234
235 // Add to main dictionary
236 DynamicFactorGraphStateKey factorGraphStateKey(gtsamKey, timeK, 0, approximateTransformationBeforeOptimization, variableType, frame1,
237 frame2);
239
240 // Increase the counter of specific symbol
241 ++numStoredTransformsPerSymbol_[symbolIndex];
242
243 // Add to key-to-frame pair map
244 // TODO: Check if necessary for non reference frames
245 transformGtsamKeyToFramePairMap_[gtsamKey] = std::make_pair(frame1, frame2);
246 // Add to key-to-keyframe position map
248
249 // Return
250 return factorGraphStateKey;
251 }
252
253 std::mutex& mutex() { return externalModifierMutex_; }
254
255 private:
256 // Mapping in other direction --> from key to frame pair
257 std::map<gtsam::Key, std::pair<std::string, std::string>> transformGtsamKeyToFramePairMap_;
258 // Container for storing the keyframe position for each key (for later use)
259 std::map<gtsam::Key, Eigen::Vector3d> transformGtsamKeyToKeyframePositionMap_;
260 // Container to store potential initial guesses
261 std::map<std::pair<std::string, std::string>, GTSAM_DYNAMIC_STATE_TYPE> transformGtsamKeyToInitialGuessMap_;
262
263 // Mutex
266
267 // Num Stored Transforms Per Letter --> compile time initialization, set all to zero
269 makeValuedArray<unsigned long, sizeof(ADMISSIBLE_DYNAMIC_SYMBOL_CHARS)>(0);
270};
271
272} // namespace holistic_fusion
273
274#endif // TRANSFORMS_EXPRESSION_KEYS_H
#define REGULAR_COUT
#define COLOR_END
#define GREEN_START
#define RED_START
void setApproximateTransformationBeforeOptimization(const gtsam::Pose3 &approximateTransformationBeforeOptimization)
const DynamicVariableTypeEnum & getVariableTypeEnum() const
std::array< unsigned long, sizeof(ADMISSIBLE_DYNAMIC_SYMBOL_CHARS)> numStoredTransformsPerSymbol_
bool getKeyframePositionFromGtsamKey(Eigen::Vector3d &keyframePositionRef, const gtsam::Key &gtsamKey) const
std::map< gtsam::Key, std::pair< std::string, std::string > > transformGtsamKeyToFramePairMap_
std::map< std::pair< std::string, std::string >, GTSAM_DYNAMIC_STATE_TYPE > transformGtsamKeyToInitialGuessMap_
const std::map< gtsam::Key, std::pair< std::string, std::string > > & getTransformGtsamKeyToFramePairMap() const
void removeInitialGuessForFramePair(const std::string &frame1, const std::string &frame2)
bool addNewFramePairSafelyToDictionary(DynamicFactorGraphStateKey< GTSAM_DYNAMIC_STATE_TYPE > &returnStateKey, const std::string &frame1, const std::string &frame2, const double timeK, const gtsam::Pose3 &approximateTransformationBeforeOptimization, const DynamicVariableType &variableType)
DynamicFactorGraphStateKey< GTSAM_DYNAMIC_STATE_TYPE > addNewFactorGraphStateKey(const std::string &frame1, const std::string &frame2, const double timeK, const gtsam::Pose3 &approximateTransformationBeforeOptimization, const DynamicVariableType &variableType)
bool removeTransform(const std::string &frame1, const std::string &frame2, DynamicFactorGraphStateKey< GTSAM_DYNAMIC_STATE_TYPE > &returnRemovedKey) override
bool getFramePairFromGtsamKey(std::pair< std::string, std::string > &framePairRef, const gtsam::Key &gtsamKey) const
void setInitialGuessForFramePair(const std::string &frame1, const std::string &frame2, const GTSAM_DYNAMIC_STATE_TYPE &initialGuess)
std::map< gtsam::Key, Eigen::Vector3d > transformGtsamKeyToKeyframePositionMap_
DynamicFactorGraphStateKey< GTSAM_DYNAMIC_STATE_TYPE > getTransformationKey(bool &newGraphKeyAdded, const std::string &frame1, const std::string &frame2, const double timeK, const gtsam::Pose3 &approximateTransformationBeforeOptimization, const DynamicVariableType &variableType)
bool removeOrDeactivateTransform(const std::string &frame1, const std::string &frame2)
bool getInitialGuessForFramePair(const std::string &frame1, const std::string &frame2, GTSAM_DYNAMIC_STATE_TYPE &initialGuessRef) const
DynamicFactorGraphStateKey< GTSAM_DYNAMIC_STATE_TYPE > & lv_T_frame1_frame2(const std::string &frame1, const std::string &frame2)
void set_T_frame1_frame2(const std::string &frame1, const std::string &frame2, const DynamicFactorGraphStateKey< GTSAM_DYNAMIC_STATE_TYPE > T_frame1_frame2)
TransformsDictionary(DynamicFactorGraphStateKey< GTSAM_DYNAMIC_STATE_TYPE > identityObject)
constexpr int getSymbolIndex()
constexpr auto makeValuedArray(T value) -> std::array< T, N >
constexpr char ADMISSIBLE_DYNAMIC_SYMBOL_CHARS[4]
constexpr void checkSymbol()
const Eigen::Vector3d & getReferenceFrameKeyframePosition() const
const DynamicVariableTypeEnum & getVariableTypeEnum() const