Skip to content

Commit f94dfa1

Browse files
committed
visualize potential field
1 parent 6a709c8 commit f94dfa1

File tree

4 files changed

+70
-20
lines changed

4 files changed

+70
-20
lines changed

PathPlanning/PotentialField/PotentialField.py

+18-3
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ def plan(self, start, target):
4545

4646
def calculate_attractive_potential(self, pos, target):
4747
if pos.dist(target) <= self.da:
48-
return 0.5 * self.ka * pos.dist(target) ** 2
48+
return self.ka * pos.dist(target) ** 2
4949
else:
50-
return self.ka * (self.da * pos.dist(target) - 0.5 * self.da ** 2)
50+
return self.ka * (2 * self.da * pos.dist(target) - self.da ** 2)
5151

5252
def calculate_repulsive_potential(self, pos):
5353
pr = 0
@@ -56,4 +56,19 @@ def calculate_repulsive_potential(self, pos):
5656
return float('inf')
5757
if obs.dist(pos) <= self.dr:
5858
pr = pr + 0.5 * self.kr * (1/obs.dist(pos) - 1/self.dr) ** 2
59-
return pr
59+
return pr
60+
61+
def calculate_potential_force(self, pos, target):
62+
# attractive force(simple version)
63+
attractive_force = Vector(pos.x - target.x, pos.y - target.y) * (-self.ka)
64+
# repulsive force
65+
repulsive_force = Vector(0, 0)
66+
for obs in self.map.obstacles:
67+
if obs.dist(pos) == 0:
68+
repulsive_force += Vector(float('inf'), float('inf'))
69+
elif obs.dist(pos) <= self.dr:
70+
repulsive_force += Vector(pos.x - obs.pos.x, pos.y - obs.pos.y) * self.kr * (1/obs.dist(pos) - 1/self.dr) * ((1/obs.dist(pos))**2) * (1/obs.dist(pos))
71+
# sum up
72+
potential_force = attractive_force + repulsive_force
73+
74+
return potential_force

PathPlanning/PotentialField/run.py

+38-11
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,46 @@
22
from PathPlanning.utils import *
33

44
def main():
5-
map = Map(left=0, right=640, top=480, down=0)
5+
map = Map(left=0, right=640, top=480, down=0, refresh=False)
66
map.add_obstacle(CircleObstacle(pos=Point(200, 200), radius=50))
7-
map.add_obstacle(CircleObstacle(pos=Point(350, 250), radius=30))
8-
map.add_obstacle(CircleObstacle(pos=Point(450, 400), radius=80))
9-
potentialFieldPlanner = PotentialFieldPlanner(map=map, iterations=1e4, step_size=2, ka=1, kr=1e4, da=10, dr=100)
10-
start = Point(0, 0)
11-
end = Point(640, 480)
7+
map.add_obstacle(CircleObstacle(pos=Point(400, 300), radius=40))
8+
# map.add_obstacle(CircleObstacle(pos=Point(450, 400), radius=80))
9+
potentialFieldPlanner = PotentialFieldPlanner(map=map, iterations=1e4, step_size=2, ka=1, kr=1e7, da=10, dr=50)
10+
start = Point(100, 100)
11+
end = Point(500, 250)
12+
potentialFieldPlanner.plan(start=start, target=end)
13+
map.add_geometry(type='point', pos=start.tuple(), size=10, color=(100, 0, 0))
14+
map.add_geometry(type='point', pos=end.tuple(), size=10, color=(0, 100, 0))
15+
for i in range(len(potentialFieldPlanner.finalPath)-1):
16+
map.add_geometry(type='line', start=potentialFieldPlanner.finalPath[i].tuple(), end=potentialFieldPlanner.finalPath[i+1].tuple(), color=(0, 100, 0))
17+
# draw potential force
18+
for x in range(0, map.right+1, 10):
19+
for y in range(0, map.top+1, 10):
20+
force = potentialFieldPlanner.calculate_potential_force(Point(x, y), end)
21+
force_start = Point(x, y)
22+
force_end = force_start + Polar2Vector(5, force.dir())
23+
# map.add_geometry(type='point', pos=(x,y), size=3, color=(0, 0, 100))
24+
map.add_geometry(type='line', start=force_start.tuple(), end=force_end.tuple(), width=2, color=(120,50,80))
25+
# draw potential line
26+
potential_lines = [i for i in range(0, 20000, 1000)]
27+
for x in range(0, map.right+1, 1):
28+
for y in range(0, map.top+1, 1):
29+
valid = True
30+
for obs in map.obstacles:
31+
if obs.dist(Point(x, y)) <= 32:
32+
valid = False
33+
34+
if valid:
35+
offset = 20
36+
else:
37+
offset = 100
38+
potential = potentialFieldPlanner.calculate_attractive_potential(Point(x, y), end) + potentialFieldPlanner.calculate_repulsive_potential(Point(x, y))
39+
# print(potential, potentialFieldPlanner.calculate_attractive_potential(Point(x, y), end))
40+
for p in potential_lines:
41+
if math.fabs(potential-p) < offset:
42+
map.add_geometry(type='point', pos=(x,y), size=1, color=(0, 0, 100))
43+
1244
while map.is_open:
13-
potentialFieldPlanner.plan(start=start, target=end)
14-
map.add_geometry(type='point', pos=start.tuple(), size=30, color=(100, 0, 0))
15-
map.add_geometry(type='point', pos=end.tuple(), size=30, color=(0, 100, 0))
16-
for i in range(len(potentialFieldPlanner.finalPath)-1):
17-
map.add_geometry(type='line', start=potentialFieldPlanner.finalPath[i].tuple(), end=potentialFieldPlanner.finalPath[i+1].tuple(), color=(0, 100, 0))
1845
map.render()
1946

