41 from math
import sin, cos
43 import matplotlib.pyplot
as plt
44 import matplotlib.animation
as animation
45 import matplotlib.patches
as patches
49 def readWorldFile(worldFile):
50 handle = open(worldFile,
"r")
52 dataMap = yaml.safe_load(handle)
56 xlower = float(dataMap[
"bounds"][
"x"][
"lower"])
57 xupper = float(dataMap[
"bounds"][
"x"][
"upper"])
58 ylower = float(dataMap[
"bounds"][
"y"][
"lower"])
59 yupper = float(dataMap[
"bounds"][
"y"][
"upper"])
61 bounds = [[xlower, xupper], [ylower, yupper]]
65 if "obstacles" in dataMap:
66 for r
in dataMap[
"obstacles"]:
74 def readPathFile(pathFile):
76 lines = [line.rstrip()
for line
in open(pathFile)
if len(line.rstrip()) > 0]
80 metadata = metadata.split(
" ")
81 if len(metadata) != 5:
83 "Malformed path file. Expected first line with # links, link length, originX, originY, xySlices"
86 numLinks = int(metadata[0])
87 linkLength = float(metadata[1])
88 origin = (float(metadata[2]), float(metadata[3]))
89 slices = int(metadata[4])
94 entries = l.split(
" ")
95 if len(entries) != numLinks:
97 "Malformed path file. Path entries must have length = # links"
99 config = [float(e)
for e
in entries]
102 return numLinks, linkLength, origin, path, slices
105 def plotPolygon(axes, data, color, alpha=1.0, edgecolor=None):
110 coords = d[k].strip()
111 if coords.startswith(
"("):
112 coords = coords[1:-1]
113 coords = coords.strip().split(
",")
114 pt = [float(coords[0]), float(coords[1])]
118 raise RuntimeError(
'Expected "vertex", but got ', k)
121 arr = np.array(points)
124 arr, facecolor=color, alpha=alpha, fill=
True, edgecolor=edgecolor
129 def plotObstacles(axes, obstacles, bounds):
130 for k, v
in obstacles.items():
133 plotPolygon(axes, o,
"0.4", edgecolor=
"0.4")
135 raise RuntimeError(
"Unknown geometry type: ", k)
137 plt.axis([bounds[0][0], bounds[0][1], bounds[1][0], bounds[1][1]])
140 def plotChain(axes, angles, origin, color="blue"):
145 linkLength = 1.0 / len(angles)
149 xN = x + (cos(angle) * linkLength)
150 yN = y + (sin(angle) * linkLength)
152 axes.plot([x, xN], [y, yN],
"-", color=color)
158 def plotChainFrame(frame_num, ax, path, obstacles, bounds, origin, rate, slices):
160 plotObstacles(ax, obstacles, bounds)
164 configuration = path[0]
165 elif frame_num >= len(path) + rate:
166 configuration = path[-1]
168 configuration = path[frame_num - rate]
170 plotChain(ax, configuration, origin)
173 def AnimatePath(obstacles, bounds, numLinks, linkLength, origin, path, slices):
178 numFrames = len(path)
179 anim = animation.FuncAnimation(
182 fargs=[axes, path, obstacles, bounds, origin, slices, framerate],
183 frames=numFrames + (framerate * 2),
184 interval=(1.0 / framerate) * 1000,
188 filename =
"animation.mp4"
189 anim.save(filename, fps=framerate)
192 if __name__ ==
"__main__":
193 worldFile =
"./world.yaml"
194 pathFile =
"./manipulator_path.txt"
196 obs, bounds = readWorldFile(worldFile)
197 numLinks, linkLength, origin, path, slices = readPathFile(pathFile)
199 print(
"Creating animation for planar kinematic chain... ")
200 AnimatePath(obs, bounds, numLinks, linkLength, origin, path, slices)