-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathvisualizer.py
More file actions
97 lines (81 loc) · 3.69 KB
/
Copy pathvisualizer.py
File metadata and controls
97 lines (81 loc) · 3.69 KB
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
import matplotlib
matplotlib.use('Agg') # No need to show it
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation, PillowWriter # For gif
import pdb # Use this for debugging python!
import argparse
###############################################################
################### Util Functions Below ######################
def readMap(mapfile):
""" Input: mapfile path
Output: 2D numpy array with binary values based on the map
"""
with open(mapfile) as f:
line = f.readline() # e.g. "height 50"
height = int(line.split(' ')[1])
line = f.readline() # e.g. "width 50"
width = int(line.split(' ')[1])
mapdata = np.array([line.rstrip().split(" ") for line in f])
mapdata.reshape((width,height))
mapdata = mapdata.astype(int)
return mapdata
###############################################################
################### Main Functions Below ######################
def createSingleFrame(i, mapData, allPoses, includePrevious):
""" Input: frameIndex (int)
mapData (2D numpy)
allPoses (list of numpy or 2D numpy)
includePrevious (boolean)
Output:
Returns matplotlib artists for gif creation.
Note: Feel free to modify this function based off your needs.
"""
if not includePrevious:
plt.clf()
curPose = allPoses[i]
artists = [] # Need to save plots into artists for animating
## Show obstacles, need to transpose as C++ map is transposed as well
artists.append(plt.imshow(1-mapData.T, cmap=plt.cm.gray))
## Base position
xBase = mapData.shape[0]//2
yBase = 0
linkLength = 10
xs, ys = [xBase], [yBase]
for i in range(0, len(curPose)):
xs.append(xs[i] + linkLength*np.cos(curPose[i]))
ys.append(ys[i] + linkLength*np.sin(curPose[i]))
xs = np.array(xs)
ys = np.array(ys)
artists.append(plt.plot(xs, ys, color="g", linewidth="2"))
artists.append(plt.plot(xs[0], ys[0], 'go', markersize=10, label='Base Position'))
artists.append(plt.plot(xs[-1], ys[-1], 'ro', markersize=5, label='End Effector Position'))
return artists
def viz():
""" Main function for creating a gif give the solution file path and gif args.
Note: Feel free to change anything in this function or file. This was made
solely for your convience. :-)
"""
parser = argparse.ArgumentParser()
parser.add_argument("fileWithSolution", help="filepath with solution", type=str, default="output.txt")
parser.add_argument("--gifFilepath", help="filepath for gif", type=str, default="output.gif", required=False)
parser.add_argument("--fps", help="frames per second", type=int, default=4, required=False)
parser.add_argument("--incPrev", help="include previous poses (1), else don't (0). Note this slows gif creation speed",
type=int, default=0, required=False)
args = parser.parse_args()
assert(args.gifFilepath.endswith(".gif")) # Make sure it ends with a .gif extension
assert(args.incPrev == 0 or args.incPrev == 1) # 0 is don't include, 1 is include
with open(args.fileWithSolution) as f:
line = f.readline().rstrip() # filepath of the map
mapData = readMap(line)
solution = []
for line in f:
solution.append(line.split(",")[:-1]) # :-1 to drop trailing comma
solution = np.asarray(solution).astype(float)
numFrames = len(solution)
fig = plt.figure()
ani = FuncAnimation(fig, createSingleFrame, repeat=False,
frames=numFrames, fargs=(mapData, solution, args.incPrev))
ani.save(args.gifFilepath, dpi=300, writer=PillowWriter(fps=args.fps))
if __name__ == "__main__":
viz()