ply_writing_points_processor.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2016 The Cartographer Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
19 #include <iomanip>
20 #include <sstream>
21 #include <string>
22 
26 #include "glog/logging.h"
27 
28 namespace cartographer {
29 namespace io {
30 
31 namespace {
32 
33 // Writes the PLY header claiming 'num_points' will follow it into
34 // 'output_file'.
35 void WriteBinaryPlyHeader(const bool has_color, const bool has_intensities,
36  const int64 num_points,
37  FileWriter* const file_writer) {
38  const std::string color_header = !has_color ? ""
39  : "property uchar red\n"
40  "property uchar green\n"
41  "property uchar blue\n";
42  const std::string intensity_header =
43  !has_intensities ? "" : "property float intensity\n";
44  std::ostringstream stream;
45  stream << "ply\n"
46  << "format binary_little_endian 1.0\n"
47  << "comment generated by Cartographer\n"
48  << "element vertex " << std::setw(15) << std::setfill('0')
49  << num_points << "\n"
50  << "property float x\n"
51  << "property float y\n"
52  << "property float z\n"
53  << color_header << intensity_header << "end_header\n";
54  const std::string out = stream.str();
55  CHECK(file_writer->WriteHeader(out.data(), out.size()));
56 }
57 
58 void WriteBinaryPlyPointCoordinate(const Eigen::Vector3f& point,
59  FileWriter* const file_writer) {
60  // TODO(sirver): This ignores endianness.
61  char buffer[12];
62  memcpy(buffer, &point[0], sizeof(float));
63  memcpy(buffer + 4, &point[1], sizeof(float));
64  memcpy(buffer + 8, &point[2], sizeof(float));
65  CHECK(file_writer->Write(buffer, 12));
66 }
67 
68 void WriteBinaryIntensity(const float intensity,
69  FileWriter* const file_writer) {
70  // TODO(sirver): This ignores endianness.
71  CHECK(file_writer->Write(reinterpret_cast<const char*>(&intensity),
72  sizeof(float)));
73 }
74 
75 void WriteBinaryPlyPointColor(const Uint8Color& color,
76  FileWriter* const file_writer) {
77  CHECK(file_writer->Write(reinterpret_cast<const char*>(color.data()),
78  color.size()));
79 }
80 
81 } // namespace
82 
83 std::unique_ptr<PlyWritingPointsProcessor>
85  const FileWriterFactory& file_writer_factory,
86  common::LuaParameterDictionary* const dictionary,
87  PointsProcessor* const next) {
88  return common::make_unique<PlyWritingPointsProcessor>(
89  file_writer_factory(dictionary->GetString("filename")), next);
90 }
91 
93  std::unique_ptr<FileWriter> file_writer, PointsProcessor* const next)
94  : next_(next),
95  num_points_(0),
96  has_colors_(false),
97  file_(std::move(file_writer)) {}
98 
100  WriteBinaryPlyHeader(has_colors_, has_intensities_, num_points_, file_.get());
101  CHECK(file_->Close()) << "Closing PLY file_writer failed.";
102 
103  switch (next_->Flush()) {
105  return FlushResult::kFinished;
106 
108  LOG(FATAL) << "PLY generation must be configured to occur after any "
109  "stages that require multiple passes.";
110  }
111  LOG(FATAL);
112 }
113 
114 void PlyWritingPointsProcessor::Process(std::unique_ptr<PointsBatch> batch) {
115  if (batch->points.empty()) {
116  next_->Process(std::move(batch));
117  return;
118  }
119 
120  if (num_points_ == 0) {
121  has_colors_ = !batch->colors.empty();
122  has_intensities_ = !batch->intensities.empty();
123  WriteBinaryPlyHeader(has_colors_, has_intensities_, 0, file_.get());
124  }
125  if (has_colors_) {
126  CHECK_EQ(batch->points.size(), batch->colors.size())
127  << "First PointsBatch had colors, but encountered one without. "
128  "frame_id: "
129  << batch->frame_id;
130  }
131  if (has_intensities_) {
132  CHECK_EQ(batch->points.size(), batch->intensities.size())
133  << "First PointsBatch had intensities, but encountered one without. "
134  "frame_id: "
135  << batch->frame_id;
136  }
137 
138  for (size_t i = 0; i < batch->points.size(); ++i) {
139  WriteBinaryPlyPointCoordinate(batch->points[i], file_.get());
140  if (has_colors_) {
141  WriteBinaryPlyPointColor(ToUint8Color(batch->colors[i]), file_.get());
142  }
143  if (has_intensities_) {
144  WriteBinaryIntensity(batch->intensities[i], file_.get());
145  }
146  ++num_points_;
147  }
148  next_->Process(std::move(batch));
149 }
150 
151 } // namespace io
152 } // namespace cartographer
virtual void Process(std::unique_ptr< PointsBatch > points_batch)=0
std::function< std::unique_ptr< FileWriter >(const std::string &filename)> FileWriterFactory
Definition: file_writer.h:66
PlyWritingPointsProcessor(std::unique_ptr< FileWriter > file_writer, PointsProcessor *next)
int64_t int64
Definition: port.h:33
Uint8Color ToUint8Color(const FloatColor &color)
Definition: color.h:42
void Process(std::unique_ptr< PointsBatch > batch) override
std::array< uint8, 3 > Uint8Color
Definition: color.h:28
virtual FlushResult Flush()=0
static std::unique_ptr< PlyWritingPointsProcessor > FromDictionary(const FileWriterFactory &file_writer_factory, common::LuaParameterDictionary *dictionary, PointsProcessor *next)


cartographer
Author(s): The Cartographer Authors
autogenerated on Mon Feb 28 2022 22:00:58