4 Fit a plane to the fiducials in the map as a quantitative test of the 5 map quality. Assumes they are all on a ceiling 8 import matplotlib.pyplot
as plt
9 from mpl_toolkits.mplot3d
import Axes3D
15 from standard_fit
import standard_fit, distance, projection
33 map_file = os.environ[
"HOME"] +
"/.ros/slam/map.txt" 34 parser = argparse.ArgumentParser()
35 parser.add_argument(
"--map_file", help=
"Name of map file ", default=map_file, type=str)
36 parser.add_argument(
"--adjust", help=
"Adjust points to fit plane", action=
"store_true")
37 args = parser.parse_args()
48 with open(args.map_file)
as file:
49 lines = file.readlines()
52 ids.append(int(parts[0]))
53 points.append([float(parts[1]), float(parts[2]), float(parts[3])])
54 roll.append(float(parts[4]))
55 pitch.append(float(parts[5]))
56 other.append(
" ".join(parts[6:]))
61 points = np.array(points)
62 ax = plt.subplot(111, projection=
'3d')
67 ax.scatter(xs, ys, zs, color=
'b')
70 print(
"Plane normal: %s" % N)
74 xs = fixed_points[:,0]
75 ys = fixed_points[:,1]
76 zs = fixed_points[:,2]
77 ax.scatter(xs, ys, zs, color=
'r') 79 errors = distance(points, C, N) 80 residual = np.linalg.norm(errors) 82 slopex = math.atan2(N[0], N[2]) * 180.0 / math.pi 83 slopey = math.atan2(N[1], N[2]) * 180.0 / math.pi 84 print("slope: %f deg in X %f deg in Y" % (slopex, slopey))
86 print(
"residual: %f" % residual)
92 X,Y = np.meshgrid(np.arange(xlim[0], xlim[1]),
93 np.arange(ylim[0], ylim[1]))
95 Z = (-N[0] * X - N[1] * Y - D) / N[2]
96 ax.plot_wireframe(X,Y,Z, color=
'k')
105 print(
"Saving adjusted map")
106 os.rename(map_file, map_file +
".bak")
107 with open(map_file,
'w')
as file:
108 for i
in range(len(errors)):
109 file.write(
"%d %f %f %f %f %f %s\n" % (ids[i], xs[i], ys[i], zs[i],
def closest_angle(old, new)