Geometry¶

Classes:

 Distance([pairwise, n_dim, metric, squareform]) Given an n_samples x n_dimensions array, compute pairwise or mean distances Angle([abs, degrees]) Get angle between line formed by two points and horizontal axis IMU_Orientation([use_kalman, invert_gyro]) Compute absolute orientation (roll, pitch) from accelerometer and gyroscope measurements (eg from hardware.i2c.I2C_9DOF ) Rotate([dims, rotation_type, degrees, ...]) Rotate in 3 dimensions using scipy.spatial.transform.Rotation Spheroid([target, source, fit]) Fit and transform 3d coordinates according to some spheroid.

Functions:

 _ellipsoid_func(fit, a, b, c, x, y, z) Ellipsoid equation for use with Ellipsoid.fit()
class Distance(pairwise: bool = False, n_dim: int = 2, metric: str = 'euclidean', squareform: bool = True, *args, **kwargs)[source]

Given an n_samples x n_dimensions array, compute pairwise or mean distances

Parameters
• pairwise (bool) – If False (default), return mean distance. if True, return all distances

• n_dim (int) – number of dimensions (input array will be filtered like input[:,0:n_dim]

• metric (str) – any metric acceptable to :func:`scipy.spatial.distance.pdist

• squareform (bool) – if pairwise is True, if True return square distance matrix, otherwise return compressed distance matrix (dist(X[i], X[j] = y[i*j])

• *args

• **kwargs

Attributes:

Methods:

 process(input)
format_in = {'type': <class 'numpy.ndarray'>}
format_out = {'type': <class 'numpy.ndarray'>}
process(input: numpy.ndarray)[source]
class Angle(abs=True, degrees=True, *args, **kwargs)[source]

Get angle between line formed by two points and horizontal axis

Attributes:

Methods:

 process(input)
format_in = {'type': <class 'numpy.ndarray'>}
format_out = {'type': <class 'float'>}
process(input)[source]
class IMU_Orientation(use_kalman: bool = True, invert_gyro: bool = False, *args, **kwargs)[source]

Compute absolute orientation (roll, pitch) from accelerometer and gyroscope measurements (eg from hardware.i2c.I2C_9DOF )

Uses a timeseries.Kalman filter, and implements [PPT+18] to fuse the sensors

Can be used with accelerometer data only, or with combined accelerometer/gyroscope data for greater accuracy

Parameters
• invert_gyro (bool) – if the gyroscope’s orientation is inverted from accelerometer measurement, multiply gyro readings by -1 before using

• use_kalman (bool) – Whether to use kalman filtering (True, default), or return raw trigonometric transformation of accelerometer readings (if provided, gyroscope readings will be ignored)

Variables

kalman (transform.timeseries.Kalman) – If use_kalman == True , the Kalman Filter.

References

[PPT+18] [ABCO15]

Methods:

 process(accelgyro) Parameters accelgyro (tuple, numpy.ndarray) -- tuple of (accelerometer[x,y,z], gyro[x,y,z]) readings as arrays, or
process(accelgyro: Union[Tuple[numpy.ndarray, numpy.ndarray], numpy.ndarray]) [source]
Parameters

accelgyro (tuple, numpy.ndarray) – tuple of (accelerometer[x,y,z], gyro[x,y,z]) readings as arrays, or an array of just accelerometer[x,y,z]

Returns

filtered [roll, pitch] calculations in degrees

Return type

numpy.ndarray

class Rotate(dims='xyz', rotation_type='euler', degrees=True, inverse='', rotation=None, *args, **kwargs)[source]

Rotate in 3 dimensions using scipy.spatial.transform.Rotation

Parameters
• dims (“xyz”) – string specifying which axes the rotation will be around, eg "xy" , "xyz"`

• rotation_type (str) – Format of rotation input, must be one available to the Rotation class (but currently only euler angles are supported)

• degrees (bool) – whether to output rotation in degrees (True, default) or radians

• inverse (“xyz”) – dimensions in the “rotation” input to Rotate.process() to inverse before applying rotation

• rotation (tuple, list, numpy.ndarray, None) – If supplied, use the same rotation for all processed data. If None, Rotate.process() will expect a tuple of (data, rotation).

Methods:

 process(input) Parameters input (tuple, numpy.ndarray) -- a tuple of (input[x,y,z], rotation[x,y,z]) where input is to be rotated
process(input)[source]
Parameters

input (tuple, numpy.ndarray) – a tuple of (input[x,y,z], rotation[x,y,z]) where input is to be rotated according to the axes in rotation (indicated in Rotate.dims ). If only an input array is provided, a static rotation array must have been provided in the constructor (otherwise the most recent rotation will be used)

Returns

numpy.ndarray - rotated input array

class Spheroid(target=(1, 1, 1, 0, 0, 0), source: tuple = (None, None, None, None, None, None), fit: Optional[numpy.ndarray] = None, *args, **kwargs)[source]

Fit and transform 3d coordinates according to some spheroid.

Eg. for calibrating accelerometer readings by transforming them from their uncalibrated spheroid to the expected sphere with radius == 9.8m/s/s centered at (0,0,0).

Does not estimate/correct for rotation of the spheroid.

Examples

# Calibrate an accelerometer by transforming readings to a 9.8-radius sphere centered at 0 >>> sphere = Spheroid(target=(9.8,9.8,9.8,0,0,0)) # take some readings… # imagine we’re taking them from some sensor idk # say our sensor slightly exaggerates gravity in the z-axis… >>> readings = np.array((0.,0.,10.5)) # fit our object (need >>1 sample) >>> sphere.fit(readings) # transform to proper gravity >>> sphere.process(readings) [0., 0., 9.8]

Parameters
• target (tuple) – parameterization of spheroid to transform to, if none is passed, transform to unit circle centered at (0,0,0). parameterized as:

(a, # radius of x dimension

b, # radius of y dimension c, # radius of z dimension x, # x-offset y, # y-offset z) # z-offset

• source (tuple) – parameterization of spheroid to transform from in the same 6-tuple form as target, if None is passed, assume we will use Spheroid.fit()

• fit (None, numpy.ndarray) – Initialize with values to fit, if None assume fit will be called later.

References

Methods:

 fit(points, **kwargs) Fit a spheroid from a set of noisy measurements process(input) Transform input (x,y,z) points such that points in source are mapped to those in target generate(n[, which, noise]) Generate random points from the ellipsoid
fit(points, **kwargs)[source]

Fit a spheroid from a set of noisy measurements

updates the _scale and _offset private arrays used to manipulate input data

Note

It’s usually important to pass bounds to scipy.optimize.curve_fit() !!! passed as a 2-tuple of ((min_a, min_b, ...), (max_a, max_b...)) In particular such that a, b, and c are positive. If no bounds are passed, assume at least that much.

Parameters
Returns

parameters of fit ellipsoid (a,b,c,x,y,z)

Return type

tuple

process(input: numpy.ndarray)[source]

Transform input (x,y,z) points such that points in source are mapped to those in target

Parameters

input (numpy.ndarray) – x, y, and z coordinates

Returns

coordinates transformed according to the spheroid requested

Return type

numpy.ndarray

generate(n: int, which: str = 'source', noise: float = 0)[source]

Generate random points from the ellipsoid

Parameters
• n (int) – number of points to generate

• which (‘str’) – which spheroid to generate from? (‘source’ - default, or ‘target’)

• noise (float) – noise to add to points

Returns

(n, 3) array of generated points

Return type

numpy.ndarray

_ellipsoid_func(fit, a, b, c, x, y, z)[source]

Ellipsoid equation for use with Ellipsoid.fit()

Parameters
• fit (numpy.ndarray) – (M, 3) array of x,y,z points to fit

• a (float) – X-scale parameter to fit

• b (float) – Y-scale parameter to fit

• c (float) – Z-scale parameter to fit

• x (float) – X-offset parameter to fit

• y (float) – Y-offset parameter to fit

• z (float) – Z-offset parameter to fit

Returns

result of ellipsoid function, minimize parameters to == 1

Return type

float