planning_test_base.cc 8.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

D
Dong Li 已提交
42
void PlanningTestBase::SetUpTestCase() {
43
  FLAGS_planning_config_file = "modules/planning/conf/planning_config.pb.txt";
44
  FLAGS_adapter_config_path = "modules/planning/testdata/conf/adapter.conf";
45
  FLAGS_map_dir = "modules/planning/testdata";
46 47 48
  FLAGS_test_localization_file = "garage_localization.pb.txt";
  FLAGS_test_chassis_file = "garage_chassis.pb.txt";
  FLAGS_test_prediction_file = "garage_prediction.pb.txt";
49
  FLAGS_align_prediction_time = false;
50 51
}

52
bool PlanningTestBase::SetUpAdapters() {
53 54 55
  if (!AdapterManager::Initialized()) {
    AdapterManager::Init(FLAGS_adapter_config_path);
  }
56
  if (!AdapterManager::GetRoutingResponse()) {
57
    AERROR << "routing is not registered in adapter manager, check adapter "
58
              "config file."
59
           << FLAGS_adapter_config_path;
60 61
    return false;
  }
62 63 64 65
  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;
66 67
    return false;
  }
68 69 70 71 72
  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;
73 74
    return false;
  }
75 76 77 78
  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;
79
    return false;
80
  }
81 82
  AINFO << "Using Chassis file: " << chassis_file;
  auto prediction_file = FLAGS_test_data_dir + "/" + FLAGS_test_prediction_file;
83
  if (!FLAGS_test_prediction_file.empty() &&
84 85
      !AdapterManager::FeedPredictionFile(prediction_file)) {
    AERROR << "Failed to load prediction file: " << prediction_file;
86 87
    return false;
  }
88
  AINFO << "Using Prediction file: " << prediction_file;
89 90 91
  return true;
}

92
void PlanningTestBase::SetUp() {
93
  planning_.Stop();
D
Dong Li 已提交
94
  CHECK(SetUpAdapters()) << "Failed to setup adapters";
95
  planning_.Init();
96 97
}

98
void PlanningTestBase::TrimPlanning(ADCTrajectory* origin) {
D
Dong Li 已提交
99 100
  origin->clear_latency_stats();
  origin->clear_debug();
101 102 103 104
  origin->mutable_header()->clear_radar_timestamp();
  origin->mutable_header()->clear_lidar_timestamp();
  origin->mutable_header()->clear_timestamp_sec();
  origin->mutable_header()->clear_camera_timestamp();
105
  origin->mutable_header()->clear_sequence_num();
106 107 108 109 110 111
}

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");
112

113
  std::string full_golden_path = FLAGS_test_data_dir + "/" + golden_result_file;
114
  planning_.RunOnce();
115 116 117

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

119
  if (!trajectory_pointer) {
120 121 122
    AERROR << " did not get latest adc trajectory";
    return false;
  }
123

124 125 126 127 128
  if (!IsValidTrajectory(*trajectory_pointer)) {
    AERROR << "Fail to pass trajectory check.";
    return false;
  }

129 130
  adc_trajectory_ = *trajectory_pointer;
  TrimPlanning(&adc_trajectory_);
131
  if (FLAGS_test_update_golden_log) {
132
    AINFO << "The golden file is regenerated:" << full_golden_path;
133
    ::apollo::common::util::SetProtoToASCIIFile(adc_trajectory_,
134
                                                full_golden_path);
135 136 137 138
  } else {
    ADCTrajectory golden_result;
    bool load_success = ::apollo::common::util::GetProtoFromASCIIFile(
        full_golden_path, &golden_result);
139
    TrimPlanning(&golden_result);
140 141 142 143 144 145 146 147
    if (!load_success ||
        !::apollo::common::util::IsProtoEqual(golden_result, adc_trajectory_)) {
      char tmp_fname[100] = "/tmp/XXXXXX";
      int fd = mkstemp(tmp_fname);
      if (!::apollo::common::util::SetProtoToASCIIFile(adc_trajectory_, fd)) {
        AERROR << "Failed to write to file " << tmp_fname;
      }
      AERROR << "found\ndiff " << tmp_fname << " " << full_golden_path;
148 149 150 151
      return false;
    }
  }
  return true;
152 153
}

154
void PlanningTestBase::export_sl_points(
A
Aaron Xiao 已提交
155
    const std::vector<std::vector<common::SLPoint>>& points,
156
    const std::string& filename) {
D
Dong Li 已提交
157
  AINFO << "Write sl_points to file " << filename;
158 159 160 161 162 163 164 165 166 167 168 169
  std::ofstream ofs(filename);
  ofs << "level, s, l" << std::endl;
  int level = 0;
  for (const auto& level_points : points) {
    for (const auto& point : level_points) {
      ofs << level << ", " << point.s() << ", " << point.l() << std::endl;
    }
    ++level;
  }
  ofs.close();
}

170 171
void PlanningTestBase::export_path_data(const PathData& path_data,
                                        const std::string& filename) {
D
Dong Li 已提交
172
  AINFO << "Write path_data to file " << filename;
173 174 175
  std::ofstream ofs(filename);
  ofs << "s, l, dl, ddl, x, y, z" << std::endl;
  const auto& frenet_path = path_data.frenet_frame_path();
176
  const auto& discrete_path = path_data.discretized_path();
177
  if (frenet_path.NumOfPoints() != discrete_path.NumOfPoints()) {
178 179 180
    AERROR << "frenet_path and discrete path have different number of points";
    return;
  }
181 182 183
  for (uint32_t i = 0; i < frenet_path.NumOfPoints(); ++i) {
    const auto& frenet_point = frenet_path.PointAt(i);
    const auto& discrete_point = discrete_path.PathPointAt(i);
184 185 186 187 188 189 190 191
    ofs << frenet_point.s() << ", " << frenet_point.l() << ", "
        << frenet_point.dl() << ", " << frenet_point.ddl() << discrete_point.x()
        << ", " << discrete_point.y() << ", " << discrete_point.z()
        << std::endl;
  }
  ofs.close();
}

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
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);

    const double kMaxAccelThreshold = 1.5;
    const double kMinAccelThreshold = -4.0;
    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;
    }

    const double kDkappaThreshold = 0.1;
    if (point.path_point().dkappa() > kDkappaThreshold ||
        point.path_point().dkappa() < -kDkappaThreshold) {
      AERROR << "Invalid trajectory point because dkappa out of range: "
             << 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;
}

239 240
}  // namespace planning
}  // namespace apollo