00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <condition_variable>
00018 #include <mutex>
00019
00020 #include "cartographer/cloud/client/map_builder_stub.h"
00021 #include "cartographer/cloud/internal/map_builder_server.h"
00022 #include "cartographer/cloud/map_builder_server_options.h"
00023 #include "cartographer/io/internal/in_memory_proto_stream.h"
00024 #include "cartographer/io/proto_stream.h"
00025 #include "cartographer/io/proto_stream_deserializer.h"
00026 #include "cartographer/io/testing/test_helpers.h"
00027 #include "cartographer/mapping/internal/testing/mock_map_builder.h"
00028 #include "cartographer/mapping/internal/testing/mock_pose_graph.h"
00029 #include "cartographer/mapping/internal/testing/mock_trajectory_builder.h"
00030 #include "cartographer/mapping/internal/testing/test_helpers.h"
00031 #include "cartographer/mapping/local_slam_result_data.h"
00032 #include "glog/logging.h"
00033 #include "gmock/gmock.h"
00034 #include "gtest/gtest.h"
00035
00036 using ::cartographer::io::testing::ProtoReaderFromStrings;
00037 using ::cartographer::mapping::MapBuilder;
00038 using ::cartographer::mapping::MapBuilderInterface;
00039 using ::cartographer::mapping::PoseGraphInterface;
00040 using ::cartographer::mapping::TrajectoryBuilderInterface;
00041 using ::cartographer::mapping::testing::MockMapBuilder;
00042 using ::cartographer::mapping::testing::MockPoseGraph;
00043 using ::cartographer::mapping::testing::MockTrajectoryBuilder;
00044 using ::testing::_;
00045 using SensorId = ::cartographer::mapping::TrajectoryBuilderInterface::SensorId;
00046
00047 namespace cartographer {
00048 namespace cloud {
00049 namespace {
00050
00051 constexpr char kClientId[] = "CLIENT_ID";
00052 const SensorId kImuSensorId{SensorId::SensorType::IMU, "imu"};
00053 const SensorId kRangeSensorId{SensorId::SensorType::RANGE, "range"};
00054 constexpr double kDuration = 4.;
00055 constexpr double kTimeStep = 0.1;
00056 constexpr double kTravelDistance = 1.2;
00057
00058 constexpr char kSerializationHeaderProtoString[] = "format_version: 1";
00059 constexpr char kPoseGraphProtoString[] = R"(pose_graph {
00060 trajectory: {
00061 trajectory_id: 0
00062 node: {}
00063 submap: {}
00064 }
00065 })";
00066 constexpr char kAllTrajectoryBuilderOptionsProtoString[] =
00067 R"(all_trajectory_builder_options {
00068 options_with_sensor_ids: {}
00069 })";
00070 constexpr char kSubmapProtoString[] = "submap {}";
00071 constexpr char kNodeProtoString[] = "node {}";
00072 constexpr char kTrajectoryDataProtoString[] = "trajectory_data {}";
00073 constexpr char kImuDataProtoString[] = "imu_data {}";
00074 constexpr char kOdometryDataProtoString[] = "odometry_data {}";
00075 constexpr char kFixedFramePoseDataProtoString[] = "fixed_frame_pose_data {}";
00076 constexpr char kLandmarkDataProtoString[] = "landmark_data {}";
00077
00078 template <class T>
00079 class ClientServerTestBase : public T {
00080 protected:
00081 void SetUp() override {
00082
00083
00084 const std::string kMapBuilderServerLua = R"text(
00085 include "map_builder_server.lua"
00086 MAP_BUILDER.use_trajectory_builder_2d = true
00087 MAP_BUILDER.pose_graph.optimize_every_n_nodes = 0
00088 MAP_BUILDER_SERVER.num_event_threads = 1
00089 MAP_BUILDER_SERVER.num_grpc_threads = 1
00090 MAP_BUILDER_SERVER.uplink_server_address = ""
00091 MAP_BUILDER_SERVER.server_address = "0.0.0.0:50051"
00092 return MAP_BUILDER_SERVER)text";
00093 auto map_builder_server_parameters =
00094 mapping::testing::ResolveLuaParameters(kMapBuilderServerLua);
00095 map_builder_server_options_ =
00096 CreateMapBuilderServerOptions(map_builder_server_parameters.get());
00097
00098 const std::string kUploadingMapBuilderServerLua = R"text(
00099 include "map_builder_server.lua"
00100 MAP_BUILDER.use_trajectory_builder_2d = true
00101 MAP_BUILDER.pose_graph.optimize_every_n_nodes = 0
00102 MAP_BUILDER_SERVER.num_event_threads = 1
00103 MAP_BUILDER_SERVER.num_grpc_threads = 1
00104 MAP_BUILDER_SERVER.uplink_server_address = "localhost:50051"
00105 MAP_BUILDER_SERVER.server_address = "0.0.0.0:50052"
00106 MAP_BUILDER_SERVER.upload_batch_size = 1
00107 return MAP_BUILDER_SERVER)text";
00108 auto uploading_map_builder_server_parameters =
00109 mapping::testing::ResolveLuaParameters(kUploadingMapBuilderServerLua);
00110 uploading_map_builder_server_options_ = CreateMapBuilderServerOptions(
00111 uploading_map_builder_server_parameters.get());
00112 EXPECT_NE(map_builder_server_options_.server_address(),
00113 uploading_map_builder_server_options_.server_address());
00114
00115 const std::string kTrajectoryBuilderLua = R"text(
00116 include "trajectory_builder.lua"
00117 TRAJECTORY_BUILDER.trajectory_builder_2d.use_imu_data = false
00118 TRAJECTORY_BUILDER.trajectory_builder_2d.submaps.num_range_data = 4
00119 return TRAJECTORY_BUILDER)text";
00120 auto trajectory_builder_parameters =
00121 mapping::testing::ResolveLuaParameters(kTrajectoryBuilderLua);
00122 trajectory_builder_options_ = mapping::CreateTrajectoryBuilderOptions(
00123 trajectory_builder_parameters.get());
00124 number_of_insertion_results_ = 0;
00125 local_slam_result_callback_ =
00126 [this](int, common::Time, transform::Rigid3d local_pose,
00127 sensor::RangeData,
00128 std::unique_ptr<
00129 const mapping::TrajectoryBuilderInterface::InsertionResult>
00130 insertion_result) {
00131 std::unique_lock<std::mutex> lock(local_slam_result_mutex_);
00132 if (insertion_result) {
00133 ++number_of_insertion_results_;
00134 }
00135 local_slam_result_poses_.push_back(local_pose);
00136 lock.unlock();
00137 local_slam_result_condition_.notify_all();
00138 };
00139 }
00140
00141 void InitializeRealServer() {
00142 auto map_builder = absl::make_unique<MapBuilder>(
00143 map_builder_server_options_.map_builder_options());
00144 server_ = absl::make_unique<MapBuilderServer>(map_builder_server_options_,
00145 std::move(map_builder));
00146 EXPECT_TRUE(server_ != nullptr);
00147 }
00148
00149 void InitializeRealUploadingServer() {
00150 auto map_builder = absl::make_unique<MapBuilder>(
00151 uploading_map_builder_server_options_.map_builder_options());
00152 uploading_server_ = absl::make_unique<MapBuilderServer>(
00153 uploading_map_builder_server_options_, std::move(map_builder));
00154 EXPECT_TRUE(uploading_server_ != nullptr);
00155 }
00156
00157 void InitializeServerWithMockMapBuilder() {
00158 auto mock_map_builder = absl::make_unique<MockMapBuilder>();
00159 mock_map_builder_ = mock_map_builder.get();
00160 mock_pose_graph_ = absl::make_unique<MockPoseGraph>();
00161 EXPECT_CALL(*mock_map_builder_, pose_graph())
00162 .WillOnce(::testing::Return(mock_pose_graph_.get()));
00163 EXPECT_CALL(*mock_pose_graph_, SetGlobalSlamOptimizationCallback(_));
00164 server_ = absl::make_unique<MapBuilderServer>(map_builder_server_options_,
00165 std::move(mock_map_builder));
00166 EXPECT_TRUE(server_ != nullptr);
00167 mock_trajectory_builder_ = absl::make_unique<MockTrajectoryBuilder>();
00168 }
00169
00170 void InitializeStub() {
00171 stub_ = absl::make_unique<MapBuilderStub>(
00172 map_builder_server_options_.server_address(), kClientId);
00173 EXPECT_TRUE(stub_ != nullptr);
00174 }
00175
00176 void InitializeStubForUploadingServer() {
00177 stub_for_uploading_server_ = absl::make_unique<MapBuilderStub>(
00178 uploading_map_builder_server_options_.server_address(), kClientId);
00179 EXPECT_TRUE(stub_for_uploading_server_ != nullptr);
00180 }
00181
00182 void SetOptionsToTSDF2D() {
00183 trajectory_builder_options_.mutable_trajectory_builder_2d_options()
00184 ->mutable_submaps_options()
00185 ->mutable_range_data_inserter_options()
00186 ->set_range_data_inserter_type(
00187 ::cartographer::mapping::proto::RangeDataInserterOptions::
00188 TSDF_INSERTER_2D);
00189 trajectory_builder_options_.mutable_trajectory_builder_2d_options()
00190 ->mutable_submaps_options()
00191 ->mutable_grid_options_2d()
00192 ->set_grid_type(::cartographer::mapping::proto::GridOptions2D::TSDF);
00193 trajectory_builder_options_.mutable_trajectory_builder_2d_options()
00194 ->mutable_ceres_scan_matcher_options()
00195 ->set_occupied_space_weight(10.0);
00196 map_builder_server_options_.mutable_map_builder_options()
00197 ->mutable_pose_graph_options()
00198 ->mutable_constraint_builder_options()
00199 ->mutable_ceres_scan_matcher_options()
00200 ->set_occupied_space_weight(50.0);
00201 uploading_map_builder_server_options_.mutable_map_builder_options()
00202 ->mutable_pose_graph_options()
00203 ->mutable_constraint_builder_options()
00204 ->mutable_ceres_scan_matcher_options()
00205 ->set_occupied_space_weight(50.0);
00206 }
00207
00208 void WaitForLocalSlamResults(size_t size) {
00209 std::unique_lock<std::mutex> lock(local_slam_result_mutex_);
00210 local_slam_result_condition_.wait(
00211 lock, [&] { return local_slam_result_poses_.size() >= size; });
00212 }
00213
00214 void WaitForLocalSlamResultUploads(size_t size) {
00215 while (stub_->pose_graph()->GetTrajectoryNodePoses().size() < size) {
00216 std::this_thread::sleep_for(std::chrono::milliseconds(100));
00217 }
00218 }
00219
00220 proto::MapBuilderServerOptions map_builder_server_options_;
00221 proto::MapBuilderServerOptions uploading_map_builder_server_options_;
00222 MockMapBuilder* mock_map_builder_;
00223 std::unique_ptr<MockPoseGraph> mock_pose_graph_;
00224 std::unique_ptr<MockTrajectoryBuilder> mock_trajectory_builder_;
00225 ::cartographer::mapping::proto::TrajectoryBuilderOptions
00226 trajectory_builder_options_;
00227 std::unique_ptr<MapBuilderServer> server_;
00228 std::unique_ptr<MapBuilderServer> uploading_server_;
00229 std::unique_ptr<MapBuilderStub> stub_;
00230 std::unique_ptr<MapBuilderStub> stub_for_uploading_server_;
00231 TrajectoryBuilderInterface::LocalSlamResultCallback
00232 local_slam_result_callback_;
00233 std::condition_variable local_slam_result_condition_;
00234 std::condition_variable local_slam_result_upload_condition_;
00235 std::mutex local_slam_result_mutex_;
00236 std::mutex local_slam_result_upload_mutex_;
00237 std::vector<transform::Rigid3d> local_slam_result_poses_;
00238 int number_of_insertion_results_;
00239 };
00240
00241 class ClientServerTest : public ClientServerTestBase<::testing::Test> {};
00242 class ClientServerTestByGridType
00243 : public ClientServerTestBase<
00244 ::testing::TestWithParam<::cartographer::mapping::GridType>> {};
00245
00246 INSTANTIATE_TEST_CASE_P(
00247 ClientServerTestByGridType, ClientServerTestByGridType,
00248 ::testing::Values(::cartographer::mapping::GridType::PROBABILITY_GRID,
00249 ::cartographer::mapping::GridType::TSDF));
00250
00251 TEST_F(ClientServerTest, StartAndStopServer) {
00252 InitializeRealServer();
00253 server_->Start();
00254 server_->Shutdown();
00255 }
00256
00257 TEST_P(ClientServerTestByGridType, AddTrajectoryBuilder) {
00258 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00259 SetOptionsToTSDF2D();
00260 }
00261 InitializeRealServer();
00262 server_->Start();
00263 InitializeStub();
00264 int trajectory_id = stub_->AddTrajectoryBuilder(
00265 {kImuSensorId}, trajectory_builder_options_, nullptr);
00266 EXPECT_FALSE(stub_->pose_graph()->IsTrajectoryFinished(trajectory_id));
00267 stub_->FinishTrajectory(trajectory_id);
00268 EXPECT_TRUE(stub_->pose_graph()->IsTrajectoryFinished(trajectory_id));
00269 EXPECT_FALSE(stub_->pose_graph()->IsTrajectoryFrozen(trajectory_id));
00270 server_->Shutdown();
00271 }
00272
00273 TEST_P(ClientServerTestByGridType, AddTrajectoryBuilderWithMock) {
00274 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00275 SetOptionsToTSDF2D();
00276 }
00277 InitializeServerWithMockMapBuilder();
00278 server_->Start();
00279 InitializeStub();
00280 std::set<SensorId> expected_sensor_ids = {kImuSensorId};
00281 EXPECT_CALL(
00282 *mock_map_builder_,
00283 AddTrajectoryBuilder(::testing::ContainerEq(expected_sensor_ids), _, _))
00284 .WillOnce(::testing::Return(3));
00285 EXPECT_CALL(*mock_map_builder_, GetTrajectoryBuilder(_))
00286 .WillRepeatedly(::testing::Return(nullptr));
00287 int trajectory_id = stub_->AddTrajectoryBuilder(
00288 expected_sensor_ids, trajectory_builder_options_, nullptr);
00289 EXPECT_EQ(trajectory_id, 3);
00290 EXPECT_CALL(*mock_map_builder_, FinishTrajectory(trajectory_id));
00291 stub_->FinishTrajectory(trajectory_id);
00292 server_->Shutdown();
00293 }
00294
00295 TEST_P(ClientServerTestByGridType, AddSensorData) {
00296 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00297 SetOptionsToTSDF2D();
00298 }
00299 trajectory_builder_options_.mutable_trajectory_builder_2d_options()
00300 ->set_use_imu_data(true);
00301 InitializeRealServer();
00302 server_->Start();
00303 InitializeStub();
00304 int trajectory_id = stub_->AddTrajectoryBuilder(
00305 {kImuSensorId}, trajectory_builder_options_, nullptr);
00306 TrajectoryBuilderInterface* trajectory_stub =
00307 stub_->GetTrajectoryBuilder(trajectory_id);
00308 sensor::ImuData imu_data{common::FromUniversal(42),
00309 Eigen::Vector3d(0., 0., 9.8),
00310 Eigen::Vector3d::Zero()};
00311 trajectory_stub->AddSensorData(kImuSensorId.id, imu_data);
00312 stub_->FinishTrajectory(trajectory_id);
00313 server_->Shutdown();
00314 }
00315
00316 TEST_P(ClientServerTestByGridType, AddSensorDataWithMock) {
00317 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00318 SetOptionsToTSDF2D();
00319 }
00320 InitializeServerWithMockMapBuilder();
00321 server_->Start();
00322 InitializeStub();
00323 std::set<SensorId> expected_sensor_ids = {kImuSensorId};
00324 EXPECT_CALL(
00325 *mock_map_builder_,
00326 AddTrajectoryBuilder(::testing::ContainerEq(expected_sensor_ids), _, _))
00327 .WillOnce(::testing::Return(3));
00328 int trajectory_id = stub_->AddTrajectoryBuilder(
00329 expected_sensor_ids, trajectory_builder_options_, nullptr);
00330 EXPECT_EQ(trajectory_id, 3);
00331 EXPECT_CALL(*mock_map_builder_, GetTrajectoryBuilder(_))
00332 .WillRepeatedly(::testing::Return(mock_trajectory_builder_.get()));
00333 mapping::TrajectoryBuilderInterface* trajectory_stub =
00334 stub_->GetTrajectoryBuilder(trajectory_id);
00335 sensor::ImuData imu_data{common::FromUniversal(42),
00336 Eigen::Vector3d(0., 0., 9.8),
00337 Eigen::Vector3d::Zero()};
00338 EXPECT_CALL(*mock_trajectory_builder_,
00339 AddSensorData(::testing::StrEq(kImuSensorId.id),
00340 ::testing::Matcher<const sensor::ImuData&>(_)))
00341 .WillOnce(::testing::Return());
00342 trajectory_stub->AddSensorData(kImuSensorId.id, imu_data);
00343 EXPECT_CALL(*mock_map_builder_, FinishTrajectory(trajectory_id));
00344 stub_->FinishTrajectory(trajectory_id);
00345 server_->Shutdown();
00346 }
00347
00348 TEST_P(ClientServerTestByGridType, LocalSlam2D) {
00349 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00350 SetOptionsToTSDF2D();
00351 }
00352 InitializeRealServer();
00353 server_->Start();
00354 InitializeStub();
00355 EXPECT_TRUE(stub_->pose_graph()->GetTrajectoryStates().empty());
00356 int trajectory_id =
00357 stub_->AddTrajectoryBuilder({kRangeSensorId}, trajectory_builder_options_,
00358 local_slam_result_callback_);
00359 TrajectoryBuilderInterface* trajectory_stub =
00360 stub_->GetTrajectoryBuilder(trajectory_id);
00361 const auto measurements = mapping::testing::GenerateFakeRangeMeasurements(
00362 kTravelDistance, kDuration, kTimeStep);
00363 for (const auto& measurement : measurements) {
00364 trajectory_stub->AddSensorData(kRangeSensorId.id, measurement);
00365 }
00366 WaitForLocalSlamResults(measurements.size());
00367 EXPECT_EQ(stub_->pose_graph()->GetTrajectoryStates().at(trajectory_id),
00368 PoseGraphInterface::TrajectoryState::ACTIVE);
00369 stub_->FinishTrajectory(trajectory_id);
00370 stub_->pose_graph()->RunFinalOptimization();
00371 EXPECT_EQ(stub_->pose_graph()->GetTrajectoryStates().at(trajectory_id),
00372 PoseGraphInterface::TrajectoryState::FINISHED);
00373 EXPECT_EQ(local_slam_result_poses_.size(), measurements.size());
00374 EXPECT_NEAR(kTravelDistance,
00375 (local_slam_result_poses_.back().translation() -
00376 local_slam_result_poses_.front().translation())
00377 .norm(),
00378 0.1 * kTravelDistance);
00379 server_->Shutdown();
00380 }
00381
00382 TEST_P(ClientServerTestByGridType, LocalSlamAndDelete2D) {
00383 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00384 SetOptionsToTSDF2D();
00385 }
00386 InitializeRealServer();
00387 server_->Start();
00388 InitializeStub();
00389 int trajectory_id =
00390 stub_->AddTrajectoryBuilder({kRangeSensorId}, trajectory_builder_options_,
00391 local_slam_result_callback_);
00392 TrajectoryBuilderInterface* trajectory_stub =
00393 stub_->GetTrajectoryBuilder(trajectory_id);
00394 const auto measurements = mapping::testing::GenerateFakeRangeMeasurements(
00395 kTravelDistance, kDuration, kTimeStep);
00396 for (const auto& measurement : measurements) {
00397 trajectory_stub->AddSensorData(kRangeSensorId.id, measurement);
00398 }
00399 WaitForLocalSlamResults(measurements.size());
00400 stub_->pose_graph()->RunFinalOptimization();
00401 EXPECT_EQ(stub_->pose_graph()->GetTrajectoryStates().at(trajectory_id),
00402 PoseGraphInterface::TrajectoryState::ACTIVE);
00403 EXPECT_GT(stub_->pose_graph()->GetAllSubmapPoses().size(), 0);
00404 EXPECT_GT(stub_->pose_graph()->GetTrajectoryNodePoses().size(), 0);
00405 stub_->FinishTrajectory(trajectory_id);
00406 stub_->pose_graph()->DeleteTrajectory(trajectory_id);
00407 stub_->pose_graph()->RunFinalOptimization();
00408 EXPECT_EQ(stub_->pose_graph()->GetTrajectoryStates().at(trajectory_id),
00409 PoseGraphInterface::TrajectoryState::DELETED);
00410 EXPECT_EQ(stub_->pose_graph()->GetAllSubmapPoses().size(), 0);
00411 EXPECT_EQ(stub_->pose_graph()->GetTrajectoryNodePoses().size(), 0);
00412 server_->Shutdown();
00413 }
00414
00415 TEST_F(ClientServerTest, GlobalSlam3D) {
00416 map_builder_server_options_.mutable_map_builder_options()
00417 ->set_use_trajectory_builder_2d(false);
00418 map_builder_server_options_.mutable_map_builder_options()
00419 ->set_use_trajectory_builder_3d(true);
00420 map_builder_server_options_.mutable_map_builder_options()
00421 ->mutable_pose_graph_options()
00422 ->set_optimize_every_n_nodes(3);
00423 trajectory_builder_options_.mutable_trajectory_builder_3d_options()
00424 ->mutable_motion_filter_options()
00425 ->set_max_distance_meters(0);
00426 trajectory_builder_options_.mutable_trajectory_builder_3d_options()
00427 ->mutable_motion_filter_options()
00428 ->set_max_angle_radians(0);
00429 InitializeRealServer();
00430 server_->Start();
00431 InitializeStub();
00432 int trajectory_id = stub_->AddTrajectoryBuilder(
00433 {kRangeSensorId, kImuSensorId}, trajectory_builder_options_,
00434 local_slam_result_callback_);
00435 TrajectoryBuilderInterface* trajectory_stub =
00436 stub_->GetTrajectoryBuilder(trajectory_id);
00437 const auto measurements = mapping::testing::GenerateFakeRangeMeasurements(
00438 kTravelDistance, kDuration, kTimeStep);
00439 for (const auto& measurement : measurements) {
00440 sensor::ImuData imu_data{
00441 measurement.time - common::FromSeconds(kTimeStep / 2),
00442 Eigen::Vector3d(0., 0., 9.8), Eigen::Vector3d::Zero()};
00443 trajectory_stub->AddSensorData(kImuSensorId.id, imu_data);
00444 trajectory_stub->AddSensorData(kRangeSensorId.id, measurement);
00445 }
00446
00447
00448 WaitForLocalSlamResults(measurements.size() - 1);
00449 stub_->FinishTrajectory(trajectory_id);
00450 EXPECT_NEAR(kTravelDistance,
00451 (local_slam_result_poses_.back().translation() -
00452 local_slam_result_poses_.front().translation())
00453 .norm(),
00454 0.1 * kTravelDistance);
00455 server_->Shutdown();
00456 }
00457
00458 TEST_P(ClientServerTestByGridType, StartAndStopUploadingServerAndServer) {
00459 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00460 SetOptionsToTSDF2D();
00461 }
00462 InitializeRealServer();
00463 server_->Start();
00464 InitializeRealUploadingServer();
00465 uploading_server_->Start();
00466 uploading_server_->Shutdown();
00467 server_->Shutdown();
00468 }
00469
00470 TEST_P(ClientServerTestByGridType, AddTrajectoryBuilderWithUploadingServer) {
00471 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00472 SetOptionsToTSDF2D();
00473 }
00474 InitializeRealServer();
00475 server_->Start();
00476 InitializeRealUploadingServer();
00477 uploading_server_->Start();
00478 InitializeStub();
00479 InitializeStubForUploadingServer();
00480 int trajectory_id = stub_for_uploading_server_->AddTrajectoryBuilder(
00481 {kImuSensorId}, trajectory_builder_options_, nullptr);
00482 EXPECT_FALSE(stub_for_uploading_server_->pose_graph()->IsTrajectoryFinished(
00483 trajectory_id));
00484 EXPECT_FALSE(stub_->pose_graph()->IsTrajectoryFinished(trajectory_id));
00485 stub_for_uploading_server_->FinishTrajectory(trajectory_id);
00486 EXPECT_TRUE(stub_for_uploading_server_->pose_graph()->IsTrajectoryFinished(
00487 trajectory_id));
00488 EXPECT_TRUE(stub_->pose_graph()->IsTrajectoryFinished(trajectory_id));
00489 EXPECT_FALSE(stub_for_uploading_server_->pose_graph()->IsTrajectoryFrozen(
00490 trajectory_id));
00491 EXPECT_FALSE(stub_->pose_graph()->IsTrajectoryFrozen(trajectory_id));
00492 uploading_server_->Shutdown();
00493 server_->Shutdown();
00494 }
00495
00496 TEST_P(ClientServerTestByGridType, LocalSlam2DWithUploadingServer) {
00497 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00498 SetOptionsToTSDF2D();
00499 }
00500 InitializeRealServer();
00501 server_->Start();
00502 InitializeStub();
00503 InitializeRealUploadingServer();
00504 uploading_server_->Start();
00505 InitializeStubForUploadingServer();
00506 int trajectory_id = stub_for_uploading_server_->AddTrajectoryBuilder(
00507 {kRangeSensorId}, trajectory_builder_options_,
00508 local_slam_result_callback_);
00509 TrajectoryBuilderInterface* trajectory_stub =
00510 stub_for_uploading_server_->GetTrajectoryBuilder(trajectory_id);
00511 const auto measurements = mapping::testing::GenerateFakeRangeMeasurements(
00512 kTravelDistance, kDuration, kTimeStep);
00513 for (const auto& measurement : measurements) {
00514 trajectory_stub->AddSensorData(kRangeSensorId.id, measurement);
00515 }
00516 WaitForLocalSlamResults(measurements.size());
00517 WaitForLocalSlamResultUploads(number_of_insertion_results_);
00518
00519 std::queue<std::unique_ptr<google::protobuf::Message>> chunks;
00520 io::ForwardingProtoStreamWriter writer(
00521 [&chunks](const google::protobuf::Message* proto) -> bool {
00522 if (!proto) {
00523 return true;
00524 }
00525 std::unique_ptr<google::protobuf::Message> p(proto->New());
00526 p->CopyFrom(*proto);
00527 chunks.push(std::move(p));
00528 return true;
00529 });
00530 stub_->SerializeState(false, &writer);
00531 CHECK(writer.Close());
00532
00533 io::InMemoryProtoStreamReader reader(std::move(chunks));
00534 io::ProtoStreamDeserializer deserializer(&reader);
00535 EXPECT_EQ(deserializer.pose_graph().trajectory_size(), 1);
00536
00537 stub_for_uploading_server_->FinishTrajectory(trajectory_id);
00538 EXPECT_EQ(local_slam_result_poses_.size(), measurements.size());
00539 EXPECT_NEAR(kTravelDistance,
00540 (local_slam_result_poses_.back().translation() -
00541 local_slam_result_poses_.front().translation())
00542 .norm(),
00543 0.1 * kTravelDistance);
00544 uploading_server_->Shutdown();
00545 server_->Shutdown();
00546 }
00547
00548 TEST_P(ClientServerTestByGridType, LocalSlam2DUplinkServerRestarting) {
00549 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00550 SetOptionsToTSDF2D();
00551 }
00552 InitializeRealServer();
00553 server_->Start();
00554 InitializeStub();
00555 InitializeRealUploadingServer();
00556 uploading_server_->Start();
00557 InitializeStubForUploadingServer();
00558 int trajectory_id = stub_for_uploading_server_->AddTrajectoryBuilder(
00559 {kRangeSensorId}, trajectory_builder_options_,
00560 local_slam_result_callback_);
00561 TrajectoryBuilderInterface* trajectory_stub =
00562 stub_for_uploading_server_->GetTrajectoryBuilder(trajectory_id);
00563 const auto measurements = mapping::testing::GenerateFakeRangeMeasurements(
00564 kTravelDistance, kDuration, kTimeStep);
00565
00566
00567 for (unsigned int i = 0; i < measurements.size() / 2; ++i) {
00568 trajectory_stub->AddSensorData(kRangeSensorId.id, measurements.at(i));
00569 }
00570 WaitForLocalSlamResults(measurements.size() / 2);
00571 WaitForLocalSlamResultUploads(number_of_insertion_results_);
00572
00573
00574 LOG(INFO) << "Simulating server restart.";
00575 constexpr int kUplinkTrajectoryId = 0;
00576 stub_->FinishTrajectory(kUplinkTrajectoryId);
00577 server_->Shutdown();
00578 server_->WaitForShutdown();
00579 InitializeRealServer();
00580 server_->Start();
00581 InitializeStub();
00582
00583
00584 for (unsigned int i = measurements.size() / 2; i < measurements.size(); ++i) {
00585 trajectory_stub->AddSensorData(kRangeSensorId.id, measurements.at(i));
00586 }
00587
00588 WaitForLocalSlamResults(measurements.size() / 2);
00589 WaitForLocalSlamResultUploads(2);
00590 stub_for_uploading_server_->FinishTrajectory(trajectory_id);
00591 uploading_server_->Shutdown();
00592 uploading_server_->WaitForShutdown();
00593 server_->Shutdown();
00594 server_->WaitForShutdown();
00595 }
00596
00597 TEST_F(ClientServerTest, DelayedConnectionToUplinkServer) {
00598 InitializeRealUploadingServer();
00599 uploading_server_->Start();
00600 InitializeStubForUploadingServer();
00601 int trajectory_id = stub_for_uploading_server_->AddTrajectoryBuilder(
00602 {kRangeSensorId}, trajectory_builder_options_,
00603 local_slam_result_callback_);
00604 TrajectoryBuilderInterface* trajectory_stub =
00605 stub_for_uploading_server_->GetTrajectoryBuilder(trajectory_id);
00606 const auto measurements = mapping::testing::GenerateFakeRangeMeasurements(
00607 kTravelDistance, kDuration, kTimeStep);
00608
00609
00610 trajectory_stub->AddSensorData(kRangeSensorId.id, measurements.at(0));
00611 WaitForLocalSlamResults(1);
00612
00613 LOG(INFO) << "Delayed start of uplink server.";
00614 InitializeRealServer();
00615 server_->Start();
00616 InitializeStub();
00617
00618
00619 for (unsigned int i = 1; i < measurements.size(); ++i) {
00620 trajectory_stub->AddSensorData(kRangeSensorId.id, measurements.at(i));
00621 }
00622 WaitForLocalSlamResults(measurements.size());
00623 WaitForLocalSlamResultUploads(2);
00624 stub_for_uploading_server_->FinishTrajectory(trajectory_id);
00625 uploading_server_->Shutdown();
00626 uploading_server_->WaitForShutdown();
00627 server_->Shutdown();
00628 server_->WaitForShutdown();
00629 }
00630
00631 TEST_P(ClientServerTestByGridType, LoadStateAndDelete) {
00632 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00633 SetOptionsToTSDF2D();
00634 }
00635 InitializeRealServer();
00636 server_->Start();
00637 InitializeStub();
00638
00639
00640 auto reader =
00641 ProtoReaderFromStrings(kSerializationHeaderProtoString,
00642 {
00643 kPoseGraphProtoString,
00644 kAllTrajectoryBuilderOptionsProtoString,
00645 kSubmapProtoString,
00646 kNodeProtoString,
00647 kImuDataProtoString,
00648 kOdometryDataProtoString,
00649 kLandmarkDataProtoString,
00650 });
00651
00652 auto trajectory_remapping = stub_->LoadState(reader.get(), true);
00653 int expected_trajectory_id = 0;
00654 EXPECT_EQ(trajectory_remapping.size(), 1);
00655 EXPECT_EQ(trajectory_remapping.at(0), expected_trajectory_id);
00656 stub_->pose_graph()->RunFinalOptimization();
00657 EXPECT_TRUE(stub_->pose_graph()->IsTrajectoryFrozen(expected_trajectory_id));
00658 EXPECT_FALSE(
00659 stub_->pose_graph()->IsTrajectoryFinished(expected_trajectory_id));
00660 for (const auto& entry : trajectory_remapping) {
00661 int trajectory_id = entry.second;
00662 stub_->pose_graph()->DeleteTrajectory(trajectory_id);
00663 stub_->pose_graph()->RunFinalOptimization();
00664 EXPECT_EQ(stub_->pose_graph()->GetTrajectoryStates().at(trajectory_id),
00665 PoseGraphInterface::TrajectoryState::DELETED);
00666 }
00667 server_->Shutdown();
00668 }
00669
00670 TEST_P(ClientServerTestByGridType, LoadUnfrozenStateAndDelete) {
00671 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00672 SetOptionsToTSDF2D();
00673 }
00674 InitializeRealServer();
00675 server_->Start();
00676 InitializeStub();
00677
00678
00679 auto reader =
00680 ProtoReaderFromStrings(kSerializationHeaderProtoString,
00681 {
00682 kPoseGraphProtoString,
00683 kAllTrajectoryBuilderOptionsProtoString,
00684 kSubmapProtoString,
00685 kNodeProtoString,
00686 kImuDataProtoString,
00687 kOdometryDataProtoString,
00688 kLandmarkDataProtoString,
00689 });
00690
00691 auto trajectory_remapping =
00692 stub_->LoadState(reader.get(), false );
00693 int expected_trajectory_id = 0;
00694 EXPECT_EQ(trajectory_remapping.size(), 1);
00695 EXPECT_EQ(trajectory_remapping.at(0), expected_trajectory_id);
00696 stub_->pose_graph()->RunFinalOptimization();
00697 EXPECT_FALSE(stub_->pose_graph()->IsTrajectoryFrozen(expected_trajectory_id));
00698 EXPECT_FALSE(
00699 stub_->pose_graph()->IsTrajectoryFinished(expected_trajectory_id));
00700 EXPECT_EQ(
00701 stub_->pose_graph()->GetTrajectoryStates().at(expected_trajectory_id),
00702 PoseGraphInterface::TrajectoryState::ACTIVE);
00703 stub_->FinishTrajectory(expected_trajectory_id);
00704 EXPECT_EQ(
00705 stub_->pose_graph()->GetTrajectoryStates().at(expected_trajectory_id),
00706 PoseGraphInterface::TrajectoryState::FINISHED);
00707 for (const auto& entry : trajectory_remapping) {
00708 int trajectory_id = entry.second;
00709 stub_->pose_graph()->DeleteTrajectory(trajectory_id);
00710 stub_->pose_graph()->RunFinalOptimization();
00711 EXPECT_EQ(stub_->pose_graph()->GetTrajectoryStates().at(trajectory_id),
00712 PoseGraphInterface::TrajectoryState::DELETED);
00713 }
00714 server_->Shutdown();
00715 }
00716
00717
00718
00719 TEST_P(ClientServerTestByGridType, LocalSlam2DHandlesInvalidRequests) {
00720 if (GetParam() == ::cartographer::mapping::GridType::TSDF) {
00721 SetOptionsToTSDF2D();
00722 }
00723 InitializeRealServer();
00724 server_->Start();
00725 InitializeStub();
00726 int trajectory_id =
00727 stub_->AddTrajectoryBuilder({kRangeSensorId}, trajectory_builder_options_,
00728 local_slam_result_callback_);
00729 TrajectoryBuilderInterface* trajectory_stub =
00730 stub_->GetTrajectoryBuilder(trajectory_id);
00731 const auto measurements = mapping::testing::GenerateFakeRangeMeasurements(
00732 kTravelDistance, kDuration, kTimeStep);
00733 for (const auto& measurement : measurements) {
00734 trajectory_stub->AddSensorData(kRangeSensorId.id, measurement);
00735 }
00736 WaitForLocalSlamResults(measurements.size());
00737 stub_->pose_graph()->RunFinalOptimization();
00738
00739 const int kInvalidTrajectoryId = 7;
00740 stub_->pose_graph()->DeleteTrajectory(kInvalidTrajectoryId);
00741 EXPECT_FALSE(stub_->pose_graph()->IsTrajectoryFinished(kInvalidTrajectoryId));
00742 EXPECT_FALSE(stub_->pose_graph()->IsTrajectoryFrozen(kInvalidTrajectoryId));
00743 EXPECT_EQ(nullptr, stub_->GetTrajectoryBuilder(kInvalidTrajectoryId));
00744 stub_->FinishTrajectory(kInvalidTrajectoryId);
00745 const mapping::SubmapId kInvalidSubmapId0{kInvalidTrajectoryId, 0},
00746 kInvalidSubmapId1{trajectory_id, 424242};
00747 mapping::proto::SubmapQuery::Response submap_query_response;
00748
00749 EXPECT_NE("",
00750 stub_->SubmapToProto(kInvalidSubmapId0, &submap_query_response));
00751 EXPECT_NE("",
00752 stub_->SubmapToProto(kInvalidSubmapId1, &submap_query_response));
00753
00754 EXPECT_EQ(stub_->pose_graph()->GetTrajectoryStates().at(trajectory_id),
00755 PoseGraphInterface::TrajectoryState::ACTIVE);
00756 auto submap_poses = stub_->pose_graph()->GetAllSubmapPoses();
00757 EXPECT_GT(submap_poses.size(), 0);
00758 EXPECT_GT(stub_->pose_graph()->GetTrajectoryNodePoses().size(), 0);
00759 stub_->FinishTrajectory(trajectory_id);
00760 stub_->pose_graph()->DeleteTrajectory(trajectory_id);
00761 stub_->pose_graph()->RunFinalOptimization();
00762 mapping::SubmapId deleted_submap_id = submap_poses.begin()->id;
00763 EXPECT_NE("",
00764 stub_->SubmapToProto(deleted_submap_id, &submap_query_response));
00765 EXPECT_EQ(stub_->pose_graph()->GetTrajectoryStates().at(trajectory_id),
00766 PoseGraphInterface::TrajectoryState::DELETED);
00767
00768 stub_->pose_graph()->RunFinalOptimization();
00769 server_->Shutdown();
00770 }
00771
00772 }
00773 }
00774 }