1use crate::geometry::Point;
4use crate::geometry::Pose;
5use crate::properties::Motion;
6use crate::properties::Size;
7
8#[derive(Copy, Clone, PartialEq, Debug)]
29pub struct BCar {
30 pub pose: Pose,
31 pub size: Size,
32 pub motion: Motion,
33}
34
35impl BCar {
36 pub fn new(pose: Pose, size: Size, motion: Motion) -> BCar {
37 BCar {pose, size, motion}
38 }
39
40 pub fn new_xyh(x: f64, y: f64, h: f64) -> BCar {
61 BCar {
62 pose: Pose::new(x, y, h),
63 size: Size::default(),
64 motion: Motion::default(),
65 }
66 }
67
68 pub fn default() -> BCar {
82 BCar {
83 pose: Pose::default(),
84 size: Size::default(),
85 motion: Motion::default(),
86 }
87 }
88
89 pub fn size(&self) -> Size {
91 self.size
92 }
93
94 pub fn set_size(&mut self, s: Size) {
112 self.size = s;
113 }
114
115 pub fn pose(&self) -> Pose {
117 self.pose
118 }
119
120 pub fn set_pose(&mut self, p: Pose) {
138 self.pose = p
139 }
140
141 pub fn motion(&self) -> Motion {
143 self.motion
144 }
145
146 pub fn set_motion(&mut self, m: Motion) {
164 self.motion = m
165 }
166
167 pub fn drivable(&self, pose: Pose) -> bool {
177 let pi = std::f64::consts::PI;
178 let pi2 = pi / 2.0;
179
180 let mut a_1 = (pose.y - self.pose.y).atan2(pose.x - self.pose.x);
181 a_1 -= self.pose.h;
182 while a_1 < -pi { a_1 += 2.0 * pi; }
183 while a_1 > pi { a_1 -= 2.0 * pi; }
184
185 let mut h_d = pose.h - self.pose.h;
186 while h_d < -pi { h_d += 2.0 * pi; }
187 while h_d > pi { h_d -= 2.0 * pi; }
188
189 let mut a_2 = 0.0;
190 let mut zb = self.pose;
191
192 if h_d == 0.0 && (a_1 == 0.0 || a_2 == pi || a_2 == -pi) {
193 return true;
194 } else if 0.0 < a_1 && a_1 <= pi2 { zb.rotate(self.ccl(), h_d);
196 if pose.y == zb.y && pose.x == zb.x { return true;
199 }
200 a_2 = (pose.y - zb.y).atan2(pose.x - zb.x);
201 while a_2 < -pi { a_2 += 2.0 * pi; }
202 while a_2 > pi { a_2 -= 2.0 * pi; }
203 if zb.h >= a_2 && a_2 >= self.pose.h {
204 return true;
205 }
206 } else if pi2 < a_1 && a_1 <= pi { zb.rotate(self.ccl(), h_d);
208 if pose.y == zb.y && pose.x == zb.x { return true;
211 }
212 a_2 = (pose.y - zb.y).atan2(pose.x - zb.x);
213 a_2 -= pi;
214 while a_2 < -pi { a_2 += 2.0 * pi; }
215 while a_2 > pi { a_2 -= 2.0 * pi; }
216 if self.pose.h >= a_2 && a_2 >= zb.h {
217 return true;
218 }
219 } else if 0.0 > a_1 && a_1 >= -pi2 { zb.rotate(self.ccr(), h_d);
221 if pose.y == zb.y && pose.x == zb.x { return true;
224 }
225 a_2 = (pose.y - zb.y).atan2(pose.x - zb.x);
226 while a_2 < -pi { a_2 += 2.0 * pi; }
227 while a_2 > pi { a_2 -= 2.0 * pi; }
228 if self.pose.h >= a_2 && a_2 >= zb.h {
229 return true;
230 }
231 } else if -pi2 > a_1 && a_1 >= -pi { zb.rotate(self.ccr(), h_d);
233 if pose.y == zb.y && pose.x == zb.x { return true;
236 }
237 a_2 = (pose.y - zb.y).atan2(pose.x - zb.x);
238 a_2 -= pi;
239 while a_2 < -pi { a_2 += 2.0 * pi; }
240 while a_2 > pi { a_2 -= 2.0 * pi; }
241 if zb.h >= a_2 && a_2 >= self.pose.h {
242 return true;
243 }
244 }
245
246 false
247 }
248
249 pub fn mtr(&self) -> f64 {
251 (
252 (self.size.curb_to_curb / 2.0).powi(2)
253 - self.size.wheelbase.powi(2)
254 ).sqrt()
255 - self.size.width / 2.0
256 }
257
258 pub fn ccl(&self) -> Point {
260 let x = self.pose.x;
261 let y = self.pose.y;
262 let h = self.pose.h;
263 Point::new(
264 x + self.mtr() * (h + std::f64::consts::PI / 2.0).cos(),
265 y + self.mtr() * (h + std::f64::consts::PI / 2.0).sin(),
266 )
267 }
268
269 pub fn ccr(&self) -> Point {
271 let x = self.pose.x;
272 let y = self.pose.y;
273 let h = self.pose.h;
274 Point::new(
275 x + self.mtr() * (h - std::f64::consts::PI / 2.0).cos(),
276 y + self.mtr() * (h - std::f64::consts::PI / 2.0).sin(),
277 )
278 }
279
280 pub fn cf(&self) -> Point {
282 let mut x = self.pose.x;
283 x += self.size.distance_to_front * self.pose.h.cos();
284 let mut y = self.pose.y;
285 y += self.size.distance_to_front * self.pose.h.sin();
286 Point {x, y}
287 }
288
289 pub fn lf(&self) -> Point {
291 let pi = std::f64::consts::PI;
292 let mut x = self.pose.x;
293 x += self.size.width/2.0 * (self.pose.h + pi/2.0).cos();
294 x += self.size.distance_to_front * self.pose.h.cos();
295 let mut y = self.pose.y;
296 y += self.size.width/2.0 * (self.pose.h + pi/2.0).sin();
297 y += self.size.distance_to_front * self.pose.h.sin();
298 Point {x, y}
299 }
300
301 pub fn la(&self) -> Point {
303 let pi = std::f64::consts::PI;
304 let mut x = self.pose.x;
305 x += self.size.width/2.0 * (self.pose.h + pi/2.0).cos();
306 let mut y = self.pose.y;
307 y += self.size.width/2.0 * (self.pose.h + pi/2.0).sin();
308 Point {x, y}
309 }
310
311 pub fn lr(&self) -> Point {
313 let pi = std::f64::consts::PI;
314 let distance_to_rear = self.size.length - self.size.distance_to_front;
315 let mut x = self.pose.x;
316 x += self.size.width/2.0 * (self.pose.h + pi/2.0).cos();
317 x += -distance_to_rear * self.pose.h.cos();
318 let mut y = self.pose.y;
319 y += self.size.width/2.0 * (self.pose.h + pi/2.0).sin();
320 y += -distance_to_rear * self.pose.h.sin();
321 Point {x, y}
322 }
323
324 pub fn rr(&self) -> Point {
326 let pi = std::f64::consts::PI;
327 let distance_to_rear = self.size.length - self.size.distance_to_front;
328 let mut x = self.pose.x;
329 x += self.size.width/2.0 * (self.pose.h - pi/2.0).cos();
330 x += -distance_to_rear * self.pose.h.cos();
331 let mut y = self.pose.y;
332 y += self.size.width/2.0 * (self.pose.h - pi/2.0).sin();
333 y += -distance_to_rear * self.pose.h.sin();
334 Point {x, y}
335 }
336
337 pub fn ra(&self) -> Point {
339 let pi = std::f64::consts::PI;
340 let mut x = self.pose.x;
341 x += self.size.width/2.0 * (self.pose.h - pi/2.0).cos();
342 let mut y = self.pose.y;
343 y += self.size.width/2.0 * (self.pose.h - pi/2.0).sin();
344 Point {x, y}
345 }
346
347 pub fn rf(&self) -> Point {
349 let pi = std::f64::consts::PI;
350 let mut x = self.pose.x;
351 x += self.size.width/2.0 * (self.pose.h - pi/2.0).cos();
352 x += self.size.distance_to_front * self.pose.h.cos();
353 let mut y = self.pose.y;
354 y += self.size.width/2.0 * (self.pose.h - pi/2.0).sin();
355 y += self.size.distance_to_front * self.pose.h.sin();
356 Point {x, y}
357 }
358}
359
360impl Iterator for BCar {
361 type Item = BCar;
362
363 fn next(&mut self) -> Option<Self::Item> {
380 self.pose.x += self.motion.speed * self.pose.h.cos();
381 self.pose.y += self.motion.speed * self.pose.h.sin();
382 self.pose.h += self.motion.speed
383 / self.size.wheelbase
384 * self.motion.steer.tan();
385 Some(*self)
386 }
387}