Recorder.h
Go to the documentation of this file.
1 /*
2  * OpenVINS: An Open Platform for Visual-Inertial Research
3  * Copyright (C) 2018-2023 Patrick Geneva
4  * Copyright (C) 2018-2023 Guoquan Huang
5  * Copyright (C) 2018-2023 OpenVINS Contributors
6  * Copyright (C) 2018-2019 Kevin Eckenhoff
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef OV_EVAL_RECORDER_H
23 #define OV_EVAL_RECORDER_H
24 
25 #include <fstream>
26 #include <iostream>
27 #include <string>
28 
29 #include <Eigen/Eigen>
30 #include <boost/filesystem.hpp>
31 
32 #include <geometry_msgs/PoseStamped.h>
33 #include <geometry_msgs/PoseWithCovarianceStamped.h>
34 #include <geometry_msgs/TransformStamped.h>
35 #include <nav_msgs/Odometry.h>
36 #include <ros/ros.h>
37 
38 namespace ov_eval {
39 
47 class Recorder {
48 
49 public:
55  Recorder(std::string filename) {
56  // Create folder path to this location if not exists
57  boost::filesystem::path dir(filename.c_str());
58  if (boost::filesystem::create_directories(dir.parent_path())) {
59  ROS_INFO("Created folder path to output file.");
60  ROS_INFO("Path: %s", dir.parent_path().c_str());
61  }
62  // If it exists, then delete it
63  if (boost::filesystem::exists(filename)) {
64  ROS_WARN("Output file exists, deleting old file....");
65  boost::filesystem::remove(filename);
66  }
67  // Open this file we want to write to
68  outfile.open(filename.c_str());
69  if (outfile.fail()) {
70  ROS_ERROR("Unable to open output file!!");
71  ROS_ERROR("Path: %s", filename.c_str());
72  std::exit(EXIT_FAILURE);
73  }
74  outfile << "# timestamp(s) tx ty tz qx qy qz qw Pr11 Pr12 Pr13 Pr22 Pr23 Pr33 Pt11 Pt12 Pt13 Pt22 Pt23 Pt33" << std::endl;
75  // Set initial state values
76  timestamp = -1;
77  q_ItoG << 0, 0, 0, 1;
78  p_IinG = Eigen::Vector3d::Zero();
79  cov_rot = Eigen::Matrix<double, 3, 3>::Zero();
80  cov_pos = Eigen::Matrix<double, 3, 3>::Zero();
81  has_covariance = false;
82  }
83 
92  void callback_odometry(const nav_msgs::OdometryPtr &msg) {
93  timestamp = msg->header.stamp.toSec();
94  q_ItoG << msg->pose.pose.orientation.x, msg->pose.pose.orientation.y, msg->pose.pose.orientation.z, msg->pose.pose.orientation.w;
95  p_IinG << msg->pose.pose.position.x, msg->pose.pose.position.y, msg->pose.pose.position.z;
96  cov_pos << msg->pose.covariance.at(0), msg->pose.covariance.at(1), msg->pose.covariance.at(2), msg->pose.covariance.at(6),
97  msg->pose.covariance.at(7), msg->pose.covariance.at(8), msg->pose.covariance.at(12), msg->pose.covariance.at(13),
98  msg->pose.covariance.at(14);
99  cov_rot << msg->pose.covariance.at(21), msg->pose.covariance.at(22), msg->pose.covariance.at(23), msg->pose.covariance.at(27),
100  msg->pose.covariance.at(28), msg->pose.covariance.at(29), msg->pose.covariance.at(33), msg->pose.covariance.at(34),
101  msg->pose.covariance.at(35);
102  has_covariance = true;
103  write();
104  }
105 
110  void callback_pose(const geometry_msgs::PoseStampedPtr &msg) {
111  timestamp = msg->header.stamp.toSec();
112  q_ItoG << msg->pose.orientation.x, msg->pose.orientation.y, msg->pose.orientation.z, msg->pose.orientation.w;
113  p_IinG << msg->pose.position.x, msg->pose.position.y, msg->pose.position.z;
114  write();
115  }
116 
125  void callback_posecovariance(const geometry_msgs::PoseWithCovarianceStampedPtr &msg) {
126  timestamp = msg->header.stamp.toSec();
127  q_ItoG << msg->pose.pose.orientation.x, msg->pose.pose.orientation.y, msg->pose.pose.orientation.z, msg->pose.pose.orientation.w;
128  p_IinG << msg->pose.pose.position.x, msg->pose.pose.position.y, msg->pose.pose.position.z;
129  cov_pos << msg->pose.covariance.at(0), msg->pose.covariance.at(1), msg->pose.covariance.at(2), msg->pose.covariance.at(6),
130  msg->pose.covariance.at(7), msg->pose.covariance.at(8), msg->pose.covariance.at(12), msg->pose.covariance.at(13),
131  msg->pose.covariance.at(14);
132  cov_rot << msg->pose.covariance.at(21), msg->pose.covariance.at(22), msg->pose.covariance.at(23), msg->pose.covariance.at(27),
133  msg->pose.covariance.at(28), msg->pose.covariance.at(29), msg->pose.covariance.at(33), msg->pose.covariance.at(34),
134  msg->pose.covariance.at(35);
135  has_covariance = true;
136  write();
137  }
138 
143  void callback_transform(const geometry_msgs::TransformStampedPtr &msg) {
144  timestamp = msg->header.stamp.toSec();
145  q_ItoG << msg->transform.rotation.x, msg->transform.rotation.y, msg->transform.rotation.z, msg->transform.rotation.w;
146  p_IinG << msg->transform.translation.x, msg->transform.translation.y, msg->transform.translation.z;
147  write();
148  }
149 
150 protected:
155  void write() {
156 
157  // timestamp
158  outfile.precision(5);
159  outfile.setf(std::ios::fixed, std::ios::floatfield);
160  outfile << timestamp << " ";
161 
162  // pose
163  outfile.precision(6);
164  outfile << p_IinG.x() << " " << p_IinG.y() << " " << p_IinG.z() << " " << q_ItoG(0) << " " << q_ItoG(1) << " " << q_ItoG(2) << " "
165  << q_ItoG(3);
166 
167  // output the covariance only if we have it
168  if (has_covariance) {
169  outfile.precision(10);
170  outfile << " " << cov_rot(0, 0) << " " << cov_rot(0, 1) << " " << cov_rot(0, 2) << " " << cov_rot(1, 1) << " " << cov_rot(1, 2) << " "
171  << cov_rot(2, 2) << " " << cov_pos(0, 0) << " " << cov_pos(0, 1) << " " << cov_pos(0, 2) << " " << cov_pos(1, 1) << " "
172  << cov_pos(1, 2) << " " << cov_pos(2, 2) << std::endl;
173  } else {
174  outfile << std::endl;
175  }
176  }
177 
178  // Output stream file
179  std::ofstream outfile;
180 
181  // Temp storage objects for our pose and its certainty
182  bool has_covariance = false;
183  double timestamp;
184  Eigen::Vector4d q_ItoG;
185  Eigen::Vector3d p_IinG;
186  Eigen::Matrix<double, 3, 3> cov_rot;
187  Eigen::Matrix<double, 3, 3> cov_pos;
188 };
189 
190 } // namespace ov_eval
191 
192 #endif // OV_EVAL_RECORDER_H
Recorder(std::string filename)
Default constructor that will open the specified file on disk. If the output directory does not exist...
Definition: Recorder.h:55
double timestamp
Definition: Recorder.h:183
void write()
This is the main write function that will save to disk. This should be called after we have saved the...
Definition: Recorder.h:155
void callback_posecovariance(const geometry_msgs::PoseWithCovarianceStampedPtr &msg)
Callback for geometry_msgs::PoseWithCovarianceStamped message types.
Definition: Recorder.h:125
Eigen::Vector4d q_ItoG
Definition: Recorder.h:184
This class takes in published poses and writes them to file.
Definition: Recorder.h:47
#define ROS_WARN(...)
void callback_odometry(const nav_msgs::OdometryPtr &msg)
Callback for nav_msgs::Odometry message types.
Definition: Recorder.h:92
Evaluation and recording utilities.
void callback_pose(const geometry_msgs::PoseStampedPtr &msg)
Callback for geometry_msgs::PoseStamped message types.
Definition: Recorder.h:110
Eigen::Matrix< double, 3, 3 > cov_rot
Definition: Recorder.h:186
void callback_transform(const geometry_msgs::TransformStampedPtr &msg)
Callback for geometry_msgs::TransformStamped message types.
Definition: Recorder.h:143
#define ROS_INFO(...)
Eigen::Vector3d p_IinG
Definition: Recorder.h:185
Eigen::Matrix< double, 3, 3 > cov_pos
Definition: Recorder.h:187
std::ofstream outfile
Definition: Recorder.h:179
#define ROS_ERROR(...)


ov_eval
Author(s): Patrick Geneva , Kevin Eckenhoff , Guoquan Huang
autogenerated on Wed Jun 21 2023 03:05:40