mirror of
https://github.com/gnxlxnxx/dubins_path
synced 2026-07-28 07:23:03 +02:00
Compare commits
4
Commits
7e02bc5a98
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f026ae21bb | ||
|
|
92d21aeb9a | ||
|
|
5992ec7008
|
||
|
|
88d978be8a
|
+1
-1
@@ -9,7 +9,7 @@ keywords = ["pathfinder", "dubinspath"]
|
|||||||
categories = ["algorithms"]
|
categories = ["algorithms"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = "Apache-2.0/MIT"
|
license = "Apache-2.0/MIT"
|
||||||
authors = ["Roman Kretschmer <gnxlxnxx@web.de>"]
|
authors = ["Roman Kretschmer <roman@kretschmer.email>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+103
-92
@@ -30,13 +30,24 @@
|
|||||||
//!
|
//!
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use euclid::{approxeq::ApproxEq, Point2D, Rotation2D, UnknownUnit};
|
use std::{
|
||||||
use num_traits;
|
cmp::PartialOrd,
|
||||||
|
convert,
|
||||||
|
ops::{Add, Mul, Rem, Sub},
|
||||||
|
};
|
||||||
|
|
||||||
|
use convert::From;
|
||||||
|
pub use euclid::Angle;
|
||||||
|
use euclid::{approxeq::ApproxEq, Point2D, Rotation2D, Trig, UnknownUnit, Vector2D};
|
||||||
|
use num_traits::{
|
||||||
|
self,
|
||||||
|
float::{Float, FloatConst},
|
||||||
|
Zero,
|
||||||
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
pub type Angle<T> = euclid::Angle<T>;
|
|
||||||
pub type Point<T> = Point2D<T, UnknownUnit>;
|
pub type Point<T> = Point2D<T, UnknownUnit>;
|
||||||
pub type Vector<T> = euclid::Vector2D<T, UnknownUnit>;
|
pub type Vector<T> = Vector2D<T, UnknownUnit>;
|
||||||
type Rotation<T> = Rotation2D<T, UnknownUnit, UnknownUnit>;
|
type Rotation<T> = Rotation2D<T, UnknownUnit, UnknownUnit>;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@@ -54,7 +65,7 @@ pub struct StraightPath<T> {
|
|||||||
pub vector: Vector<T>,
|
pub vector: Vector<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: euclid::approxeq::ApproxEq<T>> StraightPath<T> {
|
impl<T: ApproxEq<T>> StraightPath<T> {
|
||||||
/// approximate equality to other Vector
|
/// approximate equality to other Vector
|
||||||
pub fn approx_eq(&self, other: Self) -> bool {
|
pub fn approx_eq(&self, other: Self) -> bool {
|
||||||
ApproxEq::approx_eq(&self.vector, &other.vector)
|
ApproxEq::approx_eq(&self.vector, &other.vector)
|
||||||
@@ -66,13 +77,13 @@ impl<T: euclid::approxeq::ApproxEq<T>> StraightPath<T> {
|
|||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct CirclePath<T>
|
pub struct CirclePath<T>
|
||||||
where
|
where
|
||||||
T: std::ops::Mul<T, Output = T>
|
T: Mul<T, Output = T>
|
||||||
+ euclid::approxeq::ApproxEq<T>
|
+ ApproxEq<T>
|
||||||
+ std::ops::Rem<Output = T>
|
+ Rem<Output = T>
|
||||||
+ std::ops::Sub<Output = T>
|
+ Sub<Output = T>
|
||||||
+ std::ops::Add<Output = T>
|
+ Add<Output = T>
|
||||||
+ num_traits::Zero
|
+ Zero
|
||||||
+ num_traits::FloatConst
|
+ FloatConst
|
||||||
+ PartialOrd
|
+ PartialOrd
|
||||||
+ Copy,
|
+ Copy,
|
||||||
{
|
{
|
||||||
@@ -83,13 +94,13 @@ where
|
|||||||
|
|
||||||
impl<T> CirclePath<T>
|
impl<T> CirclePath<T>
|
||||||
where
|
where
|
||||||
T: std::ops::Mul<T, Output = T>
|
T: Mul<T, Output = T>
|
||||||
+ euclid::approxeq::ApproxEq<T>
|
+ ApproxEq<T>
|
||||||
+ std::ops::Rem<Output = T>
|
+ Rem<Output = T>
|
||||||
+ std::ops::Sub<Output = T>
|
+ Sub<Output = T>
|
||||||
+ std::ops::Add<Output = T>
|
+ Add<Output = T>
|
||||||
+ num_traits::Zero
|
+ Zero
|
||||||
+ num_traits::FloatConst
|
+ FloatConst
|
||||||
+ PartialOrd
|
+ PartialOrd
|
||||||
+ Copy,
|
+ Copy,
|
||||||
{
|
{
|
||||||
@@ -117,14 +128,14 @@ where
|
|||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct RouteCSC<T>
|
pub struct RouteCSC<T>
|
||||||
where
|
where
|
||||||
T: std::ops::Mul<T, Output = T>
|
T: Mul<T, Output = T>
|
||||||
+ std::ops::Mul
|
+ Mul
|
||||||
+ euclid::approxeq::ApproxEq<T>
|
+ ApproxEq<T>
|
||||||
+ std::ops::Rem<Output = T>
|
+ Rem<Output = T>
|
||||||
+ std::ops::Sub<Output = T>
|
+ Sub<Output = T>
|
||||||
+ std::ops::Add<Output = T>
|
+ Add<Output = T>
|
||||||
+ num_traits::Zero
|
+ Zero
|
||||||
+ num_traits::FloatConst
|
+ FloatConst
|
||||||
+ PartialOrd
|
+ PartialOrd
|
||||||
+ Copy,
|
+ Copy,
|
||||||
{
|
{
|
||||||
@@ -137,14 +148,14 @@ where
|
|||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct RouteCCC<T>
|
pub struct RouteCCC<T>
|
||||||
where
|
where
|
||||||
T: std::ops::Mul<T, Output = T>
|
T: Mul<T, Output = T>
|
||||||
+ std::ops::Mul
|
+ Mul
|
||||||
+ euclid::approxeq::ApproxEq<T>
|
+ ApproxEq<T>
|
||||||
+ std::ops::Rem<Output = T>
|
+ Rem<Output = T>
|
||||||
+ std::ops::Sub<Output = T>
|
+ Sub<Output = T>
|
||||||
+ std::ops::Add<Output = T>
|
+ Add<Output = T>
|
||||||
+ num_traits::Zero
|
+ Zero
|
||||||
+ num_traits::FloatConst
|
+ FloatConst
|
||||||
+ PartialOrd
|
+ PartialOrd
|
||||||
+ Copy,
|
+ Copy,
|
||||||
{
|
{
|
||||||
@@ -156,14 +167,14 @@ where
|
|||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Path<T>
|
pub enum Path<T>
|
||||||
where
|
where
|
||||||
T: std::ops::Mul<T, Output = T>
|
T: Mul<T, Output = T>
|
||||||
+ std::ops::Mul
|
+ Mul
|
||||||
+ euclid::approxeq::ApproxEq<T>
|
+ ApproxEq<T>
|
||||||
+ std::ops::Rem<Output = T>
|
+ Rem<Output = T>
|
||||||
+ std::ops::Sub<Output = T>
|
+ Sub<Output = T>
|
||||||
+ std::ops::Add<Output = T>
|
+ Add<Output = T>
|
||||||
+ num_traits::Zero
|
+ Zero
|
||||||
+ num_traits::FloatConst
|
+ FloatConst
|
||||||
+ PartialOrd
|
+ PartialOrd
|
||||||
+ Copy,
|
+ Copy,
|
||||||
{
|
{
|
||||||
@@ -174,15 +185,15 @@ where
|
|||||||
/// Route with a start Circle, a tangent straight and a end Circle
|
/// Route with a start Circle, a tangent straight and a end Circle
|
||||||
impl<T> RouteCSC<T>
|
impl<T> RouteCSC<T>
|
||||||
where
|
where
|
||||||
T: std::ops::Add
|
T: Add
|
||||||
+ std::ops::Mul
|
+ Mul
|
||||||
+ std::ops::Mul<f64, Output = T>
|
+ Mul<f64, Output = T>
|
||||||
+ num_traits::float::FloatConst
|
+ FloatConst
|
||||||
+ num_traits::float::Float
|
+ Float
|
||||||
+ std::cmp::PartialOrd
|
+ PartialOrd
|
||||||
+ std::convert::From<f64>
|
+ From<f64>
|
||||||
+ euclid::approxeq::ApproxEq<T>
|
+ ApproxEq<T>
|
||||||
+ euclid::Trig,
|
+ Trig,
|
||||||
{
|
{
|
||||||
/// right straight right route
|
/// right straight right route
|
||||||
pub fn rsr(radius: T, end_point: Point<T>, end_angle: Angle<T>) -> Result<Self, Error> {
|
pub fn rsr(radius: T, end_point: Point<T>, end_angle: Angle<T>) -> Result<Self, Error> {
|
||||||
@@ -222,7 +233,7 @@ where
|
|||||||
// get the tangent origin by moving the vector from the start circle center
|
// get the tangent origin by moving the vector from the start circle center
|
||||||
// π/2 to it's own direction and the magnitude of the circle radius
|
// π/2 to it's own direction and the magnitude of the circle radius
|
||||||
let tangent_origin = start_center
|
let tangent_origin = start_center
|
||||||
+ Rotation::new(Angle::pi() - end_angle)
|
+ Rotation::new(Angle::pi() - start_angle)
|
||||||
.transform_vector(Vector::new(radius, 0.0.into()));
|
.transform_vector(Vector::new(radius, 0.0.into()));
|
||||||
|
|
||||||
// get the angle of the start circle
|
// get the angle of the start circle
|
||||||
@@ -233,7 +244,7 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
start: CirclePath {
|
start: CirclePath {
|
||||||
center: start_center,
|
center: start_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: start_angle,
|
angle: start_angle,
|
||||||
},
|
},
|
||||||
tangent: StraightPath {
|
tangent: StraightPath {
|
||||||
@@ -242,7 +253,7 @@ where
|
|||||||
},
|
},
|
||||||
end: CirclePath {
|
end: CirclePath {
|
||||||
center: end_center,
|
center: end_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: end_angle,
|
angle: end_angle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -296,7 +307,7 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
start: CirclePath {
|
start: CirclePath {
|
||||||
center: start_center,
|
center: start_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: start_angle,
|
angle: start_angle,
|
||||||
},
|
},
|
||||||
tangent: StraightPath {
|
tangent: StraightPath {
|
||||||
@@ -305,7 +316,7 @@ where
|
|||||||
},
|
},
|
||||||
end: CirclePath {
|
end: CirclePath {
|
||||||
center: end_center,
|
center: end_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: end_angle,
|
angle: end_angle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -368,7 +379,7 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
start: CirclePath {
|
start: CirclePath {
|
||||||
center: start_center,
|
center: start_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: start_angle,
|
angle: start_angle,
|
||||||
},
|
},
|
||||||
tangent: StraightPath {
|
tangent: StraightPath {
|
||||||
@@ -377,7 +388,7 @@ where
|
|||||||
},
|
},
|
||||||
end: CirclePath {
|
end: CirclePath {
|
||||||
center: end_center,
|
center: end_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: end_angle,
|
angle: end_angle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -440,7 +451,7 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
start: CirclePath {
|
start: CirclePath {
|
||||||
center: start_center,
|
center: start_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: start_angle,
|
angle: start_angle,
|
||||||
},
|
},
|
||||||
tangent: StraightPath {
|
tangent: StraightPath {
|
||||||
@@ -449,7 +460,7 @@ where
|
|||||||
},
|
},
|
||||||
end: CirclePath {
|
end: CirclePath {
|
||||||
center: end_center,
|
center: end_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: end_angle,
|
angle: end_angle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -469,9 +480,9 @@ where
|
|||||||
let mut route_csc;
|
let mut route_csc;
|
||||||
|
|
||||||
let route_rsr = Self::rsr(radius, end_point, end_angle).unwrap();
|
let route_rsr = Self::rsr(radius, end_point, end_angle).unwrap();
|
||||||
let route_lsl = Self::rsr(radius, end_point, end_angle).unwrap();
|
let route_lsl = Self::lsl(radius, end_point, end_angle).unwrap();
|
||||||
let route_lsr = Self::rsr(radius, end_point, end_angle);
|
let route_lsr = Self::lsr(radius, end_point, end_angle);
|
||||||
let route_rsl = Self::rsr(radius, end_point, end_angle);
|
let route_rsl = Self::rsl(radius, end_point, end_angle);
|
||||||
|
|
||||||
route_csc = route_rsr;
|
route_csc = route_rsr;
|
||||||
if route_lsl.get_length() < route_csc.get_length() {
|
if route_lsl.get_length() < route_csc.get_length() {
|
||||||
@@ -495,15 +506,15 @@ where
|
|||||||
/// Route with 3 Circles
|
/// Route with 3 Circles
|
||||||
impl<T> RouteCCC<T>
|
impl<T> RouteCCC<T>
|
||||||
where
|
where
|
||||||
T: std::ops::Add
|
T: Add
|
||||||
+ std::ops::Mul
|
+ Mul
|
||||||
+ std::ops::Mul<f64, Output = T>
|
+ Mul<f64, Output = T>
|
||||||
+ num_traits::float::FloatConst
|
+ FloatConst
|
||||||
+ num_traits::float::Float
|
+ Float
|
||||||
+ std::cmp::PartialOrd
|
+ PartialOrd
|
||||||
+ std::convert::From<f64>
|
+ From<f64>
|
||||||
+ euclid::approxeq::ApproxEq<T>
|
+ ApproxEq<T>
|
||||||
+ euclid::Trig,
|
+ Trig,
|
||||||
{
|
{
|
||||||
/// right left right route (not working yet)
|
/// right left right route (not working yet)
|
||||||
pub fn rlr(radius: T, end_point: Point<T>, end_angle: Angle<T>) -> Result<Self, Error> {
|
pub fn rlr(radius: T, end_point: Point<T>, end_angle: Angle<T>) -> Result<Self, Error> {
|
||||||
@@ -537,8 +548,8 @@ where
|
|||||||
+ (vector_start_center_end_center.length() / (radius * 4.0)).acos();
|
+ (vector_start_center_end_center.length() / (radius * 4.0)).acos();
|
||||||
|
|
||||||
vector_start_center_middle_center = Vector::new(
|
vector_start_center_middle_center = Vector::new(
|
||||||
(radius * 2.0) * euclid::Trig::cos(vector_start_center_middle_center_angle),
|
(radius * 2.0) * Trig::cos(vector_start_center_middle_center_angle),
|
||||||
(radius * 2.0) * euclid::Trig::sin(vector_start_center_middle_center_angle),
|
(radius * 2.0) * Trig::sin(vector_start_center_middle_center_angle),
|
||||||
);
|
);
|
||||||
|
|
||||||
Point::new(
|
Point::new(
|
||||||
@@ -571,17 +582,17 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
start: CirclePath {
|
start: CirclePath {
|
||||||
center: start_center,
|
center: start_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: start_angle,
|
angle: start_angle,
|
||||||
},
|
},
|
||||||
middle: CirclePath {
|
middle: CirclePath {
|
||||||
center: middle_center,
|
center: middle_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: middle_angle,
|
angle: middle_angle,
|
||||||
},
|
},
|
||||||
end: CirclePath {
|
end: CirclePath {
|
||||||
center: end_center,
|
center: end_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: end_angle,
|
angle: end_angle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -618,8 +629,8 @@ where
|
|||||||
- (vector_start_center_end_center.length() / (radius * 4.0)).acos();
|
- (vector_start_center_end_center.length() / (radius * 4.0)).acos();
|
||||||
|
|
||||||
vector_start_center_middle_center = Vector::new(
|
vector_start_center_middle_center = Vector::new(
|
||||||
(radius * 2.0) * euclid::Trig::cos(vector_start_center_middle_center_angle),
|
(radius * 2.0) * Trig::cos(vector_start_center_middle_center_angle),
|
||||||
(radius * 2.0) * euclid::Trig::sin(vector_start_center_middle_center_angle),
|
(radius * 2.0) * Trig::sin(vector_start_center_middle_center_angle),
|
||||||
);
|
);
|
||||||
|
|
||||||
Point::new(
|
Point::new(
|
||||||
@@ -648,17 +659,17 @@ where
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
start: CirclePath {
|
start: CirclePath {
|
||||||
center: start_center,
|
center: start_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: start_angle,
|
angle: start_angle,
|
||||||
},
|
},
|
||||||
middle: CirclePath {
|
middle: CirclePath {
|
||||||
center: middle_center,
|
center: middle_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: middle_angle,
|
angle: middle_angle,
|
||||||
},
|
},
|
||||||
end: CirclePath {
|
end: CirclePath {
|
||||||
center: end_center,
|
center: end_center,
|
||||||
radius: radius,
|
radius,
|
||||||
angle: end_angle,
|
angle: end_angle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -699,15 +710,15 @@ where
|
|||||||
/// get the shortest path
|
/// get the shortest path
|
||||||
pub fn get_shortest<T>(radius: T, end_point: Point<T>, end_angle: Angle<T>) -> Path<T>
|
pub fn get_shortest<T>(radius: T, end_point: Point<T>, end_angle: Angle<T>) -> Path<T>
|
||||||
where
|
where
|
||||||
T: std::ops::Add
|
T: Add
|
||||||
+ std::ops::Mul
|
+ Mul
|
||||||
+ std::ops::Mul<f64, Output = T>
|
+ Mul<f64, Output = T>
|
||||||
+ num_traits::float::FloatConst
|
+ FloatConst
|
||||||
+ num_traits::float::Float
|
+ Float
|
||||||
+ std::cmp::PartialOrd
|
+ PartialOrd
|
||||||
+ std::convert::From<f64>
|
+ From<f64>
|
||||||
+ euclid::approxeq::ApproxEq<T>
|
+ ApproxEq<T>
|
||||||
+ euclid::Trig,
|
+ Trig,
|
||||||
{
|
{
|
||||||
let route_csc = RouteCSC::get_shortest(radius, end_point, end_angle).unwrap();
|
let route_csc = RouteCSC::get_shortest(radius, end_point, end_angle).unwrap();
|
||||||
let route_ccc = RouteCCC::get_shortest(radius, end_point, end_angle);
|
let route_ccc = RouteCCC::get_shortest(radius, end_point, end_angle);
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ mod tests {
|
|||||||
let radius = 0.5;
|
let radius = 0.5;
|
||||||
let end_point = Point::new(-7.0 * radius, 0.0);
|
let end_point = Point::new(-7.0 * radius, 0.0);
|
||||||
let end_angle = Angle::zero();
|
let end_angle = Angle::zero();
|
||||||
RouteCCC::rlr(radius, end_point, end_angle).unwrap();
|
RouteCCC::lrl(radius, end_point, end_angle).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user