Skip to content

Commit

Permalink
Add MobilPlanner as a benchmark for lane switching (RobotLocomotion#5701
Browse files Browse the repository at this point in the history
)

* Add MobilPlanner and asociated unit tests
  • Loading branch information
jadecastro authored Apr 10, 2017
1 parent 600fe02 commit 8cb1062
Show file tree
Hide file tree
Showing 15 changed files with 1,180 additions and 161 deletions.
38 changes: 37 additions & 1 deletion drake/automotive/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ drake_cc_library(
"gen/idm_planner_parameters.cc",
"gen/maliput_railcar_params.cc",
"gen/maliput_railcar_state.cc",
"gen/mobil_planner_parameters.cc",
"gen/simple_car_params.cc",
"gen/simple_car_state.cc",
],
Expand All @@ -33,6 +34,7 @@ drake_cc_library(
"gen/idm_planner_parameters.h",
"gen/maliput_railcar_params.h",
"gen/maliput_railcar_state.h",
"gen/mobil_planner_parameters.h",
"gen/simple_car_params.h",
"gen/simple_car_state.h",
],
Expand Down Expand Up @@ -134,7 +136,6 @@ drake_cc_library(
":generated_vectors",
":idm_planner",
":pose_selector",
":simple_car",
"//drake/automotive/maliput/api",
"//drake/math:saturate",
"//drake/systems/rendering:pose_bundle",
Expand Down Expand Up @@ -175,6 +176,25 @@ drake_cc_library(
],
)

drake_cc_library(
name = "mobil_planner",
srcs = ["mobil_planner.cc"],
hdrs = ["mobil_planner.h"],
deps = [
":generated_vectors",
":idm_controller",
":idm_planner",
":lane_direction",
":pose_selector",
"//drake/automotive/maliput/api",
"//drake/common:cond",
"//drake/common:symbolic",
"//drake/math:saturate",
"//drake/systems/rendering:pose_bundle",
"//drake/systems/rendering:pose_vector",
],
)

drake_cc_library(
name = "monolane_onramp_merge",
srcs = ["monolane_onramp_merge.cc"],
Expand Down Expand Up @@ -477,9 +497,16 @@ drake_cc_googletest(
],
)

drake_cc_library(
name = "idm_test",
testonly = 1,
hdrs = ["test/idm_test.h"],
)

drake_cc_googletest(
name = "idm_controller_test",
deps = [
":idm_test",
"//drake/automotive:idm_controller",
"//drake/automotive/maliput/dragway",
],
Expand All @@ -492,6 +519,15 @@ drake_cc_googletest(
],
)

drake_cc_googletest(
name = "mobil_planner_test",
deps = [
":idm_test",
"//drake/automotive:mobil_planner",
"//drake/automotive/maliput/dragway",
],
)

