Skip to content

Commit 99bba36

Browse files
committed
logging of real time estimates of reference frame transformations
1 parent a32581c commit 99bba36

File tree

12 files changed

+120
-31
lines changed

12 files changed

+120
-31
lines changed

Diff for: examples/anymal_estimator_graph/config/core/core_graph_config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
common_params:
33
verbosity: 0 #Debug Output, 0: only important events, 1: functioning and state machine, 2: optimization effort, 3: added factors
44
odomNotJumpAtStart: true #Whether the World->Odom transform should be updated in the beginning (odom start at identity)
5-
logRealTimeStateToMemory: true # Whether the real-time state should be logged to memory (for logging purposes)
5+
logRealTimeStateToMemory: true # Whether the real-time state should be logged to memory (for logging purposes)

Diff for: examples/anymal_estimator_graph/config/core/core_graph_params_no_gnss.yaml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Sensor Params
22
sensor_params:
3-
imuRate: 400 #Rate of IMU input (Hz)
4-
createStateEveryNthImuMeasurement: 10 # Create a new state every n-th IMU measurement
5-
useImuSignalLowPassFilter: false #If true, a low pass filter is applied to the IMU measurements
6-
imuLowPassFilterCutoffFreq: 30.0 #Cutoff frequency of the low pass filter
3+
imuRate: 400 # Rate of IMU input (Hz)
4+
createStateEveryNthImuMeasurement: 10 # Create a new state every n-th IMU measurement
5+
useImuSignalLowPassFilter: false # If true, a low pass filter is applied to the IMU measurements
6+
imuLowPassFilterCutoffFreq: 30.0 # Cutoff frequency of the low pass filter
77
imuBufferLength: 800
88
imuTimeOffset: 0.0 # Offset between IMU and LiDAR Measurements: can be determined with rqt_multiplot
99

Diff for: examples/anymal_estimator_graph/include/anymal_estimator_graph/AnymalEstimator.h

