Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <cmath>
00018 #include <fstream>
00019 #include <string>
00020
00021 #include "cartographer/common/port.h"
00022 #include "cartographer/ground_truth/autogenerate_ground_truth.h"
00023 #include "cartographer/ground_truth/proto/relations.pb.h"
00024 #include "cartographer/io/proto_stream.h"
00025 #include "cartographer/io/proto_stream_deserializer.h"
00026 #include "cartographer/mapping/proto/pose_graph.pb.h"
00027 #include "cartographer/transform/transform.h"
00028 #include "gflags/gflags.h"
00029 #include "glog/logging.h"
00030
00031 DEFINE_string(pose_graph_filename, "",
00032 "Proto stream file containing the pose graph used to generate "
00033 "ground truth data.");
00034 DEFINE_string(output_filename, "", "File to write the ground truth proto to.");
00035 DEFINE_double(min_covered_distance, 100.,
00036 "Minimum covered distance in meters before a loop closure is "
00037 "considered a candidate for autogenerated ground truth.");
00038 DEFINE_double(outlier_threshold_meters, 0.15,
00039 "Distance in meters beyond which constraints are considered "
00040 "outliers.");
00041 DEFINE_double(outlier_threshold_radians, 0.02,
00042 "Distance in radians beyond which constraints are considered "
00043 "outliers.");
00044
00045 namespace cartographer {
00046 namespace ground_truth {
00047 namespace {
00048
00049 void Run(const std::string& pose_graph_filename,
00050 const std::string& output_filename, const double min_covered_distance,
00051 const double outlier_threshold_meters,
00052 const double outlier_threshold_radians) {
00053 LOG(INFO) << "Reading pose graph from '" << pose_graph_filename << "'...";
00054 mapping::proto::PoseGraph pose_graph =
00055 io::DeserializePoseGraphFromFile(pose_graph_filename);
00056
00057 LOG(INFO) << "Autogenerating ground truth relations...";
00058 const proto::GroundTruth ground_truth =
00059 GenerateGroundTruth(pose_graph, min_covered_distance,
00060 outlier_threshold_meters, outlier_threshold_radians);
00061 LOG(INFO) << "Writing " << ground_truth.relation_size() << " relations to '"
00062 << output_filename << "'.";
00063 {
00064 std::ofstream output_stream(output_filename,
00065 std::ios_base::out | std::ios_base::binary);
00066 CHECK(ground_truth.SerializeToOstream(&output_stream))
00067 << "Could not serialize ground truth data.";
00068 output_stream.close();
00069 CHECK(output_stream) << "Could not write ground truth data.";
00070 }
00071 }
00072
00073 }
00074 }
00075 }
00076
00077 int main(int argc, char** argv) {
00078 google::InitGoogleLogging(argv[0]);
00079 FLAGS_logtostderr = true;
00080 google::SetUsageMessage(
00081 "\n\n"
00082 "This program semi-automatically generates ground truth data from a\n"
00083 "pose graph proto.\n"
00084 "\n"
00085 "The input should contain a single trajectory and should have been\n"
00086 "manually assessed to be correctly loop closed. Small local distortions\n"
00087 "are acceptable if they are tiny compared to the errors we want to\n"
00088 "assess using the generated ground truth data.\n"
00089 "\n"
00090 "All loop closure constraints separated by long covered distance are\n"
00091 "included in the output. Outliers are removed.\n");
00092 google::ParseCommandLineFlags(&argc, &argv, true);
00093
00094 if (FLAGS_pose_graph_filename.empty() || FLAGS_output_filename.empty()) {
00095 google::ShowUsageWithFlagsRestrict(argv[0], "autogenerate_ground_truth");
00096 return EXIT_FAILURE;
00097 }
00098 ::cartographer::ground_truth::Run(
00099 FLAGS_pose_graph_filename, FLAGS_output_filename,
00100 FLAGS_min_covered_distance, FLAGS_outlier_threshold_meters,
00101 FLAGS_outlier_threshold_radians);
00102 }