Caro的代碼使用了大量的 C++11 新特性,這篇博客將對這些出現的特性進行彙總以及記錄,我還沒怎麼用過C++11。
1 關鍵字:
constexpr: 在編譯過程就能確定的常量(計算結果的表達式)
void Run() {
constexpr double kTfBufferCacheTimeInSeconds = 10.;
tf2_ros::Buffer tf_buffer{::ros::Duration(kTfBufferCacheTimeInSeconds)};
tf2_ros::TransformListener tf(tf_buffer);
// ...
}
delete: 禁止使用該函數
// Wires up ROS topics to SLAM. 將ROS主題連接到SLAM。
class Node {
public:
Node(const NodeOptions& node_options,
std::unique_ptr<cartographer::mapping::MapBuilderInterface> map_builder,
tf2_ros::Buffer* tf_buffer);
~Node();
// = delete 禁止使用該函數, delete 可用於任何函數
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
// ...
}
explicit: 阻止隱式轉換的發生
class SensorBridge {
public:
explicit SensorBridge(
int num_subdivisions_per_laser_scan, const std::string& tracking_frame,
double lookup_transform_timeout_sec, tf2_ros::Buffer* tf_buffer,
::cartographer::mapping::TrajectoryBuilderInterface* trajectory_builder);
// ...
}
2 方法:
std::move(): 將左值引用轉變爲右值引用
void Run() {
// ...
// move() 將左值引用轉變爲右值引用
auto map_builder =
cartographer::common::make_unique<cartographer::mapping::MapBuilder>(
node_options.map_builder_options);
Node node(node_options, std::move(map_builder), &tf_buffer);
if (!FLAGS_load_state_filename.empty()) {
node.LoadState(FLAGS_load_state_filename, FLAGS_load_frozen_state);
}
// ...
}
std::tie()
void Run() {
// ...
NodeOptions node_options;
TrajectoryOptions trajectory_options;
std::tie(node_options, trajectory_options) =
LoadOptions(FLAGS_configuration_directory, FLAGS_configuration_basename);
// ...
}
std::forward_as_tuple()
extrapolators_.emplace(
std::piecewise_construct, std::forward_as_tuple(trajectory_id),
std::forward_as_tuple(
::cartographer::common::FromSeconds(kExtrapolationEstimationTimeSec),
gravity_time_constant));
std::tuple()
std::map()
#include <map>
#include <unordered_map>
// These are keyed with 'trajectory_id'.
std::map<int, ::cartographer::mapping::PoseExtrapolator> extrapolators_;
std::unordered_map<int, TrajectorySensorSamplers> sensor_samplers_;
map::emplace() 用於直接構造和插入元素
std::set<>
#include <set>
#include <unordered_set>
// Adds a trajectory for offline processing, i.e. not listening to topics.
int AddOfflineTrajectory(
const std::set<
cartographer::mapping::TrajectoryBuilderInterface::SensorId>&
expected_sensor_ids,
const TrajectoryOptions& options);
// unordered_set
std::unordered_set<std::string> subscribed_topics_;
set::insert()
std::unique_ptr<>
#include <memory>
3 其他:
GUARDED_BY()
MapBuilderBridge map_builder_bridge_ GUARDED_BY(mutex_);
EXCLUDES()
std::unordered_map<int, TrajectoryState> GetTrajectoryStates() EXCLUDES(mutex_);
type_traits: 模板元編程
#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
// Implementation of c++14's std::make_unique, taken from
// https://isocpp.org/files/papers/N3656.txt
template <class T>
struct _Unique_if {
typedef std::unique_ptr<T> _Single_object;
};
... : 可變參數模板
template <class T, class... Args>
typename _Unique_if<T>::_Single_object make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
std::remove_extent: 返回數組降低一個維度後的數據類型
template <class T>
typename _Unique_if<T>::_Unknown_bound make_unique(size_t n) {
typedef typename std::remove_extent<T>::type U;
return std::unique_ptr<T>(new U[n]());
}
std::bind std::placeholders : 佔位符
const int trajectory_id = map_builder_->AddTrajectoryBuilder(
expected_sensor_ids, trajectory_options.trajectory_builder_options,
::std::bind(&MapBuilderBridge::OnLocalSlamResult, this,
::std::placeholders::_1, ::std::placeholders::_2,
::std::placeholders::_3, ::std::placeholders::_4,
::std::placeholders::_5));
std::function
// cartographer/cartographer/mapping/trajectory_builder_interface.h
#include<functional>
using LocalSlamResultCallback =
std::function<void(int /* trajectory ID */, common::Time,
transform::Rigid3d /* local pose estimate */,
sensor::RangeData /* in local frame */,
std::unique_ptr<const InsertionResult>)>;
// cartographer/cartographer/mapping/map_builder_interface.h
using LocalSlamResultCallback =
TrajectoryBuilderInterface::LocalSlamResultCallback;
// Creates a new trajectory builder and returns its index.
virtual int AddTrajectoryBuilder(
const std::set<SensorId>& expected_sensor_ids,
const proto::TrajectoryBuilderOptions& trajectory_options,
LocalSlamResultCallback local_slam_result_callback) = 0;
// cartographer/cartographer/mapping/map_builder.h
int AddTrajectoryBuilder(
const std::set<SensorId> &expected_sensor_ids,
const proto::TrajectoryBuilderOptions &trajectory_options,
LocalSlamResultCallback local_slam_result_callback) override;
for (const auto& entry : sensor_bridges_)
std::unordered_map<int, MapBuilderBridge::TrajectoryState>
MapBuilderBridge::GetTrajectoryStates() {
std::unordered_map<int, TrajectoryState> trajectory_states;
for (const auto& entry : sensor_bridges_) {
const int trajectory_id = entry.first;
const SensorBridge& sensor_bridge = *entry.second;
std::shared_ptr<const TrajectoryState::LocalSlamData> local_slam_data;
{
cartographer::common::MutexLocker lock(&mutex_);
if (trajectory_state_data_.count(trajectory_id) == 0) {
continue;
}
local_slam_data = trajectory_state_data_.at(trajectory_id);
}
// Make sure there is a trajectory with 'trajectory_id'.
CHECK_EQ(trajectory_options_.count(trajectory_id), 1);
trajectory_states[trajectory_id] = {
local_slam_data,
map_builder_->pose_graph()->GetLocalToGlobalTransform(trajectory_id),
sensor_bridge.tf_bridge().LookupToTracking(
local_slam_data->time,
trajectory_options_[trajectory_id].published_frame),
trajectory_options_[trajectory_id]};
}
return trajectory_states;
}
std::chrono
#include <chrono>
// Time at which we last logged the rates of incoming sensor data.
std::chrono::steady_clock::time_point last_logging_time_;
lamda表達式
// cartographer/mapping/internal/collated_trajectory_builder.cc
sensor_collator_->AddTrajectory(
trajectory_id, expected_sensor_id_strings,
[this](const std::string& sensor_id, std::unique_ptr<sensor::Data> data) {
HandleCollatedSensorData(sensor_id, std::move(data));
});
// cartographer/sensor/collator_interface.h
// Adds a trajectory to produce sorted sensor output for. Calls 'callback'
// for each collated sensor data.
virtual void AddTrajectory(
int trajectory_id,
const std::unordered_set<std::string>& expected_sensor_ids,
const Callback& callback) = 0;
// cartographer/sensor/internal/collator.cc
void Collator::AddTrajectory(
const int trajectory_id,
const std::unordered_set<std::string>& expected_sensor_ids,
const Callback& callback) {
for (const auto& sensor_id : expected_sensor_ids) {
const auto queue_key = QueueKey{trajectory_id, sensor_id};
queue_.AddQueue(queue_key,
[callback, sensor_id](std::unique_ptr<Data> data) {
callback(sensor_id, std::move(data));
});
queue_keys_[trajectory_id].push_back(queue_key);
}
}
// cartographer/sensor/internal/ordered_multi_queue.cc
void OrderedMultiQueue::AddQueue(const QueueKey& queue_key, Callback callback) {
CHECK_EQ(queues_.count(queue_key), 0);
queues_[queue_key].callback = std::move(callback);
}
std::mt19937 rng(0);
計算隨機數的算法
std::prev