commit
08487f7a43
|
@ -13,8 +13,9 @@ def set_axes_equal(fignum):
|
||||||
Make axes of 3D plot have equal scale so that spheres appear as spheres,
|
Make axes of 3D plot have equal scale so that spheres appear as spheres,
|
||||||
cubes as cubes, etc.. This is one possible solution to Matplotlib's
|
cubes as cubes, etc.. This is one possible solution to Matplotlib's
|
||||||
ax.set_aspect('equal') and ax.axis('equal') not working for 3D.
|
ax.set_aspect('equal') and ax.axis('equal') not working for 3D.
|
||||||
Input
|
|
||||||
ax: a matplotlib axis, e.g., as output from plt.gca().
|
Args:
|
||||||
|
fignum (int): An integer representing the figure number for Matplotlib.
|
||||||
"""
|
"""
|
||||||
fig = plt.figure(fignum)
|
fig = plt.figure(fignum)
|
||||||
ax = fig.gca(projection='3d')
|
ax = fig.gca(projection='3d')
|
||||||
|
@ -34,7 +35,21 @@ def set_axes_equal(fignum):
|
||||||
|
|
||||||
|
|
||||||
def ellipsoid(xc, yc, zc, rx, ry, rz, n):
|
def ellipsoid(xc, yc, zc, rx, ry, rz, n):
|
||||||
"""Numpy equivalent of Matlab's ellipsoid function"""
|
"""
|
||||||
|
Numpy equivalent of Matlab's ellipsoid function.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
xc (double): Center of ellipsoid in X-axis.
|
||||||
|
yc (double): Center of ellipsoid in Y-axis.
|
||||||
|
zc (double): Center of ellipsoid in Z-axis.
|
||||||
|
rx (double): Radius of ellipsoid in X-axis.
|
||||||
|
ry (double): Radius of ellipsoid in Y-axis.
|
||||||
|
rz (double): Radius of ellipsoid in Z-axis.
|
||||||
|
n (int): The granularity of the ellipsoid plotted.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple[numpy.ndarray]: The points in the x, y and z axes to use for the surface plot.
|
||||||
|
"""
|
||||||
u = np.linspace(0, 2*np.pi, n+1)
|
u = np.linspace(0, 2*np.pi, n+1)
|
||||||
v = np.linspace(0, np.pi, n+1)
|
v = np.linspace(0, np.pi, n+1)
|
||||||
x = -rx * np.outer(np.cos(u), np.sin(v)).T
|
x = -rx * np.outer(np.cos(u), np.sin(v)).T
|
||||||
|
@ -51,6 +66,14 @@ def plot_covariance_ellipse_3d(axes, origin, P, scale=1, n=8, alpha=0.5):
|
||||||
Based on Maybeck Vol 1, page 366
|
Based on Maybeck Vol 1, page 366
|
||||||
k=2.296 corresponds to 1 std, 68.26% of all probability
|
k=2.296 corresponds to 1 std, 68.26% of all probability
|
||||||
k=11.82 corresponds to 3 std, 99.74% of all probability
|
k=11.82 corresponds to 3 std, 99.74% of all probability
|
||||||
|
|
||||||
|
Args:
|
||||||
|
axes (matplotlib.axes.Axes): Matplotlib axes.
|
||||||
|
origin (gtsam.Point3): The origin in the world frame.
|
||||||
|
P (numpy.ndarray): The marginal covariance matrix of the 3D point which will be represented as an ellipse.
|
||||||
|
scale (float): Scaling factor of the radii of the covariance ellipse.
|
||||||
|
n (int): Defines the granularity of the ellipse. Higher values indicate finer ellipses.
|
||||||
|
alpha (float): Transparency value for the plotted surface in the range [0, 1].
|
||||||
"""
|
"""
|
||||||
k = 11.82
|
k = 11.82
|
||||||
U, S, _ = np.linalg.svd(P)
|
U, S, _ = np.linalg.svd(P)
|
||||||
|
@ -74,7 +97,15 @@ def plot_covariance_ellipse_3d(axes, origin, P, scale=1, n=8, alpha=0.5):
|
||||||
|
|
||||||
|
|
||||||
def plot_pose2_on_axes(axes, pose, axis_length=0.1, covariance=None):
|
def plot_pose2_on_axes(axes, pose, axis_length=0.1, covariance=None):
|
||||||
"""Plot a 2D pose on given axis 'axes' with given 'axis_length'."""
|
"""
|
||||||
|
Plot a 2D pose on given axis `axes` with given `axis_length`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
axes (matplotlib.axes.Axes): Matplotlib axes.
|
||||||
|
pose (gtsam.Pose2): The pose to be plotted.
|
||||||
|
axis_length (float): The length of the camera axes.
|
||||||
|
covariance (numpy.ndarray): Marginal covariance matrix to plot the uncertainty of the estimation.
|
||||||
|
"""
|
||||||
# get rotation and translation (center)
|
# get rotation and translation (center)
|
||||||
gRp = pose.rotation().matrix() # rotation from pose to global
|
gRp = pose.rotation().matrix() # rotation from pose to global
|
||||||
t = pose.translation()
|
t = pose.translation()
|
||||||
|
@ -105,22 +136,47 @@ def plot_pose2_on_axes(axes, pose, axis_length=0.1, covariance=None):
|
||||||
|
|
||||||
|
|
||||||
def plot_pose2(fignum, pose, axis_length=0.1, covariance=None):
|
def plot_pose2(fignum, pose, axis_length=0.1, covariance=None):
|
||||||
"""Plot a 2D pose on given figure with given 'axis_length'."""
|
"""
|
||||||
|
Plot a 2D pose on given figure with given `axis_length`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fignum (int): Integer representing the figure number to use for plotting.
|
||||||
|
pose (gtsam.Pose2): The pose to be plotted.
|
||||||
|
axis_length (float): The length of the camera axes.
|
||||||
|
covariance (numpy.ndarray): Marginal covariance matrix to plot the uncertainty of the estimation.
|
||||||
|
"""
|
||||||
# get figure object
|
# get figure object
|
||||||
fig = plt.figure(fignum)
|
fig = plt.figure(fignum)
|
||||||
axes = fig.gca()
|
axes = fig.gca()
|
||||||
plot_pose2_on_axes(axes, pose, axis_length, covariance)
|
plot_pose2_on_axes(axes, pose, axis_length=axis_length,
|
||||||
|
covariance=covariance)
|
||||||
|
|
||||||
|
|
||||||
def plot_point3_on_axes(axes, point, linespec, P=None):
|
def plot_point3_on_axes(axes, point, linespec, P=None):
|
||||||
"""Plot a 3D point on given axis 'axes' with given 'linespec'."""
|
"""
|
||||||
|
Plot a 3D point on given axis `axes` with given `linespec`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
axes (matplotlib.axes.Axes): Matplotlib axes.
|
||||||
|
point (gtsam.Point3): The point to be plotted.
|
||||||
|
linespec (string): String representing formatting options for Matplotlib.
|
||||||
|
P (numpy.ndarray): Marginal covariance matrix to plot the uncertainty of the estimation.
|
||||||
|
"""
|
||||||
axes.plot([point.x()], [point.y()], [point.z()], linespec)
|
axes.plot([point.x()], [point.y()], [point.z()], linespec)
|
||||||
if P is not None:
|
if P is not None:
|
||||||
plot_covariance_ellipse_3d(axes, point.vector(), P)
|
plot_covariance_ellipse_3d(axes, point.vector(), P)
|
||||||
|
|
||||||
|
|
||||||
def plot_point3(fignum, point, linespec, P=None):
|
def plot_point3(fignum, point, linespec, P=None):
|
||||||
"""Plot a 3D point on given figure with given 'linespec'."""
|
"""
|
||||||
|
Plot a 3D point on given figure with given `linespec`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fignum (int): Integer representing the figure number to use for plotting.
|
||||||
|
point (gtsam.Point3): The point to be plotted.
|
||||||
|
linespec (string): String representing formatting options for Matplotlib.
|
||||||
|
P (numpy.ndarray): Marginal covariance matrix to plot the uncertainty of the estimation.
|
||||||
|
"""
|
||||||
fig = plt.figure(fignum)
|
fig = plt.figure(fignum)
|
||||||
axes = fig.gca(projection='3d')
|
axes = fig.gca(projection='3d')
|
||||||
plot_point3_on_axes(axes, point, linespec, P)
|
plot_point3_on_axes(axes, point, linespec, P)
|
||||||
|
@ -128,10 +184,16 @@ def plot_point3(fignum, point, linespec, P=None):
|
||||||
|
|
||||||
def plot_3d_points(fignum, values, linespec="g*", marginals=None):
|
def plot_3d_points(fignum, values, linespec="g*", marginals=None):
|
||||||
"""
|
"""
|
||||||
Plots the Point3s in 'values', with optional covariances.
|
Plots the Point3s in `values`, with optional covariances.
|
||||||
Finds all the Point3 objects in the given Values object and plots them.
|
Finds all the Point3 objects in the given Values object and plots them.
|
||||||
If a Marginals object is given, this function will also plot marginal
|
If a Marginals object is given, this function will also plot marginal
|
||||||
covariance ellipses for each point.
|
covariance ellipses for each point.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fignum (int): Integer representing the figure number to use for plotting.
|
||||||
|
values (gtsam.Values): Values dictionary consisting of points to be plotted.
|
||||||
|
linespec (string): String representing formatting options for Matplotlib.
|
||||||
|
covariance (numpy.ndarray): Marginal covariance matrix to plot the uncertainty of the estimation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
keys = values.keys()
|
keys = values.keys()
|
||||||
|
@ -142,11 +204,11 @@ def plot_3d_points(fignum, values, linespec="g*", marginals=None):
|
||||||
key = keys.at(i)
|
key = keys.at(i)
|
||||||
point = values.atPoint3(key)
|
point = values.atPoint3(key)
|
||||||
if marginals is not None:
|
if marginals is not None:
|
||||||
P = marginals.marginalCovariance(key);
|
covariance = marginals.marginalCovariance(key)
|
||||||
else:
|
else:
|
||||||
P = None
|
covariance = None
|
||||||
|
|
||||||
plot_point3(fignum, point, linespec, P)
|
plot_point3(fignum, point, linespec, covariance)
|
||||||
|
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
continue
|
continue
|
||||||
|
@ -154,7 +216,15 @@ def plot_3d_points(fignum, values, linespec="g*", marginals=None):
|
||||||
|
|
||||||
|
|
||||||
def plot_pose3_on_axes(axes, pose, axis_length=0.1, P=None, scale=1):
|
def plot_pose3_on_axes(axes, pose, axis_length=0.1, P=None, scale=1):
|
||||||
"""Plot a 3D pose on given axis 'axes' with given 'axis_length'."""
|
"""
|
||||||
|
Plot a 3D pose on given axis `axes` with given `axis_length`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
axes (matplotlib.axes.Axes): Matplotlib axes.
|
||||||
|
point (gtsam.Point3): The point to be plotted.
|
||||||
|
linespec (string): String representing formatting options for Matplotlib.
|
||||||
|
P (numpy.ndarray): Marginal covariance matrix to plot the uncertainty of the estimation.
|
||||||
|
"""
|
||||||
# get rotation and translation (center)
|
# get rotation and translation (center)
|
||||||
gRp = pose.rotation().matrix() # rotation from pose to global
|
gRp = pose.rotation().matrix() # rotation from pose to global
|
||||||
origin = pose.translation().vector()
|
origin = pose.translation().vector()
|
||||||
|
@ -182,13 +252,33 @@ def plot_pose3_on_axes(axes, pose, axis_length=0.1, P=None, scale=1):
|
||||||
|
|
||||||
|
|
||||||
def plot_pose3(fignum, pose, axis_length=0.1, P=None):
|
def plot_pose3(fignum, pose, axis_length=0.1, P=None):
|
||||||
"""Plot a 3D pose on given figure with given 'axis_length'."""
|
"""
|
||||||
|
Plot a 3D pose on given figure with given `axis_length`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fignum (int): Integer representing the figure number to use for plotting.
|
||||||
|
pose (gtsam.Pose3): 3D pose to be plotted.
|
||||||
|
linespec (string): String representing formatting options for Matplotlib.
|
||||||
|
P (numpy.ndarray): Marginal covariance matrix to plot the uncertainty of the estimation.
|
||||||
|
"""
|
||||||
# get figure object
|
# get figure object
|
||||||
fig = plt.figure(fignum)
|
fig = plt.figure(fignum)
|
||||||
axes = fig.gca(projection='3d')
|
axes = fig.gca(projection='3d')
|
||||||
plot_pose3_on_axes(axes, pose, P=P, axis_length=axis_length)
|
plot_pose3_on_axes(axes, pose, P=P,
|
||||||
|
axis_length=axis_length)
|
||||||
|
|
||||||
|
|
||||||
def plot_trajectory(fignum, values, scale=1, marginals=None):
|
def plot_trajectory(fignum, values, scale=1, marginals=None):
|
||||||
|
"""
|
||||||
|
Plot a complete 3D trajectory using poses in `values`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fignum (int): Integer representing the figure number to use for plotting.
|
||||||
|
values (gtsam.Values): Values dict containing the poses.
|
||||||
|
scale (float): Value to scale the poses by.
|
||||||
|
marginals (gtsam.Marginals): Marginalized probability values of the estimation.
|
||||||
|
Used to plot uncertainty bounds.
|
||||||
|
"""
|
||||||
pose3Values = gtsam.allPose3s(values)
|
pose3Values = gtsam.allPose3s(values)
|
||||||
keys = gtsam.KeyVector(pose3Values.keys())
|
keys = gtsam.KeyVector(pose3Values.keys())
|
||||||
lastIndex = None
|
lastIndex = None
|
||||||
|
@ -209,11 +299,12 @@ def plot_trajectory(fignum, values, scale=1, marginals=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if marginals:
|
if marginals:
|
||||||
P = marginals.marginalCovariance(lastKey)
|
covariance = marginals.marginalCovariance(lastKey)
|
||||||
else:
|
else:
|
||||||
P = None
|
covariance = None
|
||||||
|
|
||||||
plot_pose3(fignum, lastPose, P, scale)
|
plot_pose3(fignum, lastPose, P=covariance,
|
||||||
|
axis_length=scale)
|
||||||
|
|
||||||
lastIndex = i
|
lastIndex = i
|
||||||
|
|
||||||
|
@ -223,11 +314,12 @@ def plot_trajectory(fignum, values, scale=1, marginals=None):
|
||||||
try:
|
try:
|
||||||
lastPose = pose3Values.atPose3(lastKey)
|
lastPose = pose3Values.atPose3(lastKey)
|
||||||
if marginals:
|
if marginals:
|
||||||
P = marginals.marginalCovariance(lastKey)
|
covariance = marginals.marginalCovariance(lastKey)
|
||||||
else:
|
else:
|
||||||
P = None
|
covariance = None
|
||||||
|
|
||||||
plot_pose3(fignum, lastPose, P, scale)
|
plot_pose3(fignum, lastPose, P=covariance,
|
||||||
|
axis_length=scale)
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Reference in New Issue