2047
if __name__ == '__main__':

PathPlanning/geometry.py

+6
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,18 @@ def __init__(self, x, y):
2929
self.x = x
3030
self.y = y
3131

32+
def dir(self):
33+
return math.atan2(self.y, self.x)
34+
3235
def mod(self):
3336
return math.sqrt(pow(self.x, 2) + pow(self.y, 2))
3437

3538
def __mul__(self, other):
3639
return Vector(other*self.x, other*self.y)
3740

41+
def __add__(self, other):
42+
return Vector(self.x+other.x, self.y+other.y)
43+
3844

3945
def Polar2Vector(dist, theta):
4046
return Vector(dist*math.cos(theta), dist*math.sin(theta))

PathPlanning/utils.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,14 @@ def check_collision(self, other, avoidDist):
8787

8888

8989
class Map(Viewer):
90-
def __init__(self, top, down, left, right):
90+
def __init__(self, top, down, left, right, refresh=True):
9191
self.top = max(top, down)
9292
self.down = min(top, down)
9393
self.left = min(left, right)
9494
self.right = max(left, right)
9595
self.length = math.fabs(left - right)
9696
self.width = math.fabs(top - down)
97+
self.refresh = refresh
9798
Viewer.__init__(self, width=self.length, height=self.width)
9899
self.obstacles = []
99100

@@ -115,16 +116,17 @@ def draw(self):
115116
# self.draw_line(start=(self.left, self.top), end=(self.right, self.top), lineWidth=5)
116117
# self.draw_line(start=(self.right, self.top), end=(self.right, self.down), lineWidth=5)
117118
# self.draw_line(start=(self.right, self.down), end=(self.left, self.down), lineWidth=5)
119+
# draw geoms
120+
for geom in self.geoms:
121+
geom.render()
118122
# draw obstacles
119123
for obs in self.obstacles:
120124
if obs.type() == 'circle':
121125
self.draw_circle(pos=obs.pos.tuple(), radius=obs.radius)
122126
elif obs.type() == 'rectangle':
123-
self.draw_polygon(points=obs.vertex(), )
124-
# draw geoms
125-
for geom in self.geoms:
126-
geom.render()
127-
self.geoms = []
127+
self.draw_polygon(points=obs.vertex(), filled=True)
128+
if self.refresh:
129+
self.geoms = []
128130

129131

130132
class PathPlanner(object):

0 commit comments

Comments
 (0)