planning_test_base.cc 7.7 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_filename = "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;
D
Dong Li 已提交
50
  FLAGS_enable_reference_line_provider_thread = false;
51 52
}

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

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

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

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

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

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

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

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

130 131
  adc_trajectory_ = *trajectory_pointer;
  TrimPlanning(&adc_trajectory_);
132
  if (FLAGS_test_update_golden_log) {
133
    AINFO << "The golden file is regenerated:" << full_golden_path;
134
    ::apollo::common::util::SetProtoToASCIIFile(adc_trajectory_,
135
                                                full_golden_path);
136 137 138 139
  } else {
    ADCTrajectory golden_result;
    bool load_success = ::apollo::common::util::GetProtoFromASCIIFile(
        full_golden_path, &golden_result);
140
    TrimPlanning(&golden_result);
141 142 143 144 145 146 147 148
    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;
D
Dong Li 已提交
149
      AERROR << "visualize diff\npython "
150 151
                "modules/tools/plot_trace/plot_planning_result.py "
             << tmp_fname << " " << full_golden_path;
152 153 154 155
      return false;
    }
  }
  return true;
156 157
}

158 159 160 161 162 163 164 165 166
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);

167 168 169 170
    const double kMaxAccelThreshold =
        FLAGS_longitudinal_acceleration_upper_bound;
    const double kMinAccelThreshold =
        FLAGS_longitudinal_acceleration_lower_bound;
171 172 173 174 175 176 177 178 179 180 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
    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;
}

207 208
}  // namespace planning
}  // namespace apollo