40 from pathlib
import Path
41 from tempfile
import TemporaryDirectory
43 import matplotlib.pyplot
as plt
45 from skspatial.objects
import Sphere
46 from subprocess
import run
51 def updateProjection(ax, axi, projection='3d', fig=None):
54 rows, cols, start, stop = axi.get_subplotspec().get_geometry()
55 ax.flat[start].remove()
56 ax.flat[start] = fig.add_subplot(rows, cols, start+1, projection=projection)
60 def readPath(path_file):
61 return np.array([[float(x)
for x
in line.split()] \
62 for line
in open(path_file).readlines()
68 def getPath(exec_path, **kwargs):
69 with TemporaryDirectory()
as tmpdir:
70 path_file = Path(tmpdir) /
"path.dat"
71 demo_args =
' '.join([f
'--{key} {value}' for key, value
in kwargs.items()])
72 result = run(f
'{exec_path} {demo_args} --savepath {path_file}', shell=
True, capture_output=
True)
73 print(result.stdout.decode(
"utf-8"))
74 return readPath(path_file)
80 def plotPath(path, radius, spheres=True):
81 fig, axs = plt.subplots(3, 1, gridspec_kw={
'height_ratios': [6, 1, 1]})
82 updateProjection(axs, axs[0])
83 axs[0].plot(path[:,0], path[:,1], path[:,2], color=
'k')
84 diameter = 2. * radius
85 n = int(10 // diameter)
87 for xi
in range(-n, n):
88 for yi
in range(-n, n):
89 for zi
in range(-n, n):
90 sphere = Sphere([xi*diameter + radius, yi*diameter + radius, zi*diameter + radius], .75*radius)
91 sphere.plot_3d(axs[0], alpha=.2)
92 axs[0].set_xlabel(
'X')
93 axs[0].set_ylabel(
'Y')
94 axs[0].set_zlabel(
'Z')
95 axs[0].set_aspect(
'equal')
96 px, = axs[1].plot(path[:,0], color=cmap(0), label=
'X')
97 py, = axs[1].plot(path[:,1], color=cmap(1), label=
'Y')
98 pz, = axs[1].plot(path[:,2], color=cmap(2), label=
'Z')
99 axs[1].legend(handles=[px, py, pz])
101 ppitch, = axs[2].plot(path[:,3], color=cmap(0), label=
'pitch')
102 pyaw, = axs[2].plot(path[:,4], color=cmap(1), label=
'yaw')
103 axs[2].legend(handles=[ppitch, pyaw])
105 axs[2].plot(path[:,3], color=cmap(0), label=
'yaw')
106 axs[2].set_ylabel(
'yaw')
112 def findExecutable(exec_name='demo_DubinsAirplane'):
114 executable = shutil.which(exec_name)
117 if executable ==
None:
118 for match
in Path(__file__).parent.glob(f
'**/{exec_name}'):
119 executable = str(match.resolve())
122 for match
in Path(__file__).parent.parent.glob(f
'**/{exec_name}'):
123 executable = str(match.resolve())
126 for match
in Path(__file__).parent.parent.parent.glob(f
'**/{exec_name}'):
127 executable = str(match.resolve())
130 print(f
"Could not find the {exec_name} executable; please update the path in this script")
134 if __name__ ==
"__main__":
136 exec_path = findExecutable()
139 path = getPath(exec_path,
149 plotPath(path, radius)