-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ class AnymalEstimator : public graph_msf::GraphMsfRos {
109109
Eigen::Matrix<double, 6, 1> lioSe3AlignmentRandomWalk_ = 0.0 * Eigen::Matrix<double, 6, 1>::Ones();
110110

111111
// Noise
112-
double gnssPositionUnaryNoise_ = 1.0; // in [m]
113112
Eigen::Matrix<double, 6, 1> lioPoseUnaryNoise_ = 1.0 * Eigen::Matrix<double, 6, 1>::Ones();
114113
Eigen::Matrix<double, 6, 1> lioPoseBetweenNoise_ = 1.0 * Eigen::Matrix<double, 6, 1>::Ones();
115114
Eigen::Matrix<double, 6, 1> legPoseBetweenNoise_ = 1.0 * Eigen::Matrix<double, 6, 1>::Ones();

Diff for: examples/anymal_estimator_graph/launch/anymal_estimator_graph_replay.launch

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212

1313
<!-- Input Topics -->
1414
<arg name="imu_topic_name" default="/sensors/imu"/>
15-
<!-- <arg name="lidar_odometry_topic_name"-->
16-
<!-- default="/open3d_slam/scan2map_odometry"/> &lt;!&ndash;/compslam_lio/odom_aft_mapped_to_init_CORRECTED &ndash;&gt;-->
1715
<arg name="lidar_odometry_topic_name"
18-
default="/open3d_slam/optimized_poses_as_odometry"/>
16+
default="/open3d_slam/scan2map_odometry"/> <!--/compslam_lio/odom_aft_mapped_to_init_CORRECTED -->
17+
<!-- <arg name="lidar_odometry_topic_name"-->
18+
<!-- default="/open3d_slam/optimized_poses_as_odometry"/>-->
1919

2020

2121
<!-- Load dumped parameters, mainly for description -->

Diff for: examples/anymal_estimator_graph/src/lib/readParams.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ void AnymalEstimator::readParams(const ros::NodeHandle& privateNode) {
5050
lioSe3AlignmentRandomWalk[3], lioSe3AlignmentRandomWalk[4], lioSe3AlignmentRandomWalk[5];
5151

5252
// Noise Parameters ---------------------------------------------------
53-
/// Gnss
54-
gnssPositionUnaryNoise_ = graph_msf::tryGetParam<double>("noise_params/gnssPositionUnaryNoiseDensity", privateNode);
55-
5653
/// LiDAR Odometry
5754
const auto poseUnaryNoise =
5855
graph_msf::tryGetParam<std::vector<double>>("noise_params/lioPoseUnaryNoiseDensity", privateNode); // roll,pitch,yaw,x,y,z

Diff for: graph_msf/include/graph_msf/core/GraphManager.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,11 @@ class GraphManager {
9292
// Slow Graph Update (if desired)
9393
bool optimizeSlowBatchSmoother(int maxIterations, const std::string& savePath, const bool saveCovarianceFlag);
9494

95-
// Logging of real-time states
96-
bool logRealTimeStates(const std::string& savePath, const std::string& timeString);
95+
// Logging of real-time navigation states
96+
bool logRealTimeNavStates(const std::string& savePath, const std::string& timeString);
97+
98+
// Logging of real-time reference frame states
99+
bool logRealTimeReferenceFrameStates(const std::string& savePath, const std::string& timeString);
97100

98101
// Save Variables to File
99102
void saveOptimizedValuesToFile(const gtsam::Values& optimizedValues, const std::map<gtsam::Key, double>& keyTimestampMap,
@@ -211,6 +214,9 @@ class GraphManager {
211214
// Real-time Pose Container
212215
std::map<double, gtsam::Pose3> realTimeWorldPoseContainer_ = {};
213216
std::map<double, gtsam::Pose3> realTimeOdomPoseContainer_ = {};
217+
// Real-time Reference Frame Transformation Container
218+
std::map<double, TransformsDictionary<Eigen::Isometry3d>> realTimeReferenceFrameContainer_ = {};
219+
std::set<std::pair<std::string, std::string>> realTimeReferenceFrameNamePairs_ = {};
214220

215221
// Member variables
216222
/// Mutex

Diff for: graph_msf/include/graph_msf/core/TransformsDictionary.h

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ class TransformsDictionary {
2323
// Constructor
2424
TransformsDictionary(TRANSFORM_TYPE identityObject) : identity_(identityObject) {}
2525

26+
// Copy Constructor
27+
TransformsDictionary(const TransformsDictionary& other) {
28+
T_frame1_frame2_map_ = other.T_frame1_frame2_map_;
29+
identity_ = other.identity_;
30+
numStoredTransforms_ = other.numStoredTransforms_;
31+
}
32+
2633
// Getters ------------------------------------------------------------
2734
// Check for specific transformation pair
2835
bool isFramePairInDictionary(const std::string& frame1, const std::string& frame2) {

Diff for: graph_msf/include/graph_msf/interface/GraphMsf.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class GraphMsf {
4848
bool optimizeSlowBatchSmoother(int maxIterations, const std::string& savePath, const bool saveCovarianceFlag);
4949

5050
// Logging of the real-time states
51-
bool logRealTimeStates(const std::string& savePath);
51+
bool logRealTimeNavStates(const std::string& savePath);
5252

5353
// Getter functions
5454
bool areYawAndPositionInited() const;

Diff for: graph_msf/src/lib/GraphManager.cpp

+88-8
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ void GraphManager::updateGraph() {
533533
gtsam::Matrix33 resultVelocityCovariance =
534534
rtOptimizerPtr_->calculateMarginalCovarianceMatrixAtKey(gtsam::symbol_shorthand::V(currentPropagatedKey));
535535

536-
// D. FixedFrame Transformations ------------------------------
536+
// D. Reference Frame Transformations ------------------------------
537537
// Containers
538538
TransformsDictionary<Eigen::Isometry3d> resultReferenceFrameTransformations(Eigen::Isometry3d::Identity());
539539
TransformsDictionary<Eigen::Matrix<double, 6, 6>> resultReferenceFrameTransformationsCovariance(gtsam::Z_6x6);
@@ -547,6 +547,9 @@ void GraphManager::updateGraph() {
547547

548548
// Iterate through all dynamically allocated variables (holistic, calibration, landmarks) --------------------------------
549549
for (auto& framePairKeyMapIterator : gtsamDynamicExpressionKeys_.get<gtsam::Pose3>().getTransformsMap()) {
550+
// Frame Pair
551+
const std::pair<std::string, std::string>& framePair = framePairKeyMapIterator.first; // alias
552+
550553
// Get Variable Key
551554
const gtsam::Key& gtsamKey = framePairKeyMapIterator.second.key(); // alias
552555

@@ -606,17 +609,30 @@ void GraphManager::updateGraph() {
606609
T_frame2_frame1_corrected.translation() + framePairKeyMapIterator.second.getReferenceFrameKeyframePosition());
607610
gtsam::Pose3 T_frame1_frame2_corrected = T_frame2_frame1_corrected.inverse();
608611
// Write to container
612+
// 1: For Landmark States
609613
if (isLandmarkState) {
614+
// Write to landmark container
610615
resultLandmarkTransformations.set_T_frame1_frame2(framePairKeyMapIterator.first.first, framePairKeyMapIterator.first.second,
611616
Eigen::Isometry3d(T_frame1_frame2_corrected.matrix()));
612617
resultLandmarkTransformationsCovariance.set_T_frame1_frame2(framePairKeyMapIterator.first.first,
613618
framePairKeyMapIterator.first.second, T_frame1_frame2_covariance);
614-
} else {
619+
}
620+
// 2: For Reference Frame States
621+
else {
622+
// Write to reference frame container
615623
resultReferenceFrameTransformations.set_T_frame1_frame2(framePairKeyMapIterator.first.first,
616624
framePairKeyMapIterator.first.second,
617625
Eigen::Isometry3d(T_frame1_frame2_corrected.matrix()));
618626
resultReferenceFrameTransformationsCovariance.set_T_frame1_frame2(
619627
framePairKeyMapIterator.first.first, framePairKeyMapIterator.first.second, T_frame1_frame2_covariance);
628+
// Potentially fill in existing pairs for logging
629+
if (graphConfigPtr_->logRealTimeStateToMemoryFlag_) {
630+
if (realTimeReferenceFrameNamePairs_.find(framePair) == realTimeReferenceFrameNamePairs_.end()) {
631+
realTimeReferenceFrameNamePairs_.insert(framePair);
632+
REGULAR_COUT << " Added frame pair: " << framePair.first << " to " << framePair.second << " to real-time logging."
633+
<< std::endl;
634+
}
635+
}
620636
}
621637

622638
// Mark that this key has at least been optimized once
@@ -697,8 +713,8 @@ void GraphManager::updateGraph() {
697713
}
698714
}
699715
} // catch statement
700-
} // end: if active statement
701-
} // for loop over all transforms
716+
} // end: if active statement
717+
} // for loop over all transforms
702718
}
703719

704720
// Mutex block 2 ------------------
@@ -740,6 +756,11 @@ void GraphManager::updateGraph() {
740756
// Update the time of the last optimized state
741757
lastOptimizedStateTime_ = currentPropagatedTime;
742758
} // end of locking
759+
760+
// Potentially log real-time state to container
761+
if (graphConfigPtr_->logRealTimeStateToMemoryFlag_) {
762+
realTimeReferenceFrameContainer_.emplace(currentPropagatedTime, resultReferenceFrameTransformations);
763+
}
743764
}
744765

745766
bool GraphManager::optimizeSlowBatchSmoother(int maxIterations, const std::string& savePath, const bool saveCovarianceFlag) {
@@ -768,16 +789,16 @@ bool GraphManager::optimizeSlowBatchSmoother(int maxIterations, const std::strin
768789
}
769790
}
770791

771-
// Logging of the real-time states
772-
bool GraphManager::logRealTimeStates(const std::string& savePath, const std::string& timeString) {
792+
// Logging of the real-time navigation states
793+
bool GraphManager::logRealTimeNavStates(const std::string& savePath, const std::string& timeString) {
773794
// Note enabled
774795
if (!graphConfigPtr_->logRealTimeStateToMemoryFlag_) {
775796
REGULAR_COUT << RED_START << " Logging of real-time states is disabled. " << COLOR_END << std::endl;
776797
return false;
777798
}
778799
// Enabled
779800
else {
780-
// Main container: map, although only one element
801+
// Main container: map
781802
std::map<std::string, std::ofstream> fileStreams;
782803

783804
// Create directory if it does not exist
@@ -814,6 +835,62 @@ bool GraphManager::logRealTimeStates(const std::string& savePath, const std::str
814835
}
815836
}
816837

838+
// Logging of real-time reference frame states
839+
bool GraphManager::logRealTimeReferenceFrameStates(const std::string& savePath, const std::string& timeString) {
840+
// Note enabled
841+
if (!graphConfigPtr_->logRealTimeStateToMemoryFlag_) {
842+
REGULAR_COUT << RED_START << " Logging of real-time states is disabled. " << COLOR_END << std::endl;
843+
return false;
844+
}
845+
// Enabled
846+
else {
847+
// Main container: map
848+
std::map<std::string, std::ofstream> fileStreams;
849+
850+
// Create directory if it does not exist
851+
if (!std::filesystem::exists(savePath + timeString)) {
852+
std::filesystem::create_directories(savePath + timeString);
853+
}
854+
855+
// State Category String
856+
std::string stateCategoryString = "rt_R_6D_transform";
857+
858+
// Go through all reference frame states that have been logged
859+
for (const std::pair<std::string, std::string>& framePair : realTimeReferenceFrameNamePairs_) {
860+
// Frame Information
861+
std::string frameInformation = "_" + framePair.first + "_to_" + framePair.second;
862+
// Create File Streams
863+
// CSV
864+
FileLogger::createPose3CsvFileStream(fileStreams, savePath, stateCategoryString + frameInformation, timeString, false);
865+
// TUM
866+
FileLogger::createPose3TumFileStream(fileStreams, savePath, stateCategoryString + frameInformation + "_tum", timeString);
867+
}
868+
869+
// Iterate through all timestamps and corresponding transform maps
870+
for (const auto& mapPair : realTimeReferenceFrameContainer_) {
871+
const double& timeStamp = mapPair.first; // alias
872+
const TransformsDictionary<Eigen::Isometry3d>& referenceFrameTransforms = mapPair.second;
873+
// Iterate through all transforms for this time stamp
874+
for (const auto& framePairTransform : referenceFrameTransforms.getTransformsMap()) {
875+
// Frame Pair
876+
const std::pair<std::string, std::string>& framePair = framePairTransform.first; // alias
877+
// Transform
878+
const Eigen::Isometry3d& transform = framePairTransform.second; // alias
879+
// Frame Information
880+
std::string frameInformation = "_" + framePair.first + "_to_" + framePair.second;
881+
// Write to files
882+
// CSV
883+
FileLogger::writePose3ToCsvFile(fileStreams, gtsam::Pose3(transform.matrix()), stateCategoryString + frameInformation, timeStamp,
884+
false);
885+
// TUM
886+
FileLogger::writePose3ToTumFile(fileStreams, gtsam::Pose3(transform.matrix()), stateCategoryString + frameInformation + "_tum",
887+
timeStamp);
888+
}
889+
}
890+
return true;
891+
}
892+
}
893+
817894
// Save optimized values to file
818895
void GraphManager::saveOptimizedValuesToFile(const gtsam::Values& optimizedValues, const std::map<gtsam::Key, double>& keyTimestampMap,
819896
const std::string& savePath, const bool saveCovarianceFlag) {
@@ -846,7 +923,10 @@ void GraphManager::saveOptimizedValuesToFile(const gtsam::Values& optimizedValue
846923

847924
// Save real-time states
848925
if (graphConfigPtr_->logRealTimeStateToMemoryFlag_) {
849-
std::ignore = logRealTimeStates(savePath, timeString);
926+
// Real-time states
927+
std::ignore = logRealTimeNavStates(savePath, timeString);
928+
// Real-time Reference Frame States
929+
std::ignore = logRealTimeReferenceFrameStates(savePath, timeString);
850930
}
851931

852932
// Save optimized states

Diff for: graph_msf/src/lib/GraphMsf.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ bool GraphMsf::optimizeSlowBatchSmoother(int maxIterations, const std::string& s
5454
return graphMgrPtr_->optimizeSlowBatchSmoother(maxIterations, savePath, saveCovarianceFlag);
5555
}
5656

57-
bool GraphMsf::logRealTimeStates(const std::string& savePath) {
57+
bool GraphMsf::logRealTimeNavStates(const std::string& savePath) {
5858
// String of time without line breaks: year_month_day_hour_min_sec
5959
std::ostringstream oss;
6060
std::time_t now_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
@@ -63,7 +63,7 @@ bool GraphMsf::logRealTimeStates(const std::string& savePath) {
6363
// Convert stream to string
6464
std::string timeString = oss.str();
6565
// Return
66-
return graphMgrPtr_->logRealTimeStates(savePath, timeString);
66+
return graphMgrPtr_->logRealTimeNavStates(savePath, timeString);
6767
}
6868

6969
// Getter functions -----------------------

Diff for: ros/graph_msf_ros/include/graph_msf_ros/GraphMsfRos.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class GraphMsfRos : public GraphMsfClassic, public GraphMsfHolistic {
8888
// Services
8989
virtual bool srvOfflineSmootherOptimizeCallback(graph_msf_ros_msgs::OfflineOptimizationTrigger::Request& req,
9090
graph_msf_ros_msgs::OfflineOptimizationTrigger::Response& res);
91-
bool srvLogRealTimeStatesCallback(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res);
91+
bool srvLogRealTimeNavStatesCallback(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res);
9292

9393
// Publishing -----------------------------------
9494
// Higher Level Functions
@@ -191,7 +191,7 @@ class GraphMsfRos : public GraphMsfClassic, public GraphMsfHolistic {
191191
// Trigger offline smoother optimization
192192
ros::ServiceServer srvSmootherOptimize_;
193193
// Log Real-Time States
194-
ros::ServiceServer srvLogRealTimeStates_;
194+
ros::ServiceServer srvLogRealTimeNavStates_;
195195

196196
// Last Optimized State Timestamp
197197
double lastOptimizedStateTimestamp_ = 0.0;

Diff for: ros/graph_msf_ros/src/lib/GraphMsfRos.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ void GraphMsfRos::initializeServices(ros::NodeHandle& privateNode) {
117117
srvSmootherOptimize_ =
118118
privateNode.advertiseService("/graph_msf/trigger_offline_optimization", &GraphMsfRos::srvOfflineSmootherOptimizeCallback, this);
119119
// Real-Time State Logging
120-
srvLogRealTimeStates_ = privateNode.advertiseService("/graph_msf/log_real_time_states", &GraphMsfRos::srvLogRealTimeStatesCallback, this);
120+
srvLogRealTimeNavStates_ = privateNode.advertiseService("/graph_msf/log_real_time_nav_states", &GraphMsfRos::srvLogRealTimeNavStatesCallback, this);
121121
}
122122

123123
bool GraphMsfRos::srvOfflineSmootherOptimizeCallback(graph_msf_ros_msgs::OfflineOptimizationTrigger::Request& req,
@@ -137,9 +137,9 @@ bool GraphMsfRos::srvOfflineSmootherOptimizeCallback(graph_msf_ros_msgs::Offline
137137
return true;
138138
}
139139

140-
bool GraphMsfRos::srvLogRealTimeStatesCallback(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res) {
140+
bool GraphMsfRos::srvLogRealTimeNavStatesCallback(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res) {
141141
// Log real-time states
142-
if (GraphMsf::logRealTimeStates(optimizationResultLoggingPath)) {
142+
if (GraphMsf::logRealTimeNavStates(optimizationResultLoggingPath)) {
143143
res.success = true;
144144
res.message = "Logging real-time states.";
145145
} else {
@@ -269,7 +269,7 @@ void GraphMsfRos::createVelocityMarker(const std::string& referenceFrameName, co
269269
startPoint = geometry_msgs::Point();
270270
startPoint.x = 0.0; // origin
271271
startPoint.y = 0.0; // origin
272-
startPoint.z = 1.0; // 1 meter above origin
272+
startPoint.z = 0.0; // origin
273273
endPoint = geometry_msgs::Point();
274274
endPoint.x = startPoint.x + velocity(0);
275275
endPoint.y = startPoint.y + velocity(1);

0 commit comments

Comments
 (0)