planning_test_base.cc 7.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * 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.
 *****************************************************************************/

17
#include "modules/planning/integration_tests/planning_test_base.h"
18

19 20 21
#include <cstdlib>

#include "google/protobuf/io/zero_copy_stream_impl.h"
D
Dong Li 已提交
22
#include "modules/common/log.h"
23
#include "modules/common/vehicle_state/vehicle_state.h"
24
#include "modules/planning/common/planning_gflags.h"
D
Dong Li 已提交
25

26 27 28 29 30
namespace apollo {
namespace planning {

using common::adapter::AdapterManager;

31 32 33
DEFINE_string(test_data_dir, "", "the test data folder");
DEFINE_bool(test_update_golden_log, false,
            "true to update decision golden log file.");
34
DEFINE_string(test_routing_response_file, "garage_routing.pb.txt",
35
              "The routing file used in test");
36 37 38
DEFINE_string(test_localization_file, "garage_localization.pb.txt",
              "The localization test file");
DEFINE_string(test_chassis_file, "garage_chassis.pb.txt",
39
              "The chassis test file");
40
DEFINE_string(test_prediction_file, "", "The prediction module test file");
41

42 43 44
DEFINE_string(test_previous_planning_file, "",
              "The previous planning test file");

D
Dong Li 已提交
45
void PlanningTestBase::SetUpTestCase() {
46
  FLAGS_planning_config_file = "modules/planning/conf/planning_config.pb.txt";
47
  FLAGS_adapter_config_filename = "modules/planning/testdata/conf/adapter.conf";
48
  FLAGS_map_dir = "modules/planning/testdata";
49 50 51
  FLAGS_test_localization_file = "garage_localization.pb.txt";
  FLAGS_test_chassis_file = "garage_chassis.pb.txt";
  FLAGS_test_prediction_file = "garage_prediction.pb.txt";
52
  FLAGS_align_prediction_time = false;
D
Dong Li 已提交
53
  FLAGS_enable_reference_line_provider_thread = false;
54
  FLAGS_enable_trajectory_check = true;
55 56
}

57
bool PlanningTestBase::SetUpAdapters() {
58
  if (!AdapterManager::Initialized()) {
59
    AdapterManager::Init(FLAGS_adapter_config_filename);
60
  }
61
  if (!AdapterManager::GetRoutingResponse()) {
62
    AERROR << "routing is not registered in adapter manager, check adapter "
63
              "config file."
64
           << FLAGS_adapter_config_filename;
65 66
    return false;
  }
67 68 69 70
  auto routing_response_file =
      FLAGS_test_data_dir + "/" + FLAGS_test_routing_response_file;
  if (!AdapterManager::FeedRoutingResponseFile(routing_response_file)) {
    AERROR << "failed to routing file: " << routing_response_file;
71 72
    return false;
  }
73 74 75 76 77
  AINFO << "Using Routing " << routing_response_file;
  auto localization_file =
      FLAGS_test_data_dir + "/" + FLAGS_test_localization_file;
  if (!AdapterManager::FeedLocalizationFile(localization_file)) {
    AERROR << "Failed to load localization file: " << localization_file;
78 79
    return false;
  }
80 81 82 83
  AINFO << "Using Localization file: " << localization_file;
  auto chassis_file = FLAGS_test_data_dir + "/" + FLAGS_test_chassis_file;
  if (!AdapterManager::FeedChassisFile(chassis_file)) {
    AERROR << "Failed to load chassis file: " << chassis_file;
84
    return false;
85
  }
86 87
  AINFO << "Using Chassis file: " << chassis_file;
  auto prediction_file = FLAGS_test_data_dir + "/" + FLAGS_test_prediction_file;
88
  if (!FLAGS_test_prediction_file.empty() &&
89 90
      !AdapterManager::FeedPredictionFile(prediction_file)) {
    AERROR << "Failed to load prediction file: " << prediction_file;
91 92
    return false;
  }
93
  AINFO << "Using Prediction file: " << prediction_file;
94 95 96
  return true;
}

97
void PlanningTestBase::SetUp() {
98
  planning_.Stop();
D
Dong Li 已提交
99
  CHECK(SetUpAdapters()) << "Failed to setup adapters";
100
  CHECK(planning_.Init().ok()) << "Failed to init planning module";
101 102 103 104 105 106 107
  if (!FLAGS_test_previous_planning_file.empty()) {
    const auto prev_planning_file =
        FLAGS_test_data_dir + "/" + FLAGS_test_previous_planning_file;
    ADCTrajectory prev_planning;
    CHECK(common::util::GetProtoFromFile(prev_planning_file, &prev_planning));
    planning_.SetLastPublishableTrajectory(prev_planning);
  }
108 109
}

110
void PlanningTestBase::TrimPlanning(ADCTrajectory* origin) {
D
Dong Li 已提交
111 112
  origin->clear_latency_stats();
  origin->clear_debug();
113 114 115 116
  origin->mutable_header()->clear_radar_timestamp();
  origin->mutable_header()->clear_lidar_timestamp();
  origin->mutable_header()->clear_timestamp_sec();
  origin->mutable_header()->clear_camera_timestamp();
117
  origin->mutable_header()->clear_sequence_num();
118 119 120 121 122 123
}

bool PlanningTestBase::RunPlanning(const std::string& test_case_name,
                                   int case_num) {
  const std::string golden_result_file = apollo::common::util::StrCat(
      "result_", test_case_name, "_", case_num, ".pb.txt");
124

125
  std::string full_golden_path = FLAGS_test_data_dir + "/" + golden_result_file;
126
  planning_.RunOnce();
127 128 129

  const ADCTrajectory* trajectory_pointer =
      AdapterManager::GetPlanning()->GetLatestPublished();
130

131
  if (!trajectory_pointer) {
132 133 134
    AERROR << " did not get latest adc trajectory";
    return false;
  }
135

136 137 138 139 140
  if (!IsValidTrajectory(*trajectory_pointer)) {
    AERROR << "Fail to pass trajectory check.";
    return false;
  }

141 142
  adc_trajectory_ = *trajectory_pointer;
  TrimPlanning(&adc_trajectory_);
143
  if (FLAGS_test_update_golden_log) {
144
    AINFO << "The golden file is regenerated:" << full_golden_path;
145
    common::util::SetProtoToASCIIFile(adc_trajectory_, full_golden_path);
146 147
  } else {
    ADCTrajectory golden_result;
148 149
    bool load_success =
        common::util::GetProtoFromASCIIFile(full_golden_path, &golden_result);
150
    TrimPlanning(&golden_result);
151
    if (!load_success ||
Z
Zhang Liangliang 已提交
152
        !common::util::IsProtoEqual(golden_result, adc_trajectory_)) {
153 154
      char tmp_fname[100] = "/tmp/XXXXXX";
      int fd = mkstemp(tmp_fname);
Z
Zhang Liangliang 已提交
155
      if (!common::util::SetProtoToASCIIFile(adc_trajectory_, fd)) {
156 157 158
        AERROR << "Failed to write to file " << tmp_fname;
      }
      AERROR << "found\ndiff " << tmp_fname << " " << full_golden_path;
D
Dong Li 已提交
159
      AERROR << "visualize diff\npython "
160 161
                "modules/tools/plot_trace/plot_planning_result.py "
             << tmp_fname << " " << full_golden_path;
162 163 164 165
      return false;
    }
  }
  return true;
166 167
}

168 169 170 171 172 173 174 175 176
bool PlanningTestBase::IsValidTrajectory(const ADCTrajectory& trajectory) {
  if (trajectory.trajectory_point().empty()) {
    AERROR << "trajectory has NO point.";
    return false;
  }

  for (int i = 0; i < trajectory.trajectory_point_size(); ++i) {
    const auto& point = trajectory.trajectory_point(i);

177 178 179 180
    const double kMaxAccelThreshold =
        FLAGS_longitudinal_acceleration_upper_bound;
    const double kMinAccelThreshold =
        FLAGS_longitudinal_acceleration_lower_bound;
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
    if (point.a() > kMaxAccelThreshold || point.a() < kMinAccelThreshold) {
      AERROR << "Invalid trajectory point because accel out of range: "
             << point.DebugString();
      return false;
    }

    if (!point.has_path_point()) {
      AERROR << "Invalid trajectory point because NO path_point in "
                "trajectory_point: "
             << point.DebugString();
      return false;
    }

    if (i > 0) {
      const double kPathSEpsilon = 1e-3;
      const auto& last_point = trajectory.trajectory_point(i - 1);
      if (point.path_point().s() + kPathSEpsilon <
          last_point.path_point().s()) {
        AERROR << "Invalid trajectory point because s value error. last point: "
               << last_point.DebugString()
               << ", curr point: " << point.DebugString();
        return false;
      }
    }
  }
  return true;
}

209 210
}  // namespace planning
}  // namespace apollo