client_server_test.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 The Cartographer Authors
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *      http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
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.;         // Seconds.
00055 constexpr double kTimeStep = 0.1;        // Seconds.
00056 constexpr double kTravelDistance = 1.2;  // Meters.
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     // TODO(cschuet): Due to the hard-coded addresses these tests will become
00083     // flaky when run in parallel.
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   // First range data will not call back while initializing PoseExtrapolator, so
00447   // expect one less.
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   // Ensure it can be read.
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   // Insert half of the measurements.
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   // Simulate a cloud server restart.
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   // Insert the second half of the measurements.
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   // Insert the first measurement.
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   // Insert all other measurements.
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   // Load text proto into in_memory_reader.
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   // Load text proto into in_memory_reader.
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 /* load_frozen_state */);
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 // TODO(gaschler): Test-cover LoadStateFromFile.
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   // Expect that it returns non-empty error string.
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   // Make sure optimization runs with a deleted trajectory.
00768   stub_->pose_graph()->RunFinalOptimization();
00769   server_->Shutdown();
00770 }
00771 
00772 }  // namespace
00773 }  // namespace cloud
00774 }  // namespace cartographer


cartographer
Author(s): The Cartographer Authors
autogenerated on Thu May 9 2019 02:27:35