109int main(
int argc,
char **argv) {
110 boost::program_options::options_description boost_desc(
"Allowed options");
111 boost_desc.add_options()(
"help",
"produce help message")(
112 "in_folder", boost::program_options::value<std::string>(),
113 "provide the output folder")(
"loc_file_a",
114 boost::program_options::value<std::string>(),
115 "provide gnss localization file.")(
116 "loc_file_b", boost::program_options::value<std::string>(),
117 "provide lidar localization file.")(
118 "compare_file", boost::program_options::value<std::string>(),
119 "provide compare file.")(
120 "imu_to_ant_offset_file",
121 boost::program_options::value<std::string>()->default_value(
""),
122 "provide imu to ant offset file.");
124 boost::program_options::variables_map boost_args;
125 boost::program_options::store(
126 boost::program_options::parse_command_line(argc, argv, boost_desc),
128 boost::program_options::notify(boost_args);
130 if (boost_args.count(
"help") || !boost_args.count(
"in_folder")) {
131 AERROR << boost_desc << std::endl;
135 const std::string in_folder = boost_args[
"in_folder"].as<std::string>();
137 const std::string loc_file_a =
138 in_folder +
"/" + boost_args[
"loc_file_a"].as<std::string>();
139 const std::string loc_file_b =
140 in_folder +
"/" + boost_args[
"loc_file_b"].as<std::string>();
141 const std::string compare_file =
142 in_folder +
"/" + boost_args[
"compare_file"].as<std::string>();
143 const std::string imu_to_ant_offset_file =
144 boost_args[
"imu_to_ant_offset_file"].as<std::string>();
146 Eigen::Vector3d imu_ant_offset = Eigen::Vector3d::Zero();
147 if (imu_to_ant_offset_file !=
"") {
148 if (!LoadGnssAntennaExtrinsic(imu_to_ant_offset_file, &imu_ant_offset)) {
153 EigenAffine3dVec poses_a;
154 EigenVector3dVec stds_a;
155 std::vector<double> timestamps_a;
157 &stds_a, ×tamps_a);
158 if (poses_a.empty()) {
162 EigenAffine3dVec poses_b;
163 EigenVector3dVec stds_b;
164 std::vector<double> timestamps_b;
166 &stds_b, ×tamps_b);
167 if (poses_b.empty()) {
171 std::map<unsigned int, Eigen::Affine3d> out_poses_a;
172 std::map<unsigned int, Eigen::Vector3d> out_stds_a;
173 std::map<unsigned int, Eigen::Affine3d> out_poses_b;
174 std::map<unsigned int, Eigen::Vector3d> out_stds_b;
176 PoseAndStdInterpolationByTime(poses_b, stds_b, timestamps_b, timestamps_a,
177 &out_poses_b, &out_stds_b);
179 PoseAndStdInterpolationByTime(poses_a, stds_a, timestamps_a, timestamps_a,
180 &out_poses_a, &out_stds_a);
182 if (out_poses_a.empty() || out_poses_b.empty()) {
186 std::vector<unsigned int> vec_idx;
187 std::vector<double> vec_timestamp;
188 std::vector<double> vec_x_diff;
189 std::vector<double> vec_y_diff;
190 std::vector<double> vec_z_diff;
191 std::vector<double> vec_roll_diff;
192 std::vector<double> vec_pitch_diff;
193 std::vector<double> vec_yaw_diff;
195 for (
unsigned int idx = 0; idx < timestamps_a.size(); idx++) {
196 auto pose_a_found_iter = out_poses_a.find(idx);
197 if (pose_a_found_iter != out_poses_a.end()) {
198 AINFO <<
"Find pose a.";
199 const Eigen::Affine3d &pose_a = pose_a_found_iter->second;
201 Eigen::Quaterniond quatd_a(pose_a.linear());
202 Eigen::Translation3d transd_a(pose_a.translation());
204 quatd_a.w(), quatd_a.x(), quatd_a.y(), quatd_a.z());
205 double roll_a = euler_a.
roll();
206 double pitch_a = euler_a.
pitch();
207 double yaw_a = euler_a.
yaw();
209 auto pose_b_found_iter = out_poses_b.find(idx);
210 if (pose_b_found_iter != out_poses_b.end()) {
211 AINFO <<
"Find pose b.";
212 const Eigen::Affine3d &pose_b = pose_b_found_iter->second;
213 Eigen::Quaterniond quatd_b(pose_b.linear());
214 Eigen::Translation3d transd_b(pose_b.translation());
216 quatd_b.w(), quatd_b.x(), quatd_b.y(), quatd_b.z());
217 double roll_b = euler_b.
roll();
218 double pitch_b = euler_b.
pitch();
219 double yaw_b = euler_b.
yaw();
221 Eigen::Vector3d offset = quatd_b * imu_ant_offset;
222 transd_a.x() = transd_a.x() - offset[0];
223 transd_a.y() = transd_a.y() - offset[1];
224 transd_a.z() = transd_a.z() - offset[2];
226 double x_diff = fabs(transd_a.x() - transd_b.x());
227 double y_diff = fabs(transd_a.y() - transd_b.y());
228 double z_diff = fabs(transd_a.z() - transd_b.z());
229 double roll_diff = fabs(roll_a - roll_b) * 180.0 / M_PI;
230 double pitch_diff = fabs(pitch_a - pitch_b) * 180.0 / M_PI;
231 double yaw_diff = fabs(yaw_a - yaw_b);
232 yaw_diff = std::min(yaw_diff, 2.0 * M_PI - yaw_diff) * 180.0 / M_PI;
234 vec_idx.push_back(idx);
235 vec_timestamp.push_back(timestamps_a[idx]);
236 vec_x_diff.push_back(x_diff);
237 vec_y_diff.push_back(y_diff);
238 vec_z_diff.push_back(z_diff);
239 vec_roll_diff.push_back(roll_diff);
240 vec_pitch_diff.push_back(pitch_diff);
241 vec_yaw_diff.push_back(yaw_diff);
246 if (vec_idx.empty()) {
250 std::ofstream file(compare_file.c_str());
251 for (
unsigned int i = 0; i < vec_idx.size(); ++i) {
252 file << vec_idx[i] <<
" " << std::setprecision(13) << vec_timestamp[i]
253 <<
" " << vec_x_diff[i] <<
" " << vec_y_diff[i] <<
" " << vec_z_diff[i]
254 <<
" " << vec_roll_diff[i] <<
" " << vec_pitch_diff[i] <<
" "
255 << vec_yaw_diff[i] << std::endl;