parent
2434e7e40e
commit
ea55e837d2
|
@ -18,10 +18,14 @@
|
||||||
#define CARTOGRAPHER_MAPPING_ID_H_
|
#define CARTOGRAPHER_MAPPING_ID_H_
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <map>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "glog/logging.h"
|
||||||
|
|
||||||
namespace cartographer {
|
namespace cartographer {
|
||||||
namespace mapping {
|
namespace mapping {
|
||||||
|
|
||||||
|
@ -105,6 +109,139 @@ class NestedVectorsById {
|
||||||
std::vector<std::vector<ValueType>> data_;
|
std::vector<std::vector<ValueType>> data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Like std::map, but indexed by 'IdType' which can be 'NodeId' or 'SubmapId'.
|
||||||
|
template <typename IdType, typename DataType>
|
||||||
|
class MapById {
|
||||||
|
private:
|
||||||
|
class MapByIndex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct IdDataReference {
|
||||||
|
IdType id;
|
||||||
|
const DataType& data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstIterator
|
||||||
|
: public std::iterator<std::forward_iterator_tag, IdDataReference> {
|
||||||
|
public:
|
||||||
|
explicit ConstIterator(const MapById& map_by_id)
|
||||||
|
: current_trajectory_(map_by_id.trajectories_.begin()),
|
||||||
|
end_trajectory_(map_by_id.trajectories_.end()) {
|
||||||
|
if (current_trajectory_ != end_trajectory_) {
|
||||||
|
current_data_ = current_trajectory_->second.data_.begin();
|
||||||
|
end_data_ = current_trajectory_->second.data_.end();
|
||||||
|
AdvanceToValidDataIterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConstIterator EndIterator(const MapById& map_by_id) {
|
||||||
|
auto it = ConstIterator(map_by_id);
|
||||||
|
it.current_trajectory_ = it.end_trajectory_;
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
IdDataReference operator*() const {
|
||||||
|
CHECK(current_trajectory_ != end_trajectory_);
|
||||||
|
return IdDataReference{
|
||||||
|
IdType{current_trajectory_->first, current_data_->first},
|
||||||
|
current_data_->second};
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstIterator& operator++() {
|
||||||
|
CHECK(current_trajectory_ != end_trajectory_);
|
||||||
|
++current_data_;
|
||||||
|
AdvanceToValidDataIterator();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const ConstIterator& it) const {
|
||||||
|
if (current_trajectory_ == end_trajectory_ ||
|
||||||
|
it.current_trajectory_ == it.end_trajectory_) {
|
||||||
|
return current_trajectory_ == it.current_trajectory_;
|
||||||
|
}
|
||||||
|
return current_trajectory_ == it.current_trajectory_ &&
|
||||||
|
current_data_ == it.current_data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const ConstIterator& it) const { return !operator==(it); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AdvanceToValidDataIterator() {
|
||||||
|
CHECK(current_trajectory_ != end_trajectory_);
|
||||||
|
while (current_data_ == end_data_) {
|
||||||
|
++current_trajectory_;
|
||||||
|
if (current_trajectory_ == end_trajectory_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current_data_ = current_trajectory_->second.data_.begin();
|
||||||
|
end_data_ = current_trajectory_->second.data_.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typename std::map<int, MapByIndex>::const_iterator current_trajectory_;
|
||||||
|
typename std::map<int, MapByIndex>::const_iterator end_trajectory_;
|
||||||
|
typename std::map<int, DataType>::const_iterator current_data_;
|
||||||
|
typename std::map<int, DataType>::const_iterator end_data_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Appends data to a 'trajectory_id', creating trajectories as needed.
|
||||||
|
IdType Append(const int trajectory_id, const DataType& data) {
|
||||||
|
CHECK_GE(trajectory_id, 0);
|
||||||
|
auto& trajectory = trajectories_[trajectory_id];
|
||||||
|
CHECK(trajectory.can_append_);
|
||||||
|
const int index =
|
||||||
|
trajectory.data_.empty() ? 0 : trajectory.data_.rbegin()->first + 1;
|
||||||
|
trajectory.data_.emplace(index, data);
|
||||||
|
return IdType{trajectory_id, index};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inserts data (which must not exist already) into a trajectory.
|
||||||
|
void Insert(const IdType& id, const DataType& data) {
|
||||||
|
auto& trajectory = trajectories_[id.trajectory_id];
|
||||||
|
trajectory.can_append_ = false;
|
||||||
|
CHECK(trajectory.data_.emplace(GetIndex(id), data).second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes the data for 'id' which must exist.
|
||||||
|
void Trim(const IdType& id) {
|
||||||
|
auto& trajectory = trajectories_.at(id.trajectory_id);
|
||||||
|
const auto it = trajectory.data_.find(GetIndex(id));
|
||||||
|
CHECK(it != trajectory.data_.end());
|
||||||
|
if (std::next(it) == trajectory.data_.end()) {
|
||||||
|
// We are removing the data with the highest index from this trajectory.
|
||||||
|
// We assume that we will never append to it anymore. If we did, we would
|
||||||
|
// have to make sure that gaps in indices are properly chosen to maintain
|
||||||
|
// correct connectivity.
|
||||||
|
trajectory.can_append_ = false;
|
||||||
|
}
|
||||||
|
trajectory.data_.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataType& at(const IdType& id) const {
|
||||||
|
return trajectories_.at(id.trajectory_id).data_.at(GetIndex(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
DataType& at(const IdType& id) {
|
||||||
|
return trajectories_.at(id.trajectory_id).data_.at(GetIndex(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstIterator begin() const { return ConstIterator(*this); }
|
||||||
|
ConstIterator end() const { return ConstIterator::EndIterator(*this); }
|
||||||
|
|
||||||
|
bool empty() const { return begin() == end(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct MapByIndex {
|
||||||
|
bool can_append_ = true;
|
||||||
|
std::map<int, DataType> data_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int GetIndex(const NodeId& id) { return id.node_index; }
|
||||||
|
static int GetIndex(const SubmapId& id) { return id.submap_index; }
|
||||||
|
|
||||||
|
std::map<int, MapByIndex> trajectories_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mapping
|
} // namespace mapping
|
||||||
} // namespace cartographer
|
} // namespace cartographer
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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/mapping/id.h"
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
namespace cartographer {
|
||||||
|
namespace mapping {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
TEST(IdTest, EmptyMapById) {
|
||||||
|
MapById<NodeId, int> map_by_id;
|
||||||
|
EXPECT_TRUE(map_by_id.empty());
|
||||||
|
const NodeId id = map_by_id.Append(42, 42);
|
||||||
|
EXPECT_FALSE(map_by_id.empty());
|
||||||
|
map_by_id.Trim(id);
|
||||||
|
EXPECT_TRUE(map_by_id.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IdTest, MapByIdIterator) {
|
||||||
|
MapById<NodeId, int> map_by_id;
|
||||||
|
map_by_id.Append(7, 2);
|
||||||
|
map_by_id.Append(42, 3);
|
||||||
|
map_by_id.Append(0, 0);
|
||||||
|
map_by_id.Append(0, 1);
|
||||||
|
std::deque<std::pair<NodeId, int>> expected_id_data = {
|
||||||
|
{NodeId{0, 0}, 0},
|
||||||
|
{NodeId{0, 1}, 1},
|
||||||
|
{NodeId{7, 0}, 2},
|
||||||
|
{NodeId{42, 0}, 3},
|
||||||
|
};
|
||||||
|
for (const auto& id_data : map_by_id) {
|
||||||
|
EXPECT_EQ(expected_id_data.front().first, id_data.id);
|
||||||
|
EXPECT_EQ(expected_id_data.front().second, id_data.data);
|
||||||
|
ASSERT_FALSE(expected_id_data.empty());
|
||||||
|
expected_id_data.pop_front();
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(expected_id_data.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace mapping
|
||||||
|
} // namespace cartographer
|
|
@ -55,7 +55,7 @@ std::vector<mapping::SubmapId> SparsePoseGraph::GrowSubmapTransformsAsNeeded(
|
||||||
const int trajectory_id,
|
const int trajectory_id,
|
||||||
const std::vector<std::shared_ptr<const Submap>>& insertion_submaps) {
|
const std::vector<std::shared_ptr<const Submap>>& insertion_submaps) {
|
||||||
CHECK(!insertion_submaps.empty());
|
CHECK(!insertion_submaps.empty());
|
||||||
const auto& submap_data = optimization_problem_.submap_data();
|
auto submap_data = optimization_problem_.submap_data();
|
||||||
if (insertion_submaps.size() == 1) {
|
if (insertion_submaps.size() == 1) {
|
||||||
// If we don't already have an entry for the first submap, add one.
|
// If we don't already have an entry for the first submap, add one.
|
||||||
if (static_cast<size_t>(trajectory_id) >= submap_data.size() ||
|
if (static_cast<size_t>(trajectory_id) >= submap_data.size() ||
|
||||||
|
@ -63,6 +63,7 @@ std::vector<mapping::SubmapId> SparsePoseGraph::GrowSubmapTransformsAsNeeded(
|
||||||
optimization_problem_.AddSubmap(
|
optimization_problem_.AddSubmap(
|
||||||
trajectory_id,
|
trajectory_id,
|
||||||
sparse_pose_graph::ComputeSubmapPose(*insertion_submaps[0]));
|
sparse_pose_graph::ComputeSubmapPose(*insertion_submaps[0]));
|
||||||
|
submap_data = optimization_problem_.submap_data();
|
||||||
}
|
}
|
||||||
CHECK_EQ(submap_data[trajectory_id].size(), 1);
|
CHECK_EQ(submap_data[trajectory_id].size(), 1);
|
||||||
const mapping::SubmapId submap_id{trajectory_id, 0};
|
const mapping::SubmapId submap_id{trajectory_id, 0};
|
||||||
|
@ -499,7 +500,7 @@ void SparsePoseGraph::RunOptimization() {
|
||||||
optimization_problem_.Solve(constraints_, frozen_trajectories_);
|
optimization_problem_.Solve(constraints_, frozen_trajectories_);
|
||||||
common::MutexLocker locker(&mutex_);
|
common::MutexLocker locker(&mutex_);
|
||||||
|
|
||||||
const auto& submap_data = optimization_problem_.submap_data();
|
const auto submap_data = optimization_problem_.submap_data();
|
||||||
const auto& node_data = optimization_problem_.node_data();
|
const auto& node_data = optimization_problem_.node_data();
|
||||||
for (int trajectory_id = 0;
|
for (int trajectory_id = 0;
|
||||||
trajectory_id != static_cast<int>(node_data.size()); ++trajectory_id) {
|
trajectory_id != static_cast<int>(node_data.size()); ++trajectory_id) {
|
||||||
|
|
|
@ -109,20 +109,11 @@ void OptimizationProblem::TrimTrajectoryNode(const mapping::NodeId& node_id) {
|
||||||
|
|
||||||
void OptimizationProblem::AddSubmap(const int trajectory_id,
|
void OptimizationProblem::AddSubmap(const int trajectory_id,
|
||||||
const transform::Rigid2d& submap_pose) {
|
const transform::Rigid2d& submap_pose) {
|
||||||
CHECK_GE(trajectory_id, 0);
|
submap_data_.Append(trajectory_id, SubmapData{submap_pose});
|
||||||
submap_data_.resize(
|
|
||||||
std::max(submap_data_.size(), static_cast<size_t>(trajectory_id) + 1));
|
|
||||||
trajectory_data_.resize(
|
|
||||||
std::max(trajectory_data_.size(), submap_data_.size()));
|
|
||||||
auto& trajectory_data = trajectory_data_[trajectory_id];
|
|
||||||
submap_data_[trajectory_id].emplace(trajectory_data.next_submap_index,
|
|
||||||
SubmapData{submap_pose});
|
|
||||||
++trajectory_data.next_submap_index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptimizationProblem::TrimSubmap(const mapping::SubmapId& submap_id) {
|
void OptimizationProblem::TrimSubmap(const mapping::SubmapId& submap_id) {
|
||||||
auto& submap_data = submap_data_.at(submap_id.trajectory_id);
|
submap_data_.Trim(submap_id);
|
||||||
CHECK(submap_data.erase(submap_id.submap_index));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptimizationProblem::SetMaxNumIterations(const int32 max_num_iterations) {
|
void OptimizationProblem::SetMaxNumIterations(const int32 max_num_iterations) {
|
||||||
|
@ -142,33 +133,24 @@ void OptimizationProblem::Solve(const std::vector<Constraint>& constraints,
|
||||||
|
|
||||||
// Set the starting point.
|
// Set the starting point.
|
||||||
// TODO(hrapp): Move ceres data into SubmapData.
|
// TODO(hrapp): Move ceres data into SubmapData.
|
||||||
std::vector<std::map<int, std::array<double, 3>>> C_submaps(
|
mapping::MapById<mapping::SubmapId, std::array<double, 3>> C_submaps;
|
||||||
submap_data_.size());
|
|
||||||
std::vector<std::map<int, std::array<double, 3>>> C_nodes(node_data_.size());
|
std::vector<std::map<int, std::array<double, 3>>> C_nodes(node_data_.size());
|
||||||
bool first_submap = true;
|
bool first_submap = true;
|
||||||
for (size_t trajectory_id = 0; trajectory_id != submap_data_.size();
|
for (const auto& submap_id_data : submap_data_) {
|
||||||
++trajectory_id) {
|
const bool frozen =
|
||||||
const bool frozen = frozen_trajectories.count(trajectory_id);
|
frozen_trajectories.count(submap_id_data.id.trajectory_id) != 0;
|
||||||
for (const auto& index_submap_data : submap_data_[trajectory_id]) {
|
C_submaps.Insert(submap_id_data.id, FromPose(submap_id_data.data.pose));
|
||||||
const int submap_index = index_submap_data.first;
|
problem.AddParameterBlock(C_submaps.at(submap_id_data.id).data(), 3);
|
||||||
const SubmapData& submap_data = index_submap_data.second;
|
if (first_submap || frozen) {
|
||||||
|
first_submap = false;
|
||||||
C_submaps[trajectory_id].emplace(submap_index,
|
// Fix the pose of the first submap or all submaps of a frozen
|
||||||
FromPose(submap_data.pose));
|
// trajectory.
|
||||||
problem.AddParameterBlock(
|
problem.SetParameterBlockConstant(C_submaps.at(submap_id_data.id).data());
|
||||||
C_submaps[trajectory_id].at(submap_index).data(), 3);
|
|
||||||
if (first_submap || frozen) {
|
|
||||||
first_submap = false;
|
|
||||||
// Fix the pose of the first submap or all submaps of a frozen
|
|
||||||
// trajectory.
|
|
||||||
problem.SetParameterBlockConstant(
|
|
||||||
C_submaps[trajectory_id].at(submap_index).data());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t trajectory_id = 0; trajectory_id != node_data_.size();
|
for (size_t trajectory_id = 0; trajectory_id != node_data_.size();
|
||||||
++trajectory_id) {
|
++trajectory_id) {
|
||||||
const bool frozen = frozen_trajectories.count(trajectory_id);
|
const bool frozen = frozen_trajectories.count(trajectory_id) != 0;
|
||||||
for (const auto& index_node_data : node_data_[trajectory_id]) {
|
for (const auto& index_node_data : node_data_[trajectory_id]) {
|
||||||
const int node_index = index_node_data.first;
|
const int node_index = index_node_data.first;
|
||||||
const NodeData& node_data = index_node_data.second;
|
const NodeData& node_data = index_node_data.second;
|
||||||
|
@ -190,9 +172,7 @@ void OptimizationProblem::Solve(const std::vector<Constraint>& constraints,
|
||||||
constraint.tag == Constraint::INTER_SUBMAP
|
constraint.tag == Constraint::INTER_SUBMAP
|
||||||
? new ceres::HuberLoss(options_.huber_scale())
|
? new ceres::HuberLoss(options_.huber_scale())
|
||||||
: nullptr,
|
: nullptr,
|
||||||
C_submaps.at(constraint.submap_id.trajectory_id)
|
C_submaps.at(constraint.submap_id).data(),
|
||||||
.at(constraint.submap_id.submap_index)
|
|
||||||
.data(),
|
|
||||||
C_nodes.at(constraint.node_id.trajectory_id)
|
C_nodes.at(constraint.node_id.trajectory_id)
|
||||||
.at(constraint.node_id.node_index)
|
.at(constraint.node_id.node_index)
|
||||||
.data());
|
.data());
|
||||||
|
@ -258,12 +238,8 @@ void OptimizationProblem::Solve(const std::vector<Constraint>& constraints,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the result.
|
// Store the result.
|
||||||
for (size_t trajectory_id = 0; trajectory_id != submap_data_.size();
|
for (const auto& C_submap_id_data : C_submaps) {
|
||||||
++trajectory_id) {
|
submap_data_.at(C_submap_id_data.id).pose = ToPose(C_submap_id_data.data);
|
||||||
for (auto& index_submap_data : submap_data_[trajectory_id]) {
|
|
||||||
index_submap_data.second.pose =
|
|
||||||
ToPose(C_submaps[trajectory_id].at(index_submap_data.first));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (size_t trajectory_id = 0; trajectory_id != node_data_.size();
|
for (size_t trajectory_id = 0; trajectory_id != node_data_.size();
|
||||||
++trajectory_id) {
|
++trajectory_id) {
|
||||||
|
@ -279,9 +255,15 @@ const std::vector<std::map<int, NodeData>>& OptimizationProblem::node_data()
|
||||||
return node_data_;
|
return node_data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::map<int, SubmapData>>& OptimizationProblem::submap_data()
|
std::vector<std::map<int, SubmapData>> OptimizationProblem::submap_data()
|
||||||
const {
|
const {
|
||||||
return submap_data_;
|
std::vector<std::map<int, SubmapData>> result;
|
||||||
|
for (const auto& submap_id_data : submap_data_) {
|
||||||
|
result.resize(submap_id_data.id.trajectory_id + 1);
|
||||||
|
result[submap_id_data.id.trajectory_id].emplace(
|
||||||
|
submap_id_data.id.submap_index, submap_id_data.data);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sparse_pose_graph
|
} // namespace sparse_pose_graph
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "Eigen/Geometry"
|
#include "Eigen/Geometry"
|
||||||
#include "cartographer/common/port.h"
|
#include "cartographer/common/port.h"
|
||||||
#include "cartographer/common/time.h"
|
#include "cartographer/common/time.h"
|
||||||
|
#include "cartographer/mapping/id.h"
|
||||||
#include "cartographer/mapping/sparse_pose_graph.h"
|
#include "cartographer/mapping/sparse_pose_graph.h"
|
||||||
#include "cartographer/mapping/sparse_pose_graph/proto/optimization_problem_options.pb.h"
|
#include "cartographer/mapping/sparse_pose_graph/proto/optimization_problem_options.pb.h"
|
||||||
#include "cartographer/sensor/imu_data.h"
|
#include "cartographer/sensor/imu_data.h"
|
||||||
|
@ -79,19 +80,18 @@ class OptimizationProblem {
|
||||||
const std::set<int>& frozen_trajectories);
|
const std::set<int>& frozen_trajectories);
|
||||||
|
|
||||||
const std::vector<std::map<int, NodeData>>& node_data() const;
|
const std::vector<std::map<int, NodeData>>& node_data() const;
|
||||||
const std::vector<std::map<int, SubmapData>>& submap_data() const;
|
std::vector<std::map<int, SubmapData>> submap_data() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct TrajectoryData {
|
struct TrajectoryData {
|
||||||
// TODO(hrapp): Remove, once we can relabel constraints.
|
// TODO(hrapp): Remove, once we can relabel constraints.
|
||||||
int next_submap_index = 0;
|
|
||||||
int next_node_index = 0;
|
int next_node_index = 0;
|
||||||
};
|
};
|
||||||
mapping::sparse_pose_graph::proto::OptimizationProblemOptions options_;
|
mapping::sparse_pose_graph::proto::OptimizationProblemOptions options_;
|
||||||
std::vector<std::deque<sensor::ImuData>> imu_data_;
|
std::vector<std::deque<sensor::ImuData>> imu_data_;
|
||||||
std::vector<std::map<int, NodeData>> node_data_;
|
std::vector<std::map<int, NodeData>> node_data_;
|
||||||
std::vector<transform::TransformInterpolationBuffer> odometry_data_;
|
std::vector<transform::TransformInterpolationBuffer> odometry_data_;
|
||||||
std::vector<std::map<int, SubmapData>> submap_data_;
|
mapping::MapById<mapping::SubmapId, SubmapData> submap_data_;
|
||||||
std::vector<TrajectoryData> trajectory_data_;
|
std::vector<TrajectoryData> trajectory_data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ void OptimizationProblem::Solve(const std::vector<Constraint>& constraints,
|
||||||
bool first_submap = true;
|
bool first_submap = true;
|
||||||
for (size_t trajectory_id = 0; trajectory_id != submap_data_.size();
|
for (size_t trajectory_id = 0; trajectory_id != submap_data_.size();
|
||||||
++trajectory_id) {
|
++trajectory_id) {
|
||||||
const bool frozen = frozen_trajectories.count(trajectory_id);
|
const bool frozen = frozen_trajectories.count(trajectory_id) != 0;
|
||||||
for (const auto& index_submap_data : submap_data_[trajectory_id]) {
|
for (const auto& index_submap_data : submap_data_[trajectory_id]) {
|
||||||
const int submap_index = index_submap_data.first;
|
const int submap_index = index_submap_data.first;
|
||||||
if (first_submap) {
|
if (first_submap) {
|
||||||
|
@ -191,7 +191,7 @@ void OptimizationProblem::Solve(const std::vector<Constraint>& constraints,
|
||||||
}
|
}
|
||||||
for (size_t trajectory_id = 0; trajectory_id != node_data_.size();
|
for (size_t trajectory_id = 0; trajectory_id != node_data_.size();
|
||||||
++trajectory_id) {
|
++trajectory_id) {
|
||||||
const bool frozen = frozen_trajectories.count(trajectory_id);
|
const bool frozen = frozen_trajectories.count(trajectory_id) != 0;
|
||||||
for (const auto& index_node_data : node_data_[trajectory_id]) {
|
for (const auto& index_node_data : node_data_[trajectory_id]) {
|
||||||
const int node_index = index_node_data.first;
|
const int node_index = index_node_data.first;
|
||||||
C_nodes[trajectory_id].emplace(
|
C_nodes[trajectory_id].emplace(
|
||||||
|
|
Loading…
Reference in New Issue