41from math
import sin, cos
43import matplotlib.pyplot
as plt
44import matplotlib.animation
as animation
45import matplotlib.patches
as patches
50def readWorldFile(worldFile):
51 handle = open(worldFile,
"r")
53 dataMap = yaml.safe_load(handle)
57 xlower = float(dataMap[
"bounds"][
"x"][
"lower"])
58 xupper = float(dataMap[
"bounds"][
"x"][
"upper"])
59 ylower = float(dataMap[
"bounds"][
"y"][
"lower"])
60 yupper = float(dataMap[
"bounds"][
"y"][
"upper"])
62 bounds = [[xlower, xupper], [ylower, yupper]]
66 if "obstacles" in dataMap:
67 for r
in dataMap[
"obstacles"]:
75def readPathFile(pathFile):
77 lines = [line.rstrip()
for line
in open(pathFile)
if len(line.rstrip()) > 0]
81 metadata = metadata.split(
" ")
82 if len(metadata) != 5:
84 "Malformed path file. Expected first line with # links, link length, originX, originY, xySlices"
87 numLinks = int(metadata[0])
88 linkLength = float(metadata[1])
89 origin = (float(metadata[2]), float(metadata[3]))
90 slices = int(metadata[4])
95 entries = l.split(
" ")
96 if len(entries) != numLinks:
98 "Malformed path file. Path entries must have length = # links"
100 config = [float(e)
for e
in entries]
103 return numLinks, linkLength, origin, path, slices
106def plotPolygon(axes, data, color, alpha=1.0, edgecolor=None):
111 coords = d[k].strip()
112 if coords.startswith(
"("):
113 coords = coords[1:-1]
114 coords = coords.strip().split(
",")
115 pt = [float(coords[0]), float(coords[1])]
119 raise RuntimeError(
'Expected "vertex", but got ', k)
122 arr = np.array(points)
125 arr, facecolor=color, alpha=alpha, fill=
True, edgecolor=edgecolor
130def plotObstacles(axes, obstacles, bounds):
131 for k, v
in obstacles.items():
134 plotPolygon(axes, o,
"0.4", edgecolor=
"0.4")
136 raise RuntimeError(
"Unknown geometry type: ", k)
138 plt.axis([bounds[0][0], bounds[0][1], bounds[1][0], bounds[1][1]])
141def plotChain(axes, angles, origin, color="blue"):
146 linkLength = 1.0 / len(angles)
150 xN = x + (cos(angle) * linkLength)
151 yN = y + (sin(angle) * linkLength)
153 axes.plot([x, xN], [y, yN],
"-", color=color)
159def plotChainFrame(frame_num, ax, path, obstacles, bounds, origin, rate, slices):
161 plotObstacles(ax, obstacles, bounds)
165 configuration = path[0]
166 elif frame_num >= len(path) + rate:
167 configuration = path[-1]
169 configuration = path[frame_num - rate]
171 plotChain(ax, configuration, origin)
174def AnimatePath(obstacles, bounds, numLinks, linkLength, origin, path, slices):
179 numFrames = len(path)
180 anim = animation.FuncAnimation(
183 fargs=[axes, path, obstacles, bounds, origin, slices, framerate],
184 frames=numFrames + (framerate * 2),
185 interval=(1.0 / framerate) * 1000,
189 filename =
"animation.mp4"
190 anim.save(filename, fps=framerate)
193if __name__ ==
"__main__":
194 worldFile =
"./world.yaml"
195 pathFile =
"./manipulator_path.txt"
197 obs, bounds = readWorldFile(worldFile)
198 numLinks, linkLength, origin, path, slices = readPathFile(pathFile)
200 print(
"Creating animation for planar kinematic chain... ")
201 AnimatePath(obs, bounds, numLinks, linkLength, origin, path, slices)