Implement receive_global_slam_optimizations_handler (#1169)
parent
a9c90da1a8
commit
fbb2835525
|
@ -21,6 +21,7 @@
|
||||||
#include "cartographer/cloud/internal/map_builder_server.h"
|
#include "cartographer/cloud/internal/map_builder_server.h"
|
||||||
#include "cartographer/cloud/map_builder_server_options.h"
|
#include "cartographer/cloud/map_builder_server_options.h"
|
||||||
#include "cartographer/mapping/internal/testing/mock_map_builder.h"
|
#include "cartographer/mapping/internal/testing/mock_map_builder.h"
|
||||||
|
#include "cartographer/mapping/internal/testing/mock_pose_graph.h"
|
||||||
#include "cartographer/mapping/internal/testing/mock_trajectory_builder.h"
|
#include "cartographer/mapping/internal/testing/mock_trajectory_builder.h"
|
||||||
#include "cartographer/mapping/internal/testing/test_helpers.h"
|
#include "cartographer/mapping/internal/testing/test_helpers.h"
|
||||||
#include "cartographer/mapping/local_slam_result_data.h"
|
#include "cartographer/mapping/local_slam_result_data.h"
|
||||||
|
@ -33,6 +34,7 @@ using ::cartographer::mapping::MapBuilderInterface;
|
||||||
using ::cartographer::mapping::PoseGraphInterface;
|
using ::cartographer::mapping::PoseGraphInterface;
|
||||||
using ::cartographer::mapping::TrajectoryBuilderInterface;
|
using ::cartographer::mapping::TrajectoryBuilderInterface;
|
||||||
using ::cartographer::mapping::testing::MockMapBuilder;
|
using ::cartographer::mapping::testing::MockMapBuilder;
|
||||||
|
using ::cartographer::mapping::testing::MockPoseGraph;
|
||||||
using ::cartographer::mapping::testing::MockTrajectoryBuilder;
|
using ::cartographer::mapping::testing::MockTrajectoryBuilder;
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
using SensorId = ::cartographer::mapping::TrajectoryBuilderInterface::SensorId;
|
using SensorId = ::cartographer::mapping::TrajectoryBuilderInterface::SensorId;
|
||||||
|
@ -126,6 +128,14 @@ class ClientServerTest : public ::testing::Test {
|
||||||
void InitializeServerWithMockMapBuilder() {
|
void InitializeServerWithMockMapBuilder() {
|
||||||
auto mock_map_builder = common::make_unique<MockMapBuilder>();
|
auto mock_map_builder = common::make_unique<MockMapBuilder>();
|
||||||
mock_map_builder_ = mock_map_builder.get();
|
mock_map_builder_ = mock_map_builder.get();
|
||||||
|
mock_pose_graph_ = common::make_unique<MockPoseGraph>();
|
||||||
|
EXPECT_CALL(
|
||||||
|
*mock_map_builder_,
|
||||||
|
pose_graph())
|
||||||
|
.WillOnce(::testing::Return(mock_pose_graph_.get()));
|
||||||
|
EXPECT_CALL(
|
||||||
|
*mock_pose_graph_,
|
||||||
|
SetGlobalSlamOptimizationCallback(_));
|
||||||
server_ = common::make_unique<MapBuilderServer>(
|
server_ = common::make_unique<MapBuilderServer>(
|
||||||
map_builder_server_options_, std::move(mock_map_builder));
|
map_builder_server_options_, std::move(mock_map_builder));
|
||||||
EXPECT_TRUE(server_ != nullptr);
|
EXPECT_TRUE(server_ != nullptr);
|
||||||
|
@ -160,6 +170,7 @@ class ClientServerTest : public ::testing::Test {
|
||||||
proto::MapBuilderServerOptions map_builder_server_options_;
|
proto::MapBuilderServerOptions map_builder_server_options_;
|
||||||
proto::MapBuilderServerOptions uploading_map_builder_server_options_;
|
proto::MapBuilderServerOptions uploading_map_builder_server_options_;
|
||||||
MockMapBuilder* mock_map_builder_;
|
MockMapBuilder* mock_map_builder_;
|
||||||
|
std::unique_ptr<MockPoseGraph> mock_pose_graph_;
|
||||||
std::unique_ptr<MockTrajectoryBuilder> mock_trajectory_builder_;
|
std::unique_ptr<MockTrajectoryBuilder> mock_trajectory_builder_;
|
||||||
::cartographer::mapping::proto::TrajectoryBuilderOptions
|
::cartographer::mapping::proto::TrajectoryBuilderOptions
|
||||||
trajectory_builder_options_;
|
trajectory_builder_options_;
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 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/cloud/internal/handlers/receive_global_slam_optimizations_handler.h"
|
||||||
|
|
||||||
|
#include "async_grpc/rpc_handler.h"
|
||||||
|
#include "cartographer/cloud/internal/map_builder_context_interface.h"
|
||||||
|
#include "cartographer/cloud/proto/map_builder_service.pb.h"
|
||||||
|
#include "cartographer/common/make_unique.h"
|
||||||
|
#include "cartographer/transform/transform.h"
|
||||||
|
|
||||||
|
namespace cartographer {
|
||||||
|
namespace cloud {
|
||||||
|
namespace handlers {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::unique_ptr<proto::ReceiveGlobalSlamOptimizationsResponse> GenerateResponse(
|
||||||
|
const std::map<int, mapping::SubmapId> &last_optimized_submap_ids,
|
||||||
|
const std::map<int, mapping::NodeId> &last_optimized_node_ids) {
|
||||||
|
auto response =
|
||||||
|
common::make_unique<proto::ReceiveGlobalSlamOptimizationsResponse>();
|
||||||
|
for (const auto &entry : last_optimized_submap_ids) {
|
||||||
|
entry.second.ToProto(
|
||||||
|
&(*response->mutable_last_optimized_submap_ids())[entry.first]);
|
||||||
|
}
|
||||||
|
for (const auto &entry : last_optimized_node_ids) {
|
||||||
|
entry.second.ToProto(
|
||||||
|
&(*response->mutable_last_optimized_node_ids())[entry.first]);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void ReceiveGlobalSlamOptimizationsHandler::OnRequest(
|
||||||
|
const google::protobuf::Empty &request) {
|
||||||
|
auto writer = GetWriter();
|
||||||
|
const int subscription_index =
|
||||||
|
GetUnsynchronizedContext<MapBuilderContextInterface>()
|
||||||
|
->SubscribeGlobalSlamOptimizations(
|
||||||
|
[writer](const std::map<int, mapping::SubmapId>
|
||||||
|
&last_optimized_submap_ids,
|
||||||
|
const std::map<int, mapping::NodeId>
|
||||||
|
&last_optimized_node_ids) {
|
||||||
|
if (!writer.Write(GenerateResponse(last_optimized_submap_ids,
|
||||||
|
last_optimized_node_ids))) {
|
||||||
|
// Client closed connection.
|
||||||
|
LOG(INFO) << "Client closed connection.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
LOG(INFO) << "Added subscription: " << subscription_index;
|
||||||
|
subscription_index_ = subscription_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReceiveGlobalSlamOptimizationsHandler::OnFinish() {
|
||||||
|
if (subscription_index_.has_value()) {
|
||||||
|
LOG(INFO) << "Removing subscription " << subscription_index_.value();
|
||||||
|
GetUnsynchronizedContext<MapBuilderContextInterface>()
|
||||||
|
->UnsubscribeGlobalSlamOptimizations(subscription_index_.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace handlers
|
||||||
|
} // namespace cloud
|
||||||
|
} // namespace cartographer
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 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.
|
||||||
|
*/
|
||||||
|
#ifndef CARTOGRAPHER_CLOUD_INTERNAL_HANDLERS_RECEIVE_GLOBAL_SLAM_OPTIMIZATIONS_HANDLER_H
|
||||||
|
#define CARTOGRAPHER_CLOUD_INTERNAL_HANDLERS_RECEIVE_GLOBAL_SLAM_OPTIMIZATIONS_HANDLER_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "async_grpc/rpc_handler.h"
|
||||||
|
#include "cartographer/cloud/internal/map_builder_context_interface.h"
|
||||||
|
#include "cartographer/cloud/proto/map_builder_service.pb.h"
|
||||||
|
|
||||||
|
namespace cartographer {
|
||||||
|
namespace cloud {
|
||||||
|
namespace handlers {
|
||||||
|
|
||||||
|
DEFINE_HANDLER_SIGNATURE(
|
||||||
|
ReceiveGlobalSlamOptimizationsSignature, google::protobuf::Empty,
|
||||||
|
async_grpc::Stream<proto::ReceiveGlobalSlamOptimizationsResponse>,
|
||||||
|
"/cartographer.cloud.proto.MapBuilderService/"
|
||||||
|
"ReceiveGlobalSlamOptimizations")
|
||||||
|
|
||||||
|
class ReceiveGlobalSlamOptimizationsHandler
|
||||||
|
: public async_grpc::RpcHandler<ReceiveGlobalSlamOptimizationsSignature> {
|
||||||
|
public:
|
||||||
|
void OnRequest(const google::protobuf::Empty &request) override;
|
||||||
|
void OnFinish() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
common::optional<int> subscription_index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace handlers
|
||||||
|
} // namespace cloud
|
||||||
|
} // namespace cartographer
|
||||||
|
|
||||||
|
#endif // CARTOGRAPHER_CLOUD_INTERNAL_HANDLERS_RECEIVE_GLOBAL_SLAM_OPTIMIZATIONS_HANDLER_H
|
|
@ -51,7 +51,7 @@ std::unique_ptr<proto::ReceiveLocalSlamResultsResponse> GenerateResponse(
|
||||||
void ReceiveLocalSlamResultsHandler::OnRequest(
|
void ReceiveLocalSlamResultsHandler::OnRequest(
|
||||||
const proto::ReceiveLocalSlamResultsRequest& request) {
|
const proto::ReceiveLocalSlamResultsRequest& request) {
|
||||||
auto writer = GetWriter();
|
auto writer = GetWriter();
|
||||||
MapBuilderContextInterface::SubscriptionId subscription_id =
|
MapBuilderContextInterface::LocalSlamSubscriptionId subscription_id =
|
||||||
GetUnsynchronizedContext<MapBuilderContextInterface>()
|
GetUnsynchronizedContext<MapBuilderContextInterface>()
|
||||||
->SubscribeLocalSlamResults(
|
->SubscribeLocalSlamResults(
|
||||||
request.trajectory_id(),
|
request.trajectory_id(),
|
||||||
|
@ -59,16 +59,22 @@ void ReceiveLocalSlamResultsHandler::OnRequest(
|
||||||
std::unique_ptr<MapBuilderContextInterface::LocalSlamResult>
|
std::unique_ptr<MapBuilderContextInterface::LocalSlamResult>
|
||||||
local_slam_result) {
|
local_slam_result) {
|
||||||
if (local_slam_result) {
|
if (local_slam_result) {
|
||||||
writer.Write(GenerateResponse(std::move(local_slam_result)));
|
if (!writer.Write(
|
||||||
|
GenerateResponse(std::move(local_slam_result)))) {
|
||||||
|
// Client closed connection.
|
||||||
|
LOG(INFO) << "Client closed connection.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Callback with 'nullptr' signals that the trajectory
|
// Callback with 'nullptr' signals that the trajectory
|
||||||
// finished.
|
// finished.
|
||||||
writer.WritesDone();
|
writer.WritesDone();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
subscription_id_ =
|
subscription_id_ =
|
||||||
common::make_unique<MapBuilderContextInterface::SubscriptionId>(
|
common::make_unique<MapBuilderContextInterface::LocalSlamSubscriptionId>(
|
||||||
subscription_id);
|
subscription_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,8 @@ class ReceiveLocalSlamResultsHandler
|
||||||
void OnFinish() override;
|
void OnFinish() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<MapBuilderContextInterface::SubscriptionId> subscription_id_;
|
std::unique_ptr<MapBuilderContextInterface::LocalSlamSubscriptionId>
|
||||||
|
subscription_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace handlers
|
} // namespace handlers
|
||||||
|
|
|
@ -61,7 +61,7 @@ void MapBuilderContext<SubmapType>::AddSensorDataToTrajectory(
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class SubmapType>
|
template <class SubmapType>
|
||||||
MapBuilderContextInterface::SubscriptionId
|
MapBuilderContextInterface::LocalSlamSubscriptionId
|
||||||
MapBuilderContext<SubmapType>::SubscribeLocalSlamResults(
|
MapBuilderContext<SubmapType>::SubscribeLocalSlamResults(
|
||||||
int trajectory_id, LocalSlamSubscriptionCallback callback) {
|
int trajectory_id, LocalSlamSubscriptionCallback callback) {
|
||||||
return map_builder_server_->SubscribeLocalSlamResults(trajectory_id,
|
return map_builder_server_->SubscribeLocalSlamResults(trajectory_id,
|
||||||
|
@ -70,10 +70,22 @@ MapBuilderContext<SubmapType>::SubscribeLocalSlamResults(
|
||||||
|
|
||||||
template <class SubmapType>
|
template <class SubmapType>
|
||||||
void MapBuilderContext<SubmapType>::UnsubscribeLocalSlamResults(
|
void MapBuilderContext<SubmapType>::UnsubscribeLocalSlamResults(
|
||||||
const SubscriptionId& subscription_id) {
|
const LocalSlamSubscriptionId& subscription_id) {
|
||||||
map_builder_server_->UnsubscribeLocalSlamResults(subscription_id);
|
map_builder_server_->UnsubscribeLocalSlamResults(subscription_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class SubmapType>
|
||||||
|
int MapBuilderContext<SubmapType>::SubscribeGlobalSlamOptimizations(
|
||||||
|
GlobalSlamOptimizationCallback callback) {
|
||||||
|
return map_builder_server_->SubscribeGlobalSlamOptimizations(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class SubmapType>
|
||||||
|
void MapBuilderContext<SubmapType>::UnsubscribeGlobalSlamOptimizations(
|
||||||
|
int subscription_index) {
|
||||||
|
map_builder_server_->UnsubscribeGlobalSlamOptimizations(subscription_index);
|
||||||
|
}
|
||||||
|
|
||||||
template <class SubmapType>
|
template <class SubmapType>
|
||||||
void MapBuilderContext<SubmapType>::NotifyFinishTrajectory(int trajectory_id) {
|
void MapBuilderContext<SubmapType>::NotifyFinishTrajectory(int trajectory_id) {
|
||||||
map_builder_server_->NotifyFinishTrajectory(trajectory_id);
|
map_builder_server_->NotifyFinishTrajectory(trajectory_id);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "cartographer/cloud/internal/local_trajectory_uploader.h"
|
#include "cartographer/cloud/internal/local_trajectory_uploader.h"
|
||||||
#include "cartographer/common/blocking_queue.h"
|
#include "cartographer/common/blocking_queue.h"
|
||||||
#include "cartographer/mapping/map_builder_interface.h"
|
#include "cartographer/mapping/map_builder_interface.h"
|
||||||
|
#include "cartographer/mapping/pose_graph_interface.h"
|
||||||
#include "cartographer/mapping/proto/serialization.pb.h"
|
#include "cartographer/mapping/proto/serialization.pb.h"
|
||||||
#include "cartographer/sensor/data.h"
|
#include "cartographer/sensor/data.h"
|
||||||
#include "cartographer/sensor/range_data.h"
|
#include "cartographer/sensor/range_data.h"
|
||||||
|
@ -40,14 +41,27 @@ class MapBuilderContextInterface : public async_grpc::ExecutionContext {
|
||||||
std::unique_ptr<const mapping::TrajectoryBuilderInterface::InsertionResult>
|
std::unique_ptr<const mapping::TrajectoryBuilderInterface::InsertionResult>
|
||||||
insertion_result;
|
insertion_result;
|
||||||
};
|
};
|
||||||
// Calling with 'nullptr' signals subscribers that the subscription has ended.
|
// Calling with 'nullptr' signals subscribers that the subscription has ended,
|
||||||
|
// e.g. this happens when the corresponding trajectory was finished and hence
|
||||||
|
// no more local SLAM updates will occur.
|
||||||
|
// The callback can return 'false' to indicate that the client is not
|
||||||
|
// interested in more local SLAM updates and 'MapBuilderServer' will end the
|
||||||
|
// subscription.
|
||||||
using LocalSlamSubscriptionCallback =
|
using LocalSlamSubscriptionCallback =
|
||||||
std::function<void(std::unique_ptr<LocalSlamResult>)>;
|
std::function<bool(std::unique_ptr<LocalSlamResult>)>;
|
||||||
|
|
||||||
|
// The callback can return 'false' to indicate that the client is not
|
||||||
|
// interested in more global SLAM runs and 'MapBuilderServer' will end the
|
||||||
|
// subscription.
|
||||||
|
using GlobalSlamOptimizationCallback = std::function<bool(
|
||||||
|
const std::map<int /* trajectory_id */, mapping::SubmapId>&,
|
||||||
|
const std::map<int /* trajectory_id */, mapping::NodeId>&)>;
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
int trajectory_id;
|
int trajectory_id;
|
||||||
std::unique_ptr<sensor::Data> data;
|
std::unique_ptr<sensor::Data> data;
|
||||||
};
|
};
|
||||||
struct SubscriptionId {
|
struct LocalSlamSubscriptionId {
|
||||||
const int trajectory_id;
|
const int trajectory_id;
|
||||||
const int subscription_index;
|
const int subscription_index;
|
||||||
};
|
};
|
||||||
|
@ -64,10 +78,13 @@ class MapBuilderContextInterface : public async_grpc::ExecutionContext {
|
||||||
virtual mapping::TrajectoryBuilderInterface::LocalSlamResultCallback
|
virtual mapping::TrajectoryBuilderInterface::LocalSlamResultCallback
|
||||||
GetLocalSlamResultCallbackForSubscriptions() = 0;
|
GetLocalSlamResultCallbackForSubscriptions() = 0;
|
||||||
virtual void AddSensorDataToTrajectory(const Data& sensor_data) = 0;
|
virtual void AddSensorDataToTrajectory(const Data& sensor_data) = 0;
|
||||||
virtual SubscriptionId SubscribeLocalSlamResults(
|
virtual LocalSlamSubscriptionId SubscribeLocalSlamResults(
|
||||||
int trajectory_id, LocalSlamSubscriptionCallback callback) = 0;
|
int trajectory_id, LocalSlamSubscriptionCallback callback) = 0;
|
||||||
virtual void UnsubscribeLocalSlamResults(
|
virtual void UnsubscribeLocalSlamResults(
|
||||||
const SubscriptionId& subscription_id) = 0;
|
const LocalSlamSubscriptionId& subscription_id) = 0;
|
||||||
|
virtual int SubscribeGlobalSlamOptimizations(
|
||||||
|
GlobalSlamOptimizationCallback callback) = 0;
|
||||||
|
virtual void UnsubscribeGlobalSlamOptimizations(int subscription_index) = 0;
|
||||||
virtual void NotifyFinishTrajectory(int trajectory_id) = 0;
|
virtual void NotifyFinishTrajectory(int trajectory_id) = 0;
|
||||||
virtual LocalTrajectoryUploaderInterface* local_trajectory_uploader() = 0;
|
virtual LocalTrajectoryUploaderInterface* local_trajectory_uploader() = 0;
|
||||||
virtual void EnqueueSensorData(int trajectory_id,
|
virtual void EnqueueSensorData(int trajectory_id,
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "cartographer/cloud/internal/handlers/is_trajectory_finished_handler.h"
|
#include "cartographer/cloud/internal/handlers/is_trajectory_finished_handler.h"
|
||||||
#include "cartographer/cloud/internal/handlers/is_trajectory_frozen_handler.h"
|
#include "cartographer/cloud/internal/handlers/is_trajectory_frozen_handler.h"
|
||||||
#include "cartographer/cloud/internal/handlers/load_state_handler.h"
|
#include "cartographer/cloud/internal/handlers/load_state_handler.h"
|
||||||
|
#include "cartographer/cloud/internal/handlers/receive_global_slam_optimizations_handler.h"
|
||||||
#include "cartographer/cloud/internal/handlers/receive_local_slam_results_handler.h"
|
#include "cartographer/cloud/internal/handlers/receive_local_slam_results_handler.h"
|
||||||
#include "cartographer/cloud/internal/handlers/run_final_optimization_handler.h"
|
#include "cartographer/cloud/internal/handlers/run_final_optimization_handler.h"
|
||||||
#include "cartographer/cloud/internal/handlers/set_landmark_pose_handler.h"
|
#include "cartographer/cloud/internal/handlers/set_landmark_pose_handler.h"
|
||||||
|
@ -73,6 +74,8 @@ MapBuilderServer::MapBuilderServer(
|
||||||
server_builder.RegisterHandler<handlers::AddLandmarkDataHandler>();
|
server_builder.RegisterHandler<handlers::AddLandmarkDataHandler>();
|
||||||
server_builder.RegisterHandler<handlers::AddSensorDataBatchHandler>();
|
server_builder.RegisterHandler<handlers::AddSensorDataBatchHandler>();
|
||||||
server_builder.RegisterHandler<handlers::FinishTrajectoryHandler>();
|
server_builder.RegisterHandler<handlers::FinishTrajectoryHandler>();
|
||||||
|
server_builder
|
||||||
|
.RegisterHandler<handlers::ReceiveGlobalSlamOptimizationsHandler>();
|
||||||
server_builder.RegisterHandler<handlers::ReceiveLocalSlamResultsHandler>();
|
server_builder.RegisterHandler<handlers::ReceiveLocalSlamResultsHandler>();
|
||||||
server_builder.RegisterHandler<handlers::GetSubmapHandler>();
|
server_builder.RegisterHandler<handlers::GetSubmapHandler>();
|
||||||
server_builder.RegisterHandler<handlers::GetTrajectoryNodePosesHandler>();
|
server_builder.RegisterHandler<handlers::GetTrajectoryNodePosesHandler>();
|
||||||
|
@ -99,6 +102,9 @@ MapBuilderServer::MapBuilderServer(
|
||||||
LOG(FATAL)
|
LOG(FATAL)
|
||||||
<< "Set either use_trajectory_builder_2d or use_trajectory_builder_3d";
|
<< "Set either use_trajectory_builder_2d or use_trajectory_builder_3d";
|
||||||
}
|
}
|
||||||
|
map_builder_->pose_graph()->SetGlobalSlamOptimizationCallback(
|
||||||
|
std::bind(&MapBuilderServer::OnGlobalSlamOptimizations, this,
|
||||||
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapBuilderServer::Start() {
|
void MapBuilderServer::Start() {
|
||||||
|
@ -184,7 +190,7 @@ void MapBuilderServer::OnLocalSlamResult(
|
||||||
->EnqueueSensorData(std::move(sensor_data));
|
->EnqueueSensorData(std::move(sensor_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
common::MutexLocker locker(&local_slam_subscriptions_lock_);
|
common::MutexLocker locker(&subscriptions_lock_);
|
||||||
for (auto& entry : local_slam_subscriptions_[trajectory_id]) {
|
for (auto& entry : local_slam_subscriptions_[trajectory_id]) {
|
||||||
auto copy_of_insertion_result =
|
auto copy_of_insertion_result =
|
||||||
insertion_result
|
insertion_result
|
||||||
|
@ -194,34 +200,64 @@ void MapBuilderServer::OnLocalSlamResult(
|
||||||
: nullptr;
|
: nullptr;
|
||||||
MapBuilderContextInterface::LocalSlamSubscriptionCallback callback =
|
MapBuilderContextInterface::LocalSlamSubscriptionCallback callback =
|
||||||
entry.second;
|
entry.second;
|
||||||
callback(common::make_unique<MapBuilderContextInterface::LocalSlamResult>(
|
if (!callback(
|
||||||
|
common::make_unique<MapBuilderContextInterface::LocalSlamResult>(
|
||||||
MapBuilderContextInterface::LocalSlamResult{
|
MapBuilderContextInterface::LocalSlamResult{
|
||||||
trajectory_id, time, local_pose, shared_range_data,
|
trajectory_id, time, local_pose, shared_range_data,
|
||||||
std::move(copy_of_insertion_result)}));
|
std::move(copy_of_insertion_result)}))) {
|
||||||
|
LOG(INFO) << "Removing subscription with index: " << entry.first;
|
||||||
|
CHECK_EQ(local_slam_subscriptions_[trajectory_id].erase(entry.first), 1u);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBuilderContextInterface::SubscriptionId
|
void MapBuilderServer::OnGlobalSlamOptimizations(
|
||||||
|
const std::map<int, mapping::SubmapId>& last_optimized_submap_ids,
|
||||||
|
const std::map<int, mapping::NodeId>& last_optimized_node_ids) {
|
||||||
|
common::MutexLocker locker(&subscriptions_lock_);
|
||||||
|
for (auto& entry : global_slam_subscriptions_) {
|
||||||
|
if (!entry.second(last_optimized_submap_ids, last_optimized_node_ids)) {
|
||||||
|
LOG(INFO) << "Removing subscription with index: " << entry.first;
|
||||||
|
CHECK_EQ(global_slam_subscriptions_.erase(entry.first), 1u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MapBuilderContextInterface::LocalSlamSubscriptionId
|
||||||
MapBuilderServer::SubscribeLocalSlamResults(
|
MapBuilderServer::SubscribeLocalSlamResults(
|
||||||
int trajectory_id,
|
int trajectory_id,
|
||||||
MapBuilderContextInterface::LocalSlamSubscriptionCallback callback) {
|
MapBuilderContextInterface::LocalSlamSubscriptionCallback callback) {
|
||||||
common::MutexLocker locker(&local_slam_subscriptions_lock_);
|
common::MutexLocker locker(&subscriptions_lock_);
|
||||||
local_slam_subscriptions_[trajectory_id].emplace(current_subscription_index_,
|
local_slam_subscriptions_[trajectory_id].emplace(current_subscription_index_,
|
||||||
callback);
|
callback);
|
||||||
return MapBuilderContextInterface::SubscriptionId{
|
return MapBuilderContextInterface::LocalSlamSubscriptionId{
|
||||||
trajectory_id, current_subscription_index_++};
|
trajectory_id, current_subscription_index_++};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapBuilderServer::UnsubscribeLocalSlamResults(
|
void MapBuilderServer::UnsubscribeLocalSlamResults(
|
||||||
const MapBuilderContextInterface::SubscriptionId& subscription_id) {
|
const MapBuilderContextInterface::LocalSlamSubscriptionId&
|
||||||
common::MutexLocker locker(&local_slam_subscriptions_lock_);
|
subscription_id) {
|
||||||
|
common::MutexLocker locker(&subscriptions_lock_);
|
||||||
CHECK_EQ(local_slam_subscriptions_[subscription_id.trajectory_id].erase(
|
CHECK_EQ(local_slam_subscriptions_[subscription_id.trajectory_id].erase(
|
||||||
subscription_id.subscription_index),
|
subscription_id.subscription_index),
|
||||||
1u);
|
1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MapBuilderServer::SubscribeGlobalSlamOptimizations(
|
||||||
|
MapBuilderContextInterface::GlobalSlamOptimizationCallback callback) {
|
||||||
|
common::MutexLocker locker(&subscriptions_lock_);
|
||||||
|
global_slam_subscriptions_.emplace(current_subscription_index_, callback);
|
||||||
|
return current_subscription_index_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapBuilderServer::UnsubscribeGlobalSlamOptimizations(
|
||||||
|
int subscription_index) {
|
||||||
|
common::MutexLocker locker(&subscriptions_lock_);
|
||||||
|
CHECK_EQ(global_slam_subscriptions_.erase(subscription_index), 1u);
|
||||||
|
}
|
||||||
|
|
||||||
void MapBuilderServer::NotifyFinishTrajectory(int trajectory_id) {
|
void MapBuilderServer::NotifyFinishTrajectory(int trajectory_id) {
|
||||||
common::MutexLocker locker(&local_slam_subscriptions_lock_);
|
common::MutexLocker locker(&subscriptions_lock_);
|
||||||
for (auto& entry : local_slam_subscriptions_[trajectory_id]) {
|
for (auto& entry : local_slam_subscriptions_[trajectory_id]) {
|
||||||
MapBuilderContextInterface::LocalSlamSubscriptionCallback callback =
|
MapBuilderContextInterface::LocalSlamSubscriptionCallback callback =
|
||||||
entry.second;
|
entry.second;
|
||||||
|
|
|
@ -49,10 +49,13 @@ class MapBuilderContext : public MapBuilderContextInterface {
|
||||||
mapping::TrajectoryBuilderInterface::LocalSlamResultCallback
|
mapping::TrajectoryBuilderInterface::LocalSlamResultCallback
|
||||||
GetLocalSlamResultCallbackForSubscriptions() override;
|
GetLocalSlamResultCallbackForSubscriptions() override;
|
||||||
void AddSensorDataToTrajectory(const Data& sensor_data) override;
|
void AddSensorDataToTrajectory(const Data& sensor_data) override;
|
||||||
MapBuilderContextInterface::SubscriptionId SubscribeLocalSlamResults(
|
MapBuilderContextInterface::LocalSlamSubscriptionId SubscribeLocalSlamResults(
|
||||||
int trajectory_id, LocalSlamSubscriptionCallback callback) override;
|
int trajectory_id, LocalSlamSubscriptionCallback callback) override;
|
||||||
void UnsubscribeLocalSlamResults(
|
void UnsubscribeLocalSlamResults(
|
||||||
const SubscriptionId& subscription_id) override;
|
const LocalSlamSubscriptionId& subscription_id) override;
|
||||||
|
int SubscribeGlobalSlamOptimizations(
|
||||||
|
GlobalSlamOptimizationCallback callback) override;
|
||||||
|
void UnsubscribeGlobalSlamOptimizations(int subscription_index) override;
|
||||||
void NotifyFinishTrajectory(int trajectory_id) override;
|
void NotifyFinishTrajectory(int trajectory_id) override;
|
||||||
LocalTrajectoryUploaderInterface* local_trajectory_uploader() override;
|
LocalTrajectoryUploaderInterface* local_trajectory_uploader() override;
|
||||||
void EnqueueSensorData(int trajectory_id,
|
void EnqueueSensorData(int trajectory_id,
|
||||||
|
@ -107,11 +110,18 @@ class MapBuilderServer : public MapBuilderServerInterface {
|
||||||
std::unique_ptr<
|
std::unique_ptr<
|
||||||
const mapping::TrajectoryBuilderInterface::InsertionResult>
|
const mapping::TrajectoryBuilderInterface::InsertionResult>
|
||||||
insertion_result);
|
insertion_result);
|
||||||
MapBuilderContextInterface::SubscriptionId SubscribeLocalSlamResults(
|
void OnGlobalSlamOptimizations(
|
||||||
|
const std::map<int, mapping::SubmapId>& last_optimized_submap_ids,
|
||||||
|
const std::map<int, mapping::NodeId>& last_optimized_node_ids);
|
||||||
|
MapBuilderContextInterface::LocalSlamSubscriptionId SubscribeLocalSlamResults(
|
||||||
int trajectory_id,
|
int trajectory_id,
|
||||||
MapBuilderContextInterface::LocalSlamSubscriptionCallback callback);
|
MapBuilderContextInterface::LocalSlamSubscriptionCallback callback);
|
||||||
void UnsubscribeLocalSlamResults(
|
void UnsubscribeLocalSlamResults(
|
||||||
const MapBuilderContextInterface::SubscriptionId& subscription_id);
|
const MapBuilderContextInterface::LocalSlamSubscriptionId&
|
||||||
|
subscription_id);
|
||||||
|
int SubscribeGlobalSlamOptimizations(
|
||||||
|
MapBuilderContextInterface::GlobalSlamOptimizationCallback callback);
|
||||||
|
void UnsubscribeGlobalSlamOptimizations(int subscription_index);
|
||||||
void NotifyFinishTrajectory(int trajectory_id);
|
void NotifyFinishTrajectory(int trajectory_id);
|
||||||
|
|
||||||
bool shutting_down_ = false;
|
bool shutting_down_ = false;
|
||||||
|
@ -120,10 +130,13 @@ class MapBuilderServer : public MapBuilderServerInterface {
|
||||||
std::unique_ptr<mapping::MapBuilderInterface> map_builder_;
|
std::unique_ptr<mapping::MapBuilderInterface> map_builder_;
|
||||||
common::BlockingQueue<std::unique_ptr<MapBuilderContextInterface::Data>>
|
common::BlockingQueue<std::unique_ptr<MapBuilderContextInterface::Data>>
|
||||||
incoming_data_queue_;
|
incoming_data_queue_;
|
||||||
common::Mutex local_slam_subscriptions_lock_;
|
common::Mutex subscriptions_lock_;
|
||||||
int current_subscription_index_ = 0;
|
int current_subscription_index_ = 0;
|
||||||
std::map<int /* trajectory ID */, LocalSlamResultHandlerSubscriptions>
|
std::map<int /* trajectory ID */, LocalSlamResultHandlerSubscriptions>
|
||||||
local_slam_subscriptions_ GUARDED_BY(local_slam_subscriptions_lock_);
|
local_slam_subscriptions_ GUARDED_BY(subscriptions_lock_);
|
||||||
|
std::map<int /* subscription_index */,
|
||||||
|
MapBuilderContextInterface::GlobalSlamOptimizationCallback>
|
||||||
|
global_slam_subscriptions_ GUARDED_BY(subscriptions_lock_);
|
||||||
std::unique_ptr<LocalTrajectoryUploaderInterface> local_trajectory_uploader_;
|
std::unique_ptr<LocalTrajectoryUploaderInterface> local_trajectory_uploader_;
|
||||||
int starting_submap_index_ = 0;
|
int starting_submap_index_ = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,11 +39,15 @@ class MockMapBuilderContext : public MapBuilderContextInterface {
|
||||||
MOCK_METHOD1(AddSensorDataToTrajectory,
|
MOCK_METHOD1(AddSensorDataToTrajectory,
|
||||||
void(const MapBuilderContextInterface::Data &));
|
void(const MapBuilderContextInterface::Data &));
|
||||||
MOCK_METHOD2(SubscribeLocalSlamResults,
|
MOCK_METHOD2(SubscribeLocalSlamResults,
|
||||||
MapBuilderContextInterface::SubscriptionId(
|
MapBuilderContextInterface::LocalSlamSubscriptionId(
|
||||||
int,
|
int,
|
||||||
MapBuilderContextInterface::LocalSlamSubscriptionCallback));
|
MapBuilderContextInterface::LocalSlamSubscriptionCallback));
|
||||||
MOCK_METHOD1(UnsubscribeLocalSlamResults,
|
MOCK_METHOD1(
|
||||||
void(const MapBuilderContextInterface::SubscriptionId &));
|
UnsubscribeLocalSlamResults,
|
||||||
|
void(const MapBuilderContextInterface::LocalSlamSubscriptionId &));
|
||||||
|
MOCK_METHOD1(SubscribeGlobalSlamOptimizations,
|
||||||
|
int(GlobalSlamOptimizationCallback));
|
||||||
|
MOCK_METHOD1(UnsubscribeGlobalSlamOptimizations, void(int));
|
||||||
MOCK_METHOD1(NotifyFinishTrajectory, void(int));
|
MOCK_METHOD1(NotifyFinishTrajectory, void(int));
|
||||||
MOCK_METHOD0(local_trajectory_uploader, LocalTrajectoryUploaderInterface *());
|
MOCK_METHOD0(local_trajectory_uploader, LocalTrajectoryUploaderInterface *());
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,13 @@ message ReceiveLocalSlamResultsResponse {
|
||||||
LocalSlamInsertionResult insertion_result = 5;
|
LocalSlamInsertionResult insertion_result = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ReceiveGlobalSlamOptimizationsResponse {
|
||||||
|
map<int32 /* trajectory_id */, cartographer.mapping.proto.NodeId>
|
||||||
|
last_optimized_node_ids = 1;
|
||||||
|
map<int32 /* trajectory_id */, cartographer.mapping.proto.SubmapId>
|
||||||
|
last_optimized_submap_ids = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message GetSubmapRequest {
|
message GetSubmapRequest {
|
||||||
cartographer.mapping.proto.SubmapId submap_id = 1;
|
cartographer.mapping.proto.SubmapId submap_id = 1;
|
||||||
}
|
}
|
||||||
|
@ -230,6 +237,10 @@ service MapBuilderService {
|
||||||
rpc ReceiveLocalSlamResults(ReceiveLocalSlamResultsRequest)
|
rpc ReceiveLocalSlamResults(ReceiveLocalSlamResultsRequest)
|
||||||
returns (stream ReceiveLocalSlamResultsResponse);
|
returns (stream ReceiveLocalSlamResultsResponse);
|
||||||
|
|
||||||
|
// Requests the server to send a stream of global SLAM notifications.
|
||||||
|
rpc ReceiveGlobalSlamOptimizations(google.protobuf.Empty)
|
||||||
|
returns (stream ReceiveGlobalSlamOptimizationsResponse);
|
||||||
|
|
||||||
// Marks a trajectory corresponding to 'trajectory_id' as finished,
|
// Marks a trajectory corresponding to 'trajectory_id' as finished,
|
||||||
// i.e. no further sensor data is expected.
|
// i.e. no further sensor data is expected.
|
||||||
rpc FinishTrajectory(FinishTrajectoryRequest) returns (google.protobuf.Empty);
|
rpc FinishTrajectory(FinishTrajectoryRequest) returns (google.protobuf.Empty);
|
||||||
|
|
Loading…
Reference in New Issue