Sematic-Cartographer/cartographer-master/cartographer/io/probability_grid_points_pro...

213 lines
8.1 KiB
C++
Executable File

/*
* Copyright 2017 The Cartographer Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cartographer/io/probability_grid_points_processor.h"
#include "Eigen/Core"
#include "absl/memory/memory.h"
#include "cartographer/common/lua_parameter_dictionary.h"
#include "cartographer/common/math.h"
#include "cartographer/io/draw_trajectories.h"
#include "cartographer/io/image.h"
#include "cartographer/io/points_batch.h"
#include "cartographer/mapping/probability_values.h"
#include "glog/logging.h"
namespace cartographer {
namespace io {
namespace {
void DrawTrajectoriesIntoImage(
const mapping::ProbabilityGrid& probability_grid,
const Eigen::Array2i& offset,
const std::vector<mapping::proto::Trajectory>& trajectories,
cairo_surface_t* cairo_surface) {
for (size_t i = 0; i < trajectories.size(); ++i) {
DrawTrajectory(
trajectories[i], GetColor(i),
[&probability_grid,
&offset](const transform::Rigid3d& pose) -> Eigen::Array2i {
return probability_grid.limits().GetCellIndex(
pose.cast<float>().translation().head<2>()) -
offset;
},
cairo_surface);
}
}
uint8 ProbabilityToColor(float probability_from_grid) {
const float probability = 1.f - probability_from_grid;
return ::cartographer::common::RoundToInt(
255 * ((probability - mapping::kMinProbability) /
(mapping::kMaxProbability - mapping::kMinProbability)));
}
std::string FileExtensionFromOutputType(
const ProbabilityGridPointsProcessor::OutputType& output_type) {
if (output_type == ProbabilityGridPointsProcessor::OutputType::kPng) {
return ".png";
} else if (output_type == ProbabilityGridPointsProcessor::OutputType::kPb) {
return ".pb";
}
LOG(FATAL) << "OutputType does not exist!";
}
ProbabilityGridPointsProcessor::OutputType OutputTypeFromString(
const std::string& output_type) {
if (output_type == "png") {
return ProbabilityGridPointsProcessor::OutputType::kPng;
} else if (output_type == "pb") {
return ProbabilityGridPointsProcessor::OutputType::kPb;
} else {
LOG(FATAL) << "OutputType " << output_type << " does not exist!";
}
}
} // namespace
ProbabilityGridPointsProcessor::ProbabilityGridPointsProcessor(
const double resolution,
const mapping::proto::ProbabilityGridRangeDataInserterOptions2D&
probability_grid_range_data_inserter_options,
const DrawTrajectories& draw_trajectories, const OutputType& output_type,
std::unique_ptr<FileWriter> file_writer,
const std::vector<mapping::proto::Trajectory>& trajectories,
PointsProcessor* const next)
: draw_trajectories_(draw_trajectories),
output_type_(output_type),
trajectories_(trajectories),
file_writer_(std::move(file_writer)),
next_(next),
range_data_inserter_(probability_grid_range_data_inserter_options),
probability_grid_(
CreateProbabilityGrid(resolution, &conversion_tables_)) {
LOG_IF(WARNING, output_type == OutputType::kPb &&
draw_trajectories_ == DrawTrajectories::kYes)
<< "Drawing the trajectories is not supported when writing the "
"probability grid as protobuf.";
}
std::unique_ptr<ProbabilityGridPointsProcessor>
ProbabilityGridPointsProcessor::FromDictionary(
const std::vector<mapping::proto::Trajectory>& trajectories,
const FileWriterFactory& file_writer_factory,
common::LuaParameterDictionary* const dictionary,
PointsProcessor* const next) {
const auto draw_trajectories = (!dictionary->HasKey("draw_trajectories") ||
dictionary->GetBool("draw_trajectories"))
? DrawTrajectories::kYes
: DrawTrajectories::kNo;
const auto output_type =
dictionary->HasKey("output_type")
? OutputTypeFromString(dictionary->GetString("output_type"))
: OutputType::kPng;
return absl::make_unique<ProbabilityGridPointsProcessor>(
dictionary->GetDouble("resolution"),
mapping::CreateProbabilityGridRangeDataInserterOptions2D(
dictionary->GetDictionary("range_data_inserter").get()),
draw_trajectories, output_type,
file_writer_factory(dictionary->GetString("filename") +
FileExtensionFromOutputType(output_type)),
trajectories, next);
}
void ProbabilityGridPointsProcessor::Process(
std::unique_ptr<PointsBatch> batch) {
range_data_inserter_.Insert(
{batch->origin, sensor::PointCloud(batch->points), {}},
&probability_grid_);
next_->Process(std::move(batch));
}
PointsProcessor::FlushResult ProbabilityGridPointsProcessor::Flush() {
if (output_type_ == OutputType::kPng) {
Eigen::Array2i offset;
std::unique_ptr<Image> image =
DrawProbabilityGrid(probability_grid_, &offset);
if (image != nullptr) {
if (draw_trajectories_ ==
ProbabilityGridPointsProcessor::DrawTrajectories::kYes) {
DrawTrajectoriesIntoImage(probability_grid_, offset, trajectories_,
image->GetCairoSurface().get());
}
image->WritePng(file_writer_.get());
CHECK(file_writer_->Close());
}
} else if (output_type_ == OutputType::kPb) {
const auto probability_grid_proto = probability_grid_.ToProto();
std::string probability_grid_serialized;
probability_grid_proto.SerializeToString(&probability_grid_serialized);
file_writer_->Write(probability_grid_serialized.data(),
probability_grid_serialized.size());
CHECK(file_writer_->Close());
} else {
LOG(FATAL) << "Output Type " << FileExtensionFromOutputType(output_type_)
<< " is not supported.";
}
switch (next_->Flush()) {
case FlushResult::kRestartStream:
LOG(FATAL) << "ProbabilityGrid generation must be configured to occur "
"after any stages that require multiple passes.";
case FlushResult::kFinished:
return FlushResult::kFinished;
}
LOG(FATAL);
// The following unreachable return statement is needed to avoid a GCC bug
// described at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81508
return FlushResult::kFinished;
}
std::unique_ptr<Image> DrawProbabilityGrid(
const mapping::ProbabilityGrid& probability_grid, Eigen::Array2i* offset) {
mapping::CellLimits cell_limits;
probability_grid.ComputeCroppedLimits(offset, &cell_limits);
if (cell_limits.num_x_cells == 0 || cell_limits.num_y_cells == 0) {
LOG(WARNING) << "Not writing output: empty probability grid";
return nullptr;
}
auto image = absl::make_unique<Image>(cell_limits.num_x_cells,
cell_limits.num_y_cells);
for (const Eigen::Array2i& xy_index :
mapping::XYIndexRangeIterator(cell_limits)) {
const Eigen::Array2i index = xy_index + *offset;
constexpr uint8 kUnknownValue = 128;
const uint8 value =
probability_grid.IsKnown(index)
? ProbabilityToColor(probability_grid.GetProbability(index))
: kUnknownValue;
image->SetPixel(xy_index.x(), xy_index.y(), {{value, value, value}});
}
return image;
}
mapping::ProbabilityGrid CreateProbabilityGrid(
const double resolution,
mapping::ValueConversionTables* conversion_tables) {
constexpr int kInitialProbabilityGridSize = 100;
Eigen::Vector2d max =
0.5 * kInitialProbabilityGridSize * resolution * Eigen::Vector2d::Ones();
return mapping::ProbabilityGrid(
mapping::MapLimits(resolution, max,
mapping::CellLimits(kInitialProbabilityGridSize,
kInitialProbabilityGridSize)),
conversion_tables);
}
} // namespace io
} // namespace cartographer