drake_cc_googletest(
name = "pose_selector_test",
deps = [
Expand Down
15 changes: 15 additions & 0 deletions drake/automotive/gen/mobil_planner_parameters.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "drake/automotive/gen/mobil_planner_parameters.h"

// GENERATED FILE DO NOT EDIT
// See drake/tools/lcm_vector_gen.py.

namespace drake {
namespace automotive {

const int MobilPlannerParametersIndices::kNumCoordinates;
const int MobilPlannerParametersIndices::kP;
const int MobilPlannerParametersIndices::kThreshold;
const int MobilPlannerParametersIndices::kMaxDeceleration;

} // namespace automotive
} // namespace drake
91 changes: 91 additions & 0 deletions drake/automotive/gen/mobil_planner_parameters.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#pragma once

// GENERATED FILE DO NOT EDIT
// See drake/tools/lcm_vector_gen.py.

#include <cmath>
#include <stdexcept>
#include <string>

#include <Eigen/Core>

#include "drake/systems/framework/basic_vector.h"

namespace drake {
namespace automotive {

/// Describes the row indices of a MobilPlannerParameters.
struct MobilPlannerParametersIndices {
/// The total number of rows (coordinates).
static const int kNumCoordinates = 3;

// The index of each individual coordinate.
static const int kP = 0;
static const int kThreshold = 1;
static const int kMaxDeceleration = 2;
};

/// Specializes BasicVector with specific getters and setters.
template <typename T>
class MobilPlannerParameters : public systems::BasicVector<T> {
public:
/// An abbreviation for our row index constants.
typedef MobilPlannerParametersIndices K;

/// Default constructor. Sets all rows to their default value:
/// @arg @c p defaults to 0.5 in units of dimensionless.
/// @arg @c threshold defaults to 0.1 in units of m/s^2.
/// @arg @c max_deceleration defaults to 4.0 in units of m/s^2.
MobilPlannerParameters() : systems::BasicVector<T>(K::kNumCoordinates) {
this->set_p(0.5);
this->set_threshold(0.1);
this->set_max_deceleration(4.0);
}

MobilPlannerParameters<T>* DoClone() const override {
return new MobilPlannerParameters;
}

/// @name Getters and Setters
//@{
/// politeness factor (0.0 is purely egoistic, higher values increase
/// politeness)
/// @note @c p is expressed in units of dimensionless.
/// @note @c p has a limited domain of [0.0, 1.0].
const T& p() const { return this->GetAtIndex(K::kP); }
void set_p(const T& p) { this->SetAtIndex(K::kP, p); }
/// acceleration threshold for changing lanes (Delta_a_th)
/// @note @c threshold is expressed in units of m/s^2.
/// @note @c threshold has a limited domain of [0.0, +Inf].
const T& threshold() const { return this->GetAtIndex(K::kThreshold); }
void set_threshold(const T& threshold) {
this->SetAtIndex(K::kThreshold, threshold);
}
/// maximum safe deceleration (b_safe)
/// @note @c max_deceleration is expressed in units of m/s^2.
/// @note @c max_deceleration has a limited domain of [0.0, +Inf].
const T& max_deceleration() const {
return this->GetAtIndex(K::kMaxDeceleration);
}
void set_max_deceleration(const T& max_deceleration) {
this->SetAtIndex(K::kMaxDeceleration, max_deceleration);
}
//@}

/// Returns whether the current values of this vector are well-formed.
decltype(T() < T()) IsValid() const {
using std::isnan;
auto result = (T(0) == T(0));
result = result && !isnan(p());
result = result && (p() >= T(0.0));
result = result && (p() <= T(1.0));
result = result && !isnan(threshold());
result = result && (threshold() >= T(0.0));
result = result && !isnan(max_deceleration());
result = result && (max_deceleration() >= T(0.0));
return result;
}
};

} // namespace automotive
} // namespace drake
49 changes: 23 additions & 26 deletions drake/automotive/idm_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,29 @@
#include "drake/math/saturate.h"

namespace drake {
namespace automotive {

using maliput::api::RoadGeometry;
using maliput::api::RoadPosition;
using maliput::api::Rotation;
using math::saturate;
using pose_selector::RoadOdometry;
using systems::rendering::FrameVelocity;
using systems::rendering::PoseBundle;
using systems::rendering::PoseVector;

namespace automotive {

static constexpr int kIdmParamsIndex{0};

template <typename T>
IdmController<T>::IdmController(const RoadGeometry& road) : road_(road) {
// Declare the ego car pose input.
ego_pose_index_ = this->DeclareVectorInputPort(PoseVector<T>()).get_index();
// Declare the ego car velocity input.
ego_velocity_index_ =
this->DeclareVectorInputPort(FrameVelocity<T>()).get_index();
// Declare the traffic car pose bundle input.
traffic_index_ = this->DeclareAbstractInputPort().get_index();
// Declare the output port.
this->DeclareVectorOutputPort(DrivingCommand<T>());

IdmController<T>::IdmController(const RoadGeometry& road)
: road_(road),
ego_pose_index_{
this->DeclareVectorInputPort(PoseVector<T>()).get_index()},
ego_velocity_index_{
this->DeclareVectorInputPort(FrameVelocity<T>()).get_index()},
traffic_index_{this->DeclareAbstractInputPort().get_index()},
driving_command_index_{
this->DeclareVectorOutputPort(DrivingCommand<T>()).get_index()} {
this->DeclareNumericParameter(IdmPlannerParameters<T>());
}

Expand All @@ -58,6 +56,12 @@ const systems::InputPortDescriptor<T>& IdmController<T>::traffic_input() const {
return systems::System<T>::get_input_port(traffic_index_);
}

template <typename T>
const systems::OutputPortDescriptor<T>&
IdmController<T>::driving_command_output() const {
return systems::System<T>::get_output_port(driving_command_index_);
}

template <typename T>
void IdmController<T>::DoCalcOutput(const systems::Context<T>& context,
systems::SystemOutput<T>* output) const {
Expand All @@ -81,7 +85,7 @@ void IdmController<T>::DoCalcOutput(const systems::Context<T>& context,
DRAKE_ASSERT(traffic_poses != nullptr);

systems::BasicVector<T>* const command_output_vector =
output->GetMutableVectorData(0);
output->GetMutableVectorData(driving_command_index_);
DRAKE_ASSERT(command_output_vector != nullptr);
DrivingCommand<T>* const driving_command =
dynamic_cast<DrivingCommand<T>*>(command_output_vector);
Expand All @@ -97,17 +101,19 @@ void IdmController<T>::ImplDoCalcOutput(
const PoseBundle<T>& traffic_poses,
const IdmPlannerParameters<T>& idm_params,
DrivingCommand<T>* command) const {
DRAKE_DEMAND(idm_params.IsValid());

// Find the single closest car ahead.
const RoadOdometry<T>& lead_car_odom =
pose_selector::FindClosestLeading(road_, ego_pose, traffic_poses);
const RoadPosition ego_position =
pose_selector::CalcRoadPosition(road_, ego_pose.get_isometry());

const T& s_ego = ego_position.pos.s;
const T& s_dot_ego =
GetSVelocity(RoadOdometry<double>(ego_position, ego_velocity));
const T& s_dot_ego = pose_selector::GetSVelocity(
RoadOdometry<double>(ego_position, ego_velocity));
const T& s_lead = lead_car_odom.pos.s;
const T& s_dot_lead = GetSVelocity(lead_car_odom);
const T& s_dot_lead = pose_selector::GetSVelocity(lead_car_odom);

// Saturate the net_distance at distance_lower_bound away from the ego car to
// avoid near-singular solutions inherent to the IDM equation.
Expand All @@ -123,15 +129,6 @@ void IdmController<T>::ImplDoCalcOutput(
command->set_steering_angle(0.);
}

template <typename T>
double IdmController<T>::GetSVelocity(const RoadOdometry<T>& road_odom) const {
Rotation rot = road_odom.lane->GetOrientation(road_odom.pos);
const T vx = road_odom.vel.get_velocity().translational().x();
const T vy = road_odom.vel.get_velocity().translational().y();

return vx * std::cos(rot.yaw) + vy * std::sin(rot.yaw);
}

// These instantiations must match the API documentation in idm_controller.h.
template class IdmController<double>;

Expand Down
46 changes: 26 additions & 20 deletions drake/automotive/idm_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,19 @@ namespace automotive {
///
/// They are already available to link against in the containing library.
///
/// Input Port 0: @p ego_pose PoseVector for the ego car.
/// Input Port 0: PoseVector for the ego car.
/// (InputPortDescriptor getter: ego_pose_input())
/// Input Port 1: @p ego_velocity FrameVelocity of the ego car.
///
/// Input Port 1: FrameVelocity of the ego car.
/// (InputPortDescriptor getter: ego_velocity_input())
/// Input Port 2: @p traffic_poses PoseBundle for the traffic cars, possibly
/// inclusive of the ego car's pose.
///
/// Input Port 2: PoseBundle for the traffic cars, possibly inclusive of the ego
/// car's pose.
/// (InputPortDescriptor getter: traffic_input())
///
/// Output Port 0: A DrivingCommand with the following elements:
/// * steering angle (unused - outputs zero).
/// * throttle (>= 0)
/// * brake (>= 0)
/// * acceleration.
///
/// @ingroup automotive_systems
template <typename T>
Expand All @@ -56,19 +57,15 @@ class IdmController : public systems::LeafSystem<T> {
const systems::InputPortDescriptor<T>& ego_pose_input() const;
const systems::InputPortDescriptor<T>& ego_velocity_input() const;
const systems::InputPortDescriptor<T>& traffic_input() const;
const systems::OutputPortDescriptor<T>& driving_command_output() const;
/// @}

private:
// Extracts the vehicle's `s`-direction velocity based on its RoadPosition @p
// pos and FrameVelocity @p vel. Assumes the road has zero elevation.
double GetSVelocity(const RoadOdometry<T>& road_odom) const;

// Converts @p pose into RoadPosition.
const maliput::api::RoadPosition GetRoadPosition(
const Isometry3<T>& pose) const;

void DoCalcOutput(const systems::Context<T>& context,
systems::SystemOutput<T>* output) const override;
protected:
const maliput::api::RoadGeometry& road() const { return road_; }
int ego_pose_index() const { return ego_pose_index_; }
int ego_velocity_index() const { return ego_velocity_index_; }
int traffic_index() const { return traffic_index_; }
int driving_command_index() const { return driving_command_index_; }

void ImplDoCalcOutput(
const systems::rendering::PoseVector<T>& ego_pose,
Expand All @@ -77,12 +74,21 @@ class IdmController : public systems::LeafSystem<T> {
const IdmPlannerParameters<T>& idm_params,
DrivingCommand<T>* output) const;

private:
// Converts @p pose into RoadPosition.
const maliput::api::RoadPosition GetRoadPosition(
const Isometry3<T>& pose) const;

void DoCalcOutput(const systems::Context<T>& context,
systems::SystemOutput<T>* output) const override;

const maliput::api::RoadGeometry& road_;

// Indices for the input ports.
int ego_pose_index_{};
int ego_velocity_index_{};
int traffic_index_{};
const int ego_pose_index_{};
const int ego_velocity_index_{};
const int traffic_index_{};
const int driving_command_index_{};
};

} // namespace automotive
Expand Down
Loading

0 comments on commit 8cb1062

Please sign in to comment.