-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathobstacle.py
95 lines (87 loc) · 4.04 KB
/
obstacle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import numpy as np
class Obstacle():
"""
Dynamic or static rectangular obstacle. It is assumed that dynamic objects are under constant acceleration.
E.g. moving vehicle, parked vehicle, wall
"""
def __init__(self, centroid, dx, dy, angle=0, vel=[1, 0], acc=[0, 0]):
"""
:param centroid: centroid of the obstacle
:param dx: length of the vehicle >=0
:param dy: width of the vegicle >= 0
:param angle: anti-clockwise rotation from the x-axis
:param vel: [x-velocity, y-velocity], put [0,0] for static objects
:param acc: [x-acceleration, y-acceleration], put [0,0] for static objects/constant velocity
"""
self.centroid = centroid
self.dx = dx
self.dy = dy
self.angle = angle
self.vel = vel #moving up/right is positive
self.acc = acc
self.time = 0 #time is incremented for every self.update() call
def __get_points(self, centroid):
"""
:return A line: ((x1,y1,x1',y1'))
or four line segments: ((x1,y1,x1',y1'), (x2,y2,x2',y2'), (x3,y3,x3',y3'), (x4,y4,x4',y4'))
"""
dx_cos = self.dx*np.cos(self.angle)
dx_sin = self.dx*np.sin(self.angle)
dy_sin = self.dy*np.sin(self.angle)
dy_cos = self.dy*np.cos(self.angle)
BR_x = centroid[0] + 0.5*(dx_cos + dy_sin) #BR=Bottom-right
BR_y = centroid[1] + 0.5*(dx_sin - dy_cos)
BL_x = centroid[0] - 0.5*(dx_cos - dy_sin)
BL_y = centroid[1] - 0.5*(dx_sin + dy_cos)
TL_x = centroid[0] - 0.5*(dx_cos + dy_sin)
TL_y = centroid[1] - 0.5*(dx_sin - dy_cos)
TR_x = centroid[0] + 0.5*(dx_cos - dy_sin)
TR_y = centroid[1] + 0.5*(dx_sin + dy_cos)
seg_bottom = (BL_x, BL_y, BR_x, BR_y)
seg_left = (BL_x, BL_y, TL_x, TL_y)
if self.dy == 0: #if no height
return (seg_bottom,)
elif self.dx == 0: # if no width
return (seg_left,)
else: #if rectangle
seg_top = (TL_x, TL_y, TR_x, TR_y)
seg_right = (BR_x, BR_y, TR_x, TR_y)
return (seg_bottom, seg_top, seg_left, seg_right)
def __get_points_old(self, centroid):
"""
:return A line: ((x1,y1,x1',y1'))
or four line segments: ((x1,y1,x1',y1'), (x2,y2,x2',y2'), (x3,y3,x3',y3'), (x4,y4,x4',y4'))
"""
seg_bottom = (centroid[0] - self.dx/2, centroid[1] - self.dy/2, centroid[0] + self.dx/2, centroid[1] - self.dy/2)
seg_left = (centroid[0] - self.dx/2, centroid[1] - self.dy/2, centroid[0] - self.dx/2, centroid[1] + self.dy/2)
if self.dy == 0: #if no height
return (seg_bottom,)
elif self.dx == 0: # if no width
return (seg_left,)
else: #if rectangle
seg_top = (centroid[0] - self.dx/2, centroid[1] + self.dy/2, centroid[0] + self.dx/2, centroid[1] + self.dy/2)
seg_right = (centroid[0] + self.dx/2, centroid[1] - self.dy/2, centroid[0] + self.dx/2, centroid[1] + self.dy/2)
return (seg_bottom, seg_top, seg_left, seg_right)
def update(self, pos=None, recycle_pos=True):
"""
:param pos: manually give a position. If None, update based on time.
:return: updated centroid
"""
if pos is None:
disp_x = self.centroid[0] + self.vel[0]*self.time + 0.5*self.acc[0]*(self.time**2) #s_x = ut + 0.5at^2
disp_y = self.centroid[1] + self.vel[1]*self.time + 0.5*self.acc[1]*(self.time**2) #s_y = ut + 0.5at^2
else:
if recycle_pos is True:
if self.time >= pos.shape[0]:
t = self.time%pos.shape[0]
else:
t = self.time
else: #stay at where it is when t > t_max
if self.time > pos.shape[0]:
t = pos.shape[0]
else:
t = self.time
disp_x = pos[t, 0]
disp_y = pos[t, 1]
self.time += 1 #time is incremented for every self.update() call
return self.__get_points(centroid=[disp_x, disp_y])