25 #include "glog/logging.h" 36 using Levels = std::map<int, int>;
38 constexpr
double kMaxShortSpanLengthMeters = 25.;
39 constexpr
double kLevelHeightMeters = 2.5;
40 constexpr
double kMinLevelSeparationMeters = 1.;
48 bool operator<(
const Span& other)
const {
49 return std::forward_as_tuple(start_index, end_index) <
50 std::forward_as_tuple(other.start_index, other.end_index);
55 int LevelFind(
const int i,
const Levels& levels) {
56 auto it = levels.find(i);
57 CHECK(it != levels.end());
58 if (it->first == it->second) {
61 return LevelFind(it->second, levels);
64 void LevelUnion(
int i,
int j, Levels* levels) {
65 const int repr_i = LevelFind(i, *levels);
66 const int repr_j = LevelFind(j, *levels);
67 (*levels)[repr_i] = repr_j;
70 void InsertSorted(
const double val, std::vector<double>* vals) {
71 vals->insert(std::upper_bound(vals->begin(), vals->end(), val), val);
74 double Median(
const std::vector<double>& sorted) {
75 CHECK(!sorted.empty());
76 return sorted.at(sorted.size() / 2);
81 std::vector<Span> SliceByAltitudeChange(
const proto::Trajectory& trajectory) {
82 CHECK_GT(trajectory.node_size(), 0);
84 std::vector<Span> spans;
85 spans.push_back(Span{0, 0, {trajectory.node(0).pose().translation().z()}});
86 for (
int i = 1; i < trajectory.node_size(); ++i) {
87 const auto& node = trajectory.node(i);
88 const double z = node.pose().translation().z();
89 if (std::abs(Median(spans.back().z_values) - z) > kLevelHeightMeters) {
90 spans.push_back(Span{i, i, {}});
92 InsertSorted(z, &spans.back().z_values);
93 spans.back().end_index = i + 1;
99 double SpanLength(
const proto::Trajectory& trajectory,
const Span& span) {
101 for (
int i = span.start_index + 1; i < span.end_index; ++i) {
105 length += (a - b).head<2>().norm();
112 bool IsShort(
const proto::Trajectory& trajectory,
const Span& span) {
113 return SpanLength(trajectory, span) < kMaxShortSpanLengthMeters;
117 void GroupSegmentsByAltitude(
const proto::Trajectory& trajectory,
118 const std::vector<Span>& spans, Levels* levels) {
119 for (
size_t i = 0; i < spans.size(); ++i) {
120 for (
size_t j = i + 1; j < spans.size(); ++j) {
121 if (std::abs(Median(spans[i].
z_values) - Median(spans[j].z_values)) <
122 kMinLevelSeparationMeters) {
123 LevelUnion(i, j, levels);
129 std::vector<Floor> FindFloors(
const proto::Trajectory& trajectory,
130 const std::vector<Span>& spans,
131 const Levels& levels) {
132 std::map<int, std::vector<Span>> level_spans;
135 for (
size_t i = 0; i < spans.size(); ++i) {
136 const Span& span = spans[i];
137 if (!IsShort(trajectory, span)) {
138 level_spans[LevelFind(i, levels)].push_back(span);
142 for (
size_t i = 0; i < spans.size(); ++i) {
143 const Span& span = spans[i];
144 if (!IsShort(trajectory, span)) {
150 int level = LevelFind(i, levels);
151 if (!level_spans[level].empty()) {
152 level_spans[level].push_back(span);
158 size_t index = i - 1;
159 if (index < spans.size()) {
160 level_spans[LevelFind(index, levels)].push_back(span);
163 if (index < spans.size()) {
164 level_spans[LevelFind(index, levels)].push_back(span);
169 std::vector<Floor> floors;
170 for (
auto& level : level_spans) {
171 if (level.second.empty()) {
176 std::sort(level.second.begin(), level.second.end());
177 floors.emplace_back();
178 for (
const auto& span : level.second) {
179 if (!IsShort(trajectory, span)) {
183 z_values.insert(z_values.end(), span.z_values.begin(),
184 span.z_values.end());
186 floors.back().timespans.push_back(Timespan{
189 trajectory.node(span.end_index - 1).timestamp())});
191 std::sort(z_values.begin(), z_values.end());
192 floors.back().z = Median(z_values);
200 const std::vector<Span> spans = SliceByAltitudeChange(trajectory);
202 for (
size_t i = 0; i < spans.size(); ++i) {
205 GroupSegmentsByAltitude(trajectory, spans, &levels);
207 std::vector<Floor> floors = FindFloors(trajectory, spans, levels);
208 std::sort(floors.begin(), floors.end(),
209 [](
const Floor& a,
const Floor& b) {
return a.
z < b.z; });
Time FromUniversal(const int64 ticks)
std::vector< Floor > DetectFloors(const proto::Trajectory &trajectory)
std::vector< double > z_values