-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.py
169 lines (133 loc) · 4.55 KB
/
utils.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
from setting import *
import random
random.seed(RANDOM_SEED)
import math
""" Some math utilies, feel free to use any of these!!!
"""
# euclian distance in grid world
def grid_distance(x1, y1, x2, y2):
return math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
# utils for 2d rotation, given frame \theta
def rotate_point(x, y, heading_deg):
c = math.cos(math.radians(heading_deg))
s = math.sin(math.radians(heading_deg))
xr = x * c + y * -s
yr = x * s + y * c
return xr, yr
# heading angle difference = heading1 - heading2
# return value always in range (-180, 180] in deg
def diff_heading_deg(heading1, heading2):
dh = heading1 - heading2
while dh > 180:
dh -= 360
while dh <= -180:
dh += 360
return dh
def compute_mean_pose(particles, confident_dist=1):
""" Compute the mean pose for all particles
This is not part of the particle filter algorithm but rather an
addition to show the "best belief" for current pose
"""
m_x, m_y, m_count = 0, 0, 0
# for rotation average
m_hx, m_hy = 0, 0
for p in particles:
m_count += 1
m_x += p.x
m_y += p.y
m_hx += math.sin(math.radians(p.h))
m_hy += math.cos(math.radians(p.h))
if m_count == 0:
return -1, -1, 0, False
m_x /= m_count
m_y /= m_count
# average rotation
m_hx /= m_count
m_hy /= m_count
m_h = math.degrees(math.atan2(m_hx, m_hy));
# Now compute how good that mean is -- check how many particles
# actually are in the immediate vicinity
m_count = 0
for p in particles:
if grid_distance(p.x, p.y, m_x, m_y) < 1:
m_count += 1
return m_x, m_y, m_h, m_count > len(particles) * 0.95
# utils to add gaussian noise
def add_gaussian_noise(data, sigma):
return data + random.gauss(0.0, sigma)
def add_odometry_noise(odom_act, heading_sigma, trans_sigma):
return (add_gaussian_noise(odom_act[0], trans_sigma), \
add_gaussian_noise(odom_act[1], trans_sigma), \
add_gaussian_noise(odom_act[2], heading_sigma))
def add_marker_measurement_noise(marker_measured, trans_sigma, rot_sigma):
return (add_gaussian_noise(marker_measured[0], trans_sigma), \
add_gaussian_noise(marker_measured[1], trans_sigma), \
add_gaussian_noise(marker_measured[2], rot_sigma))
class Node(object):
"""Class representing a node in RRT
"""
def __init__(self, coord, parent=None):
super(Node, self).__init__()
self.coord = coord
self.parent = parent
@property
def x(self):
return self.coord[0]
@property
def y(self):
return self.coord[1]
def __getitem__(self, key):
assert (key == 0 or key == 1)
return self.coord[key]
def get_dist(p, q):
return np.sqrt((p.x - q.x) ** 2 + (p.y - q.y) ** 2)
################################################################################
######## helper function for line segment intersection check #################
# credit:http://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect
################################################################################
def is_zero(val):
return abs(val) < 1e-9
def is_on_segment(p, q, r):
if (q.x <= max(p.x, r.x) and q.x >= min(p.x, r.x) and
q.y <= max(p.y, r.y) and q.y >= min(p.y, r.y)):
return True
return False
def get_orientation(p, q, r):
val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)
if is_zero(val):
# colinear
return 0
elif val > 0:
# clockwise
return 1
else:
# counter-clockwise
return 2
def is_intersect(p1, q1, p2, q2):
o1 = get_orientation(p1, q1, p2)
o2 = get_orientation(p1, q1, q2)
o3 = get_orientation(p2, q2, p1)
o4 = get_orientation(p2, q2, q1)
if (o1 != o2 and o3 != o4):
return True
if (is_zero(o1) and is_on_segment(p1, p2, q1)):
return True
if (is_zero(o2) and is_on_segment(p1, q2, q1)):
return True
if (is_zero(o3) and is_on_segment(p2, p1, q2)):
return True
if (is_zero(o4) and is_on_segment(p2, q1, q2)):
return True
return False
if __name__ == '__main__':
p1, q1 = Node((1, 1)), Node((10, 1))
p2, q2 = Node((1, 2)), Node((10, 2))
print(is_intersect(p1, q1, p2, q2))
p1, q1 = Node((10, 0)), Node((0, 10))
p2, q2 = Node((0, 0)), Node((10, 10))
print(is_intersect(p1, q1, p2, q2))
p1, q1 = Node((-5, -5)), Node((0, 0))
p2, q2 = Node((1, 1)), Node((10, 10))
print(is_intersect(p1, q1, p2, q2))
print(p1[0])
print(p1[1])