1pub mod polar;
4pub mod spherical;
5
6use nalgebra::constraint::{SameNumberOfRows, ShapeConstraint};
9use nalgebra::storage::Storage;
10use nalgebra::{
11 Const, Dim, SVector, Scalar, SimdBool, SimdRealField, SliceStorage, Vector,
12};
13use rand::distributions::{uniform::SampleUniform, Distribution};
14use rand::{thread_rng, SeedableRng};
15use serde::{de::DeserializeOwned, Deserialize, Serialize};
16
17use crate::error::{InvalidParamError, Result};
18use crate::params::FromParams;
19use crate::rng::{LinearCoordinates, RNG};
20use crate::trajectories::{FullTraj, LinearTrajectory};
21use crate::util::{bounds::Bounds, norm::NormCost};
22
23use super::CSpace;
24
25pub trait LeaderFollowerCSpace<X, const D: usize, const N: usize>:
30 CSpace<X, N>
31{
32 fn get_leader<S: Storage<X, Const<N>>>(
34 state: &Vector<X, Const<N>, S>,
35 ) -> Vector<
36 X,
37 Const<D>,
38 SliceStorage<'_, X, Const<D>, Const<1_usize>, S::RStride, S::CStride>,
39 > {
40 debug_assert_eq!(D * 2, N);
41 state.fixed_rows::<D>(0)
42 }
43
44 fn get_follower<S: Storage<X, Const<N>>>(
46 state: &Vector<X, Const<N>, S>,
47 ) -> Vector<
48 X,
49 Const<D>,
50 SliceStorage<'_, X, Const<D>, Const<1_usize>, S::RStride, S::CStride>,
51 > {
52 debug_assert_eq!(D * 2, N);
53 state.fixed_rows::<D>(D)
54 }
55
56 fn get_state<S1, S2>(
58 leader: &Vector<X, Const<D>, S1>,
59 follower: &Vector<X, Const<D>, S2>,
60 ) -> SVector<X, N>
61 where
62 X: Scalar,
63 S1: Storage<X, Const<D>>,
64 S2: Storage<X, Const<D>>,
65 {
66 debug_assert_eq!(D * 2, N);
67 SVector::<X, N>::from_iterator(
68 leader.iter().chain(follower.iter()).cloned(),
69 )
70 }
71}
72
73#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
74#[serde(bound(
75 serialize = "X: Scalar + Serialize",
76 deserialize = "X: Scalar + DeserializeOwned"
77))]
78pub struct LeaderFollowerSpaceParams<X, const N: usize> {
79 pub bounds: Bounds<X, N>,
80 pub norm: NormCost,
81 pub seed: Option<u64>,
82 pub sensor_range: (X, X),
83}
84
85impl<X: Scalar + PartialEq, const N: usize> PartialEq
86 for LeaderFollowerSpaceParams<X, N>
87{
88 fn eq(&self, other: &Self) -> bool {
89 self.bounds == other.bounds
90 && self.norm == other.norm
91 && self.seed == other.seed
92 && self.sensor_range == other.sensor_range
93 }
94}
95
96pub struct LeaderFollowerSpace<X, const D: usize, const N: usize>
100where
101 X: SampleUniform,
102{
103 volume: X,
104 norm: NormCost,
105 rng: RNG,
106 distribution: LinearCoordinates<X, N>,
107 intial_sensor_range: (X, X),
108 sensor_range: (X, X),
109}
110
111impl<X, const D: usize, const N: usize> LeaderFollowerSpace<X, D, N>
112where
113 X: SimdRealField + SampleUniform + Copy,
114{
115 pub fn new(
116 bounds: Bounds<X::Element, N>,
117 norm: NormCost,
118 rng: RNG,
119 sensor_range: (X::Element, X::Element),
120 ) -> Result<Self>
121 where
122 X::Element: Scalar,
123 {
124 debug_assert_eq!(D * 2, N);
125
126 let bounds = Bounds::splat(bounds);
127 let sensor_range = (X::splat(sensor_range.0), X::splat(sensor_range.1));
128
129 if !bounds.is_valid() {
130 Err(InvalidParamError {
131 parameter_name: "bounds",
132 parameter_value: format!("{:?}", bounds),
133 })?;
134 }
135
136 let volume = bounds.volume();
137 let distribution = bounds.into();
138
139 if !sensor_range.0.simd_lt(sensor_range.1).all() {
140 Err(InvalidParamError {
141 parameter_name: "sensor_range",
142 parameter_value: format!("{:?}", sensor_range),
143 })?;
144 }
145
146 Ok(Self {
147 volume,
148 norm,
149 rng,
150 distribution,
151 intial_sensor_range: sensor_range,
152 sensor_range,
153 })
154 }
155
156 pub fn intial_sensor_range(&self) -> (X::Element, X::Element) {
157 (
158 self.intial_sensor_range.0.extract(0),
159 self.intial_sensor_range.1.extract(0),
160 )
161 }
162
163 pub fn get_sensor_range(&self) -> (X::Element, X::Element) {
164 (
165 self.sensor_range.0.extract(0),
166 self.sensor_range.1.extract(0),
167 )
168 }
169
170 pub fn set_sensor_range(
171 &mut self,
172 sensor_range: (X::Element, X::Element),
173 ) -> Option<()> {
174 let sensor_range = (X::splat(sensor_range.0), X::splat(sensor_range.1));
175 if sensor_range.0.simd_lt(sensor_range.1).all() {
176 self.sensor_range = sensor_range;
178 Some(())
179 } else {
180 None
182 }
183 }
184}
185
186impl<X, const D: usize, const N: usize> LeaderFollowerCSpace<X, D, N>
187 for LeaderFollowerSpace<X, D, N>
188where
189 X: SimdRealField + SampleUniform + Copy,
190 X::Element: Scalar,
191{
192 }
194
195impl<X, const D: usize, const N: usize> CSpace<X, N>
196 for LeaderFollowerSpace<X, D, N>
197where
198 X: SimdRealField + SampleUniform + Copy,
199 X::Element: Scalar,
200{
201 type Traj = LinearTrajectory<X, NormCost, N>;
202
203 fn volume(&self) -> X {
204 self.volume
205 }
206
207 fn cost<R1, R2, S1, S2>(
208 &self,
209 a: &Vector<X, R1, S1>,
210 b: &Vector<X, R2, S2>,
211 ) -> X
212 where
213 R1: Dim,
214 R2: Dim,
215 S1: Storage<X, R1>,
216 S2: Storage<X, R2>,
217 ShapeConstraint: SameNumberOfRows<R1, R2>,
218 {
219 self.norm.cost(a, b)
220 }
221
222 fn trajectory<S1, S2>(
223 &self,
224 start: Vector<X, Const<N>, S1>,
225 end: Vector<X, Const<N>, S2>,
226 ) -> Option<FullTraj<X, Self::Traj, S1, S2, N>>
227 where
228 X: Scalar,
229 S1: Storage<X, Const<N>>,
230 S2: Storage<X, Const<N>>,
231 {
232 Some(FullTraj::new(start, end, LinearTrajectory::new(self.norm)))
234 }
235
236 fn is_free<S>(&self, _: &Vector<X, Const<N>, S>) -> bool
237 where
238 S: Storage<X, Const<N>>,
239 {
240 true
242 }
243
244 fn saturate(&self, a: &mut SVector<X, N>, b: &SVector<X, N>, delta: X) {
245 let delta = delta / (X::one() + X::one());
246
247 let mut leader_a = a.fixed_rows_mut::<D>(0);
249 let leader_b = b.fixed_rows::<D>(0);
250
251 let leader_scale = delta / self.norm.cost(&leader_a, &leader_b);
252
253 leader_a.set_column(0, &(&leader_a - &leader_b));
254 leader_a.set_column(0, &(&leader_a * leader_scale));
255 leader_a.set_column(0, &(&leader_a + &leader_b));
256
257 let mut follower_a = a.fixed_rows_mut::<D>(D);
259 let follower_b = b.fixed_rows::<D>(D);
260
261 let follower_scale = delta / self.norm.cost(&follower_a, &follower_b);
262
263 follower_a.set_column(0, &(&follower_a - &follower_b));
264 follower_a.set_column(0, &(&follower_a * follower_scale));
265 follower_a.set_column(0, &(&follower_a + &follower_b));
266 }
267
268 fn sample(&mut self) -> SVector<X, N> {
269 self.distribution.sample(&mut self.rng)
270 }
271}
272
273impl<X, const D: usize, const N: usize> FromParams
274 for LeaderFollowerSpace<X, D, N>
275where
276 X: SimdRealField + SampleUniform + Copy,
277 X::Element: Scalar,
278{
279 type Params = LeaderFollowerSpaceParams<X::Element, N>;
280 fn from_params(params: Self::Params) -> Result<Self> {
281 let rng = match params.seed {
282 Some(seed) => RNG::seed_from_u64(seed),
283 None => RNG::from_rng(thread_rng())?,
284 };
285
286 LeaderFollowerSpace::new(
287 params.bounds,
288 params.norm,
289 rng,
290 params.sensor_range,
291 )
292 }
293}