-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
de6f109
commit dd9992d
Showing
9 changed files
with
436 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#include "drake/automotive/lane_direction.h" | ||
|
||
// For now, this is an empty .cc file that only serves to confirm that | ||
// our .h file is a stand-alone header. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#pragma once | ||
|
||
#include <memory> | ||
|
||
#include "drake/automotive/maliput/api/lane.h" | ||
|
||
namespace drake { | ||
namespace automotive { | ||
|
||
/// LaneDirection holds the lane that a MaliputRailcar is traversing and the | ||
/// direction in which it is moving. A MaliputRailcar can either travel in the | ||
/// increasing-`s` direction or in the decreasing-`s` direction. | ||
struct LaneDirection { | ||
DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(LaneDirection) | ||
|
||
/// Default constructor. | ||
LaneDirection() {} | ||
|
||
/// A constructor that sets `with_s` to be `true`. | ||
explicit LaneDirection(const maliput::api::Lane* lane_input) | ||
: LaneDirection(lane_input, true) {} | ||
|
||
/// Fully parameterized constructor. | ||
LaneDirection(const maliput::api::Lane* lane_input, bool with_s_input) | ||
: lane(lane_input), with_s(with_s_input) {} | ||
|
||
const maliput::api::Lane* lane{nullptr}; | ||
|
||
/// True means that the MaliputRailcar's `s` coordinate increases when the | ||
/// vehicle has positive speed. False means the opposite. | ||
bool with_s{true}; | ||
}; | ||
|
||
} // namespace automotive | ||
} // namespace drake |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
#include "drake/automotive/road_path.h" | ||
|
||
#include "drake/automotive/maliput/api/branch_point.h" | ||
#include "drake/automotive/maliput/api/lane.h" | ||
#include "drake/automotive/maliput/api/lane_data.h" | ||
#include "drake/common/cond.h" | ||
#include "drake/common/drake_assert.h" | ||
#include "drake/math/saturate.h" | ||
|
||
namespace drake { | ||
namespace automotive { | ||
|
||
using maliput::api::GeoPosition; | ||
using maliput::api::Lane; | ||
using maliput::api::LaneEnd; | ||
using maliput::api::LaneEndSet; | ||
using maliput::api::RoadGeometry; | ||
|
||
template <typename T> | ||
RoadPath<T>::RoadPath(const RoadGeometry& road, | ||
const LaneDirection& initial_lane_direction, | ||
const double step_size, int num_breaks) | ||
: path_(MakePiecewisePolynomial(initial_lane_direction, step_size, | ||
num_breaks)), | ||
path_prime_(path_.derivative()), | ||
path_double_prime_(path_.derivative(2)) {} | ||
|
||
template <typename T> | ||
RoadPath<T>::~RoadPath() {} | ||
|
||
template <typename T> | ||
const PiecewisePolynomial<T>& RoadPath<T>::get_path() const { | ||
return path_; | ||
} | ||
|
||
template <typename T> | ||
const T RoadPath<T>::GetClosestPathPosition(const Vector3<T>& geo_pos, | ||
const double s_guess) const { | ||
DRAKE_ABORT(); | ||
} | ||
|
||
template <typename T> | ||
const PiecewisePolynomial<T> RoadPath<T>::MakePiecewisePolynomial( | ||
const LaneDirection& initial_lane_direction, const double step_size, | ||
int num_breaks) { | ||
std::vector<T> s_breaks{}; | ||
std::vector<MatrixX<T>> geo_knots(num_breaks, MatrixX<T>::Zero(3, 1)); | ||
|
||
LaneDirection ld = initial_lane_direction; | ||
T s_lane{cond(ld.with_s, T(0.), T(ld.lane->length()))}; | ||
T s_break{0.}; | ||
|
||
// Loop over all the breaks and extract the knot points. | ||
for (int i = 0; i < num_breaks - 1; ++i) { | ||
s_breaks.emplace_back(s_break); | ||
s_break += T(step_size); | ||
|
||
GeoPosition geo_pos = | ||
ld.lane->ToGeoPosition({s_lane /* s */, 0. /* r */, 0. /* h */}); | ||
geo_knots[i] << T(geo_pos.x), T(geo_pos.y), T(geo_pos.z); | ||
|
||
// Take a step. | ||
if (ld.with_s) { | ||
s_lane += T(step_size); | ||
} else { | ||
s_lane -= T(step_size); | ||
} | ||
|
||
// Compute the distance in excess of the lane boundary by taking this step. | ||
const T out_distance{ | ||
cond(ld.with_s, T(s_lane - ld.lane->length()), T(-s_lane))}; | ||
if (out_distance >= 0.) { | ||
const LaneEndSet* lane_end_set{ | ||
ld.with_s ? ld.lane->GetOngoingBranches(LaneEnd::kFinish) | ||
: ld.lane->GetOngoingBranches(LaneEnd::kStart)}; | ||
if (lane_end_set->size() == 0) { // There are no more ongoing lanes. | ||
// If needed, add another knot point to make up the remaining distance. | ||
if (out_distance != 0.) { | ||
s_breaks.emplace_back(s_break + T(step_size - out_distance)); | ||
s_lane = cond(ld.with_s, T(ld.lane->length()), T(0.)); | ||
geo_pos = | ||
ld.lane->ToGeoPosition({s_lane /* s */, 0. /* r */, 0. /* h */}); | ||
geo_knots[i + 1] << T(geo_pos.x), T(geo_pos.y), T(geo_pos.z); | ||
} | ||
break; | ||
} | ||
|
||
// Always choose the first lane in the set as the new lane. | ||
ld.lane = lane_end_set->get(0).lane; | ||
ld.with_s = (lane_end_set->get(0).end == LaneEnd::kStart) ? true : false; | ||
|
||
// Correct for the distance overshoot. | ||
s_lane = | ||
cond(ld.with_s, out_distance, T(ld.lane->length()) - out_distance); | ||
} | ||
} | ||
// Resize the data structure with the knot points, if necessary. | ||
for (int i = 0; i < num_breaks - static_cast<int>(s_breaks.size()); ++i) { | ||
geo_knots.pop_back(); | ||
} | ||
|
||
// Create the resulting piecewise polynomial. | ||
return PiecewisePolynomial<T>::Cubic(s_breaks, geo_knots); | ||
} | ||
|
||
template class RoadPath<double>; | ||
|
||
} // namespace automotive | ||
} // namespace drake |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#pragma once | ||
|
||
#include <vector> | ||
|
||
#include <Eigen/Core> | ||
|
||
#include "drake/automotive/lane_direction.h" | ||
#include "drake/automotive/maliput/api/road_geometry.h" | ||
#include "drake/common/drake_copyable.h" | ||
#include "drake/common/eigen_types.h" | ||
#include "drake/common/trajectories/piecewise_polynomial.h" | ||
|
||
namespace drake { | ||
namespace automotive { | ||
|
||
/// RoadPath converts a sequence of Maliput Lanes into a PiecewisePolynomial for | ||
/// the purpose of generating a path for a car to follow. The path is created | ||
/// from the start of a user-specified initial lane and direction of travel, and | ||
/// proceeds in that direction until either the end of the road is reached | ||
/// (there exist no ongoing lanes), or the given number of specified breaks have | ||
/// been traversed. The resulting path is a cubic spline that exactly matches | ||
/// the `s = 0` coordinate of the lanes at each specified break point. | ||
/// | ||
/// This class is explicitly instantiated for the following scalar types. No | ||
/// other scalar types are supported. | ||
/// - double | ||
/// | ||
/// @tparam T The vector element type, which must be a valid Eigen scalar. | ||
/// Only double is supported. | ||
template <typename T> | ||
class RoadPath { | ||
public: | ||
DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(RoadPath) | ||
|
||
/// Constructor. | ||
/// @param road is the RoadGeometry from which a path is generated. | ||
/// @param initial_lane_direction contains the initial LaneDirection. This | ||
/// must be a valid @p road Lane. | ||
/// @param step_size is the size of each step (in the `s`-direction) between | ||
/// knot points. | ||
/// @param num_breaks are the number of breaks at which the knot points will | ||
/// be evaluated. | ||
RoadPath(const maliput::api::RoadGeometry& road, | ||
const LaneDirection& initial_lane_direction, | ||
const double step_size, int num_breaks); | ||
~RoadPath(); | ||
|
||
const PiecewisePolynomial<T>& get_path() const; | ||
|
||
/// Computes the closest path position of an arbitrary point in Cartesian | ||
/// space to the path. | ||
// TODO(jadecastro): Implement this. | ||
const T GetClosestPathPosition(const Vector3<T>& geo_position, | ||
const double s_guess) const; | ||
|
||
private: | ||
// Traverse the road, starting from an initial LaneDirection, and build a | ||
// cubic spline PiecewisePolynomial until 1) a given a number of segments has | ||
// been traversed, or 2) the end of the road has been reached. | ||
// | ||
// If a BranchPoint is encountered in which there is more than one ongoing | ||
// lane, the zero-index lane is always selected. | ||
// TODO(jadecastro): Use DefaultBranch to decide the ongoing Lane. | ||
const PiecewisePolynomial<T> MakePiecewisePolynomial( | ||
const LaneDirection& initial_lane_direction, const double step_size, | ||
int num_breaks); | ||
|
||
PiecewisePolynomial<T> path_{}; // The path representing the mid-curve of the | ||
// road. | ||
PiecewisePolynomial<T> path_prime_{}; // First derivative of path_. | ||
PiecewisePolynomial<T> path_double_prime_{}; // Second derivative of path_. | ||
}; | ||
|
||
} // namespace automotive | ||
} // namespace drake |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.