diff --git a/gen/cpp/sym/factors/inverse_range_landmark_atan_reprojection_error_factor.h b/gen/cpp/sym/factors/inverse_range_landmark_atan_reprojection_error_factor.h index 330c2b78d..3526f579a 100644 --- a/gen/cpp/sym/factors/inverse_range_landmark_atan_reprojection_error_factor.h +++ b/gen/cpp/sym/factors/inverse_range_landmark_atan_reprojection_error_factor.h @@ -20,11 +20,15 @@ namespace sym { * landmark is fixed in the source camera and always has residual 0 there (this 0 residual is not * returned, only the residual in the target camera is returned). * - * The norm of the residual is whitened using the Barron noise model. Whitening each component of - * the reprojection error separately would result in rejecting individual components as outliers. - * Instead, we minimize the whitened norm of the full reprojection error for each point. See the - * docstring for `NoiseModel.whiten_norm` for more information on this, and the docstring of - * `BarronNoiseModel` for more information on the noise model. + * The norm of the residual is whitened using the + * :class:`BarronNoiseModel `. Whitening each + * component of the reprojection error separately would result in rejecting individual components + * as outliers. Instead, we minimize the whitened norm of the full reprojection error for each + * point. See + * :meth:`ScalarNoiseModel.whiten_norm ` + * for more information on this, and + * :class:`BarronNoiseModel ` for more information on + * the noise model. * * Args: * source_pose: The pose of the source camera @@ -35,10 +39,13 @@ namespace sym { * source_pixel: The location of the landmark in the source camera * target_pixel: The location of the correspondence in the target camera * weight: The weight of the factor - * gnc_mu: The mu convexity parameter for the Barron noise model - * gnc_scale: The scale parameter for the Barron noise model + * gnc_mu: The mu convexity parameter for the + * :class:`BarronNoiseModel ` + * gnc_scale: The scale parameter for the + * :class:`BarronNoiseModel ` * epsilon: Small positive value - * camera_model_class: The subclass of CameraCal to use as the camera model + * camera_model_class: The subclass of :class:`CameraCal ` + * to use as the camera model * * Outputs: * res: 2dof residual of the reprojection diff --git a/gen/cpp/sym/factors/inverse_range_landmark_double_sphere_reprojection_error_factor.h b/gen/cpp/sym/factors/inverse_range_landmark_double_sphere_reprojection_error_factor.h index aff810232..09ce2b134 100644 --- a/gen/cpp/sym/factors/inverse_range_landmark_double_sphere_reprojection_error_factor.h +++ b/gen/cpp/sym/factors/inverse_range_landmark_double_sphere_reprojection_error_factor.h @@ -20,11 +20,15 @@ namespace sym { * landmark is fixed in the source camera and always has residual 0 there (this 0 residual is not * returned, only the residual in the target camera is returned). * - * The norm of the residual is whitened using the Barron noise model. Whitening each component of - * the reprojection error separately would result in rejecting individual components as outliers. - * Instead, we minimize the whitened norm of the full reprojection error for each point. See the - * docstring for `NoiseModel.whiten_norm` for more information on this, and the docstring of - * `BarronNoiseModel` for more information on the noise model. + * The norm of the residual is whitened using the + * :class:`BarronNoiseModel `. Whitening each + * component of the reprojection error separately would result in rejecting individual components + * as outliers. Instead, we minimize the whitened norm of the full reprojection error for each + * point. See + * :meth:`ScalarNoiseModel.whiten_norm ` + * for more information on this, and + * :class:`BarronNoiseModel ` for more information on + * the noise model. * * Args: * source_pose: The pose of the source camera @@ -35,10 +39,13 @@ namespace sym { * source_pixel: The location of the landmark in the source camera * target_pixel: The location of the correspondence in the target camera * weight: The weight of the factor - * gnc_mu: The mu convexity parameter for the Barron noise model - * gnc_scale: The scale parameter for the Barron noise model + * gnc_mu: The mu convexity parameter for the + * :class:`BarronNoiseModel ` + * gnc_scale: The scale parameter for the + * :class:`BarronNoiseModel ` * epsilon: Small positive value - * camera_model_class: The subclass of CameraCal to use as the camera model + * camera_model_class: The subclass of :class:`CameraCal ` + * to use as the camera model * * Outputs: * res: 2dof residual of the reprojection diff --git a/gen/cpp/sym/factors/inverse_range_landmark_equirectangular_reprojection_error_factor.h b/gen/cpp/sym/factors/inverse_range_landmark_equirectangular_reprojection_error_factor.h index 61aa10a16..b859085a5 100644 --- a/gen/cpp/sym/factors/inverse_range_landmark_equirectangular_reprojection_error_factor.h +++ b/gen/cpp/sym/factors/inverse_range_landmark_equirectangular_reprojection_error_factor.h @@ -20,11 +20,15 @@ namespace sym { * landmark is fixed in the source camera and always has residual 0 there (this 0 residual is not * returned, only the residual in the target camera is returned). * - * The norm of the residual is whitened using the Barron noise model. Whitening each component of - * the reprojection error separately would result in rejecting individual components as outliers. - * Instead, we minimize the whitened norm of the full reprojection error for each point. See the - * docstring for `NoiseModel.whiten_norm` for more information on this, and the docstring of - * `BarronNoiseModel` for more information on the noise model. + * The norm of the residual is whitened using the + * :class:`BarronNoiseModel `. Whitening each + * component of the reprojection error separately would result in rejecting individual components + * as outliers. Instead, we minimize the whitened norm of the full reprojection error for each + * point. See + * :meth:`ScalarNoiseModel.whiten_norm ` + * for more information on this, and + * :class:`BarronNoiseModel ` for more information on + * the noise model. * * Args: * source_pose: The pose of the source camera @@ -35,10 +39,13 @@ namespace sym { * source_pixel: The location of the landmark in the source camera * target_pixel: The location of the correspondence in the target camera * weight: The weight of the factor - * gnc_mu: The mu convexity parameter for the Barron noise model - * gnc_scale: The scale parameter for the Barron noise model + * gnc_mu: The mu convexity parameter for the + * :class:`BarronNoiseModel ` + * gnc_scale: The scale parameter for the + * :class:`BarronNoiseModel ` * epsilon: Small positive value - * camera_model_class: The subclass of CameraCal to use as the camera model + * camera_model_class: The subclass of :class:`CameraCal ` + * to use as the camera model * * Outputs: * res: 2dof residual of the reprojection diff --git a/gen/cpp/sym/factors/inverse_range_landmark_linear_reprojection_error_factor.h b/gen/cpp/sym/factors/inverse_range_landmark_linear_reprojection_error_factor.h index 9d7b2e993..7bf99b9c6 100644 --- a/gen/cpp/sym/factors/inverse_range_landmark_linear_reprojection_error_factor.h +++ b/gen/cpp/sym/factors/inverse_range_landmark_linear_reprojection_error_factor.h @@ -20,11 +20,15 @@ namespace sym { * landmark is fixed in the source camera and always has residual 0 there (this 0 residual is not * returned, only the residual in the target camera is returned). * - * The norm of the residual is whitened using the Barron noise model. Whitening each component of - * the reprojection error separately would result in rejecting individual components as outliers. - * Instead, we minimize the whitened norm of the full reprojection error for each point. See the - * docstring for `NoiseModel.whiten_norm` for more information on this, and the docstring of - * `BarronNoiseModel` for more information on the noise model. + * The norm of the residual is whitened using the + * :class:`BarronNoiseModel `. Whitening each + * component of the reprojection error separately would result in rejecting individual components + * as outliers. Instead, we minimize the whitened norm of the full reprojection error for each + * point. See + * :meth:`ScalarNoiseModel.whiten_norm ` + * for more information on this, and + * :class:`BarronNoiseModel ` for more information on + * the noise model. * * Args: * source_pose: The pose of the source camera @@ -35,10 +39,13 @@ namespace sym { * source_pixel: The location of the landmark in the source camera * target_pixel: The location of the correspondence in the target camera * weight: The weight of the factor - * gnc_mu: The mu convexity parameter for the Barron noise model - * gnc_scale: The scale parameter for the Barron noise model + * gnc_mu: The mu convexity parameter for the + * :class:`BarronNoiseModel ` + * gnc_scale: The scale parameter for the + * :class:`BarronNoiseModel ` * epsilon: Small positive value - * camera_model_class: The subclass of CameraCal to use as the camera model + * camera_model_class: The subclass of :class:`CameraCal ` + * to use as the camera model * * Outputs: * res: 2dof residual of the reprojection diff --git a/gen/cpp/sym/factors/inverse_range_landmark_polynomial_reprojection_error_factor.h b/gen/cpp/sym/factors/inverse_range_landmark_polynomial_reprojection_error_factor.h index 004f7d15e..dbd899e96 100644 --- a/gen/cpp/sym/factors/inverse_range_landmark_polynomial_reprojection_error_factor.h +++ b/gen/cpp/sym/factors/inverse_range_landmark_polynomial_reprojection_error_factor.h @@ -17,14 +17,18 @@ namespace sym { * comparing it against the correspondence. * * The landmark is specified as a camera point in the source camera with an inverse range; this - * means the landmark is fixed in the source camera and always has residual 0 there (this 0 residual - * is not returned, only the residual in the target camera is returned). + * means the landmark is fixed in the source camera and always has residual 0 there (this 0 + * residual is not returned, only the residual in the target camera is returned). * - * The norm of the residual is whitened using the Barron noise model. Whitening each component of - * the reprojection error separately would result in rejecting individual components as outliers. - * Instead, we minimize the whitened norm of the full reprojection error for each point. See the - * docstring for `NoiseModel.whiten_norm` for more information on this, and the docstring of - * `BarronNoiseModel` for more information on the noise model. + * The norm of the residual is whitened using the + * :class:`BarronNoiseModel `. Whitening each + * component of the reprojection error separately would result in rejecting individual components + * as outliers. Instead, we minimize the whitened norm of the full reprojection error for each + * point. See + * :meth:`ScalarNoiseModel.whiten_norm ` + * for more information on this, and + * :class:`BarronNoiseModel ` for more information on + * the noise model. * * Args: * source_pose: The pose of the source camera @@ -32,10 +36,16 @@ namespace sym { * target_calibration_storage: The storage vector of the target spherical camera calibration * source_inverse_range: The inverse range of the landmark in the source camera * p_camera_source: The location of the landmark in the source camera coordinate, will be - * normalized target_pixel: The location of the correspondence in the target camera weight: The - * weight of the factor gnc_mu: The mu convexity parameter for the Barron noise model gnc_scale: The - * scale parameter for the Barron noise model epsilon: Small positive value - * target_camera_model_class: The subclass of CameraCal to use as the target camera model + * normalized + * target_pixel: The location of the correspondence in the target camera + * weight: The weight of the factor + * gnc_mu: The mu convexity parameter for the + * :class:`BarronNoiseModel ` + * gnc_scale: The scale parameter for the + * :class:`BarronNoiseModel ` + * epsilon: Small positive value + * target_camera_model_class: The subclass of + * :class:`CameraCal ` to use as the target camera model * * Outputs: * res: 2dof whiten residual of the reprojection diff --git a/gen/cpp/sym/factors/inverse_range_landmark_spherical_reprojection_error_factor.h b/gen/cpp/sym/factors/inverse_range_landmark_spherical_reprojection_error_factor.h index e0fdf3828..e984ccfb3 100644 --- a/gen/cpp/sym/factors/inverse_range_landmark_spherical_reprojection_error_factor.h +++ b/gen/cpp/sym/factors/inverse_range_landmark_spherical_reprojection_error_factor.h @@ -17,14 +17,18 @@ namespace sym { * comparing it against the correspondence. * * The landmark is specified as a camera point in the source camera with an inverse range; this - * means the landmark is fixed in the source camera and always has residual 0 there (this 0 residual - * is not returned, only the residual in the target camera is returned). + * means the landmark is fixed in the source camera and always has residual 0 there (this 0 + * residual is not returned, only the residual in the target camera is returned). * - * The norm of the residual is whitened using the Barron noise model. Whitening each component of - * the reprojection error separately would result in rejecting individual components as outliers. - * Instead, we minimize the whitened norm of the full reprojection error for each point. See the - * docstring for `NoiseModel.whiten_norm` for more information on this, and the docstring of - * `BarronNoiseModel` for more information on the noise model. + * The norm of the residual is whitened using the + * :class:`BarronNoiseModel `. Whitening each + * component of the reprojection error separately would result in rejecting individual components + * as outliers. Instead, we minimize the whitened norm of the full reprojection error for each + * point. See + * :meth:`ScalarNoiseModel.whiten_norm ` + * for more information on this, and + * :class:`BarronNoiseModel ` for more information on + * the noise model. * * Args: * source_pose: The pose of the source camera @@ -32,10 +36,16 @@ namespace sym { * target_calibration_storage: The storage vector of the target spherical camera calibration * source_inverse_range: The inverse range of the landmark in the source camera * p_camera_source: The location of the landmark in the source camera coordinate, will be - * normalized target_pixel: The location of the correspondence in the target camera weight: The - * weight of the factor gnc_mu: The mu convexity parameter for the Barron noise model gnc_scale: The - * scale parameter for the Barron noise model epsilon: Small positive value - * target_camera_model_class: The subclass of CameraCal to use as the target camera model + * normalized + * target_pixel: The location of the correspondence in the target camera + * weight: The weight of the factor + * gnc_mu: The mu convexity parameter for the + * :class:`BarronNoiseModel ` + * gnc_scale: The scale parameter for the + * :class:`BarronNoiseModel ` + * epsilon: Small positive value + * target_camera_model_class: The subclass of + * :class:`CameraCal ` to use as the target camera model * * Outputs: * res: 2dof whiten residual of the reprojection diff --git a/gen/cpp/sym/factors/polynomial_reprojection_delta.h b/gen/cpp/sym/factors/polynomial_reprojection_delta.h index cf1941aee..68f383b3d 100644 --- a/gen/cpp/sym/factors/polynomial_reprojection_delta.h +++ b/gen/cpp/sym/factors/polynomial_reprojection_delta.h @@ -26,9 +26,11 @@ namespace sym { * target_calibration_storage: The storage vector of the target camera calibration * source_inverse_range: The inverse range of the landmark in the source camera * p_camera_source: The location of the landmark in the source camera coordinate, will be - * normalized target_pixel: The location of the correspondence in the target camera epsilon: Small - * positive value target_camera_model_class: The subclass of CameraCal to use as the target camera - * model + * normalized + * target_pixel: The location of the correspondence in the target camera + * epsilon: Small positive value + * target_camera_model_class: The subclass of + * :class:`CameraCal ` to use as the target camera model * * Outputs: * res: 2dof reprojection delta diff --git a/gen/cpp/sym/factors/spherical_reprojection_delta.h b/gen/cpp/sym/factors/spherical_reprojection_delta.h index 36099b479..548dd333c 100644 --- a/gen/cpp/sym/factors/spherical_reprojection_delta.h +++ b/gen/cpp/sym/factors/spherical_reprojection_delta.h @@ -26,9 +26,11 @@ namespace sym { * target_calibration_storage: The storage vector of the target camera calibration * source_inverse_range: The inverse range of the landmark in the source camera * p_camera_source: The location of the landmark in the source camera coordinate, will be - * normalized target_pixel: The location of the correspondence in the target camera epsilon: Small - * positive value target_camera_model_class: The subclass of CameraCal to use as the target camera - * model + * normalized + * target_pixel: The location of the correspondence in the target camera + * epsilon: Small positive value + * target_camera_model_class: The subclass of + * :class:`CameraCal ` to use as the target camera model * * Outputs: * res: 2dof reprojection delta diff --git a/gen/cpp/sym/pose2.h b/gen/cpp/sym/pose2.h index 59d281aa0..a4926a1a5 100644 --- a/gen/cpp/sym/pose2.h +++ b/gen/cpp/sym/pose2.h @@ -41,9 +41,10 @@ namespace sym { * * - There is no hat operator, because from_tangent/to_tangent is not the matrix exp/log * - * If you need a type that has these properties in symbolic expressions, you should use Pose2_SE2. - * There is no runtime equivalent of Pose2_SE2, see the docstring on that class for more - * information. + * If you need a type that has these properties in symbolic expressions, you should use + * :class:`symforce.geo.unsupported.pose2_se2.Pose2_SE2`. There is no runtime equivalent of + * :class:`Pose2_SE2 `, see the docstring on that + * class for more information. */ template class Pose2 { diff --git a/gen/cpp/sym/pose3.h b/gen/cpp/sym/pose3.h index cb8236d9b..11362794f 100644 --- a/gen/cpp/sym/pose3.h +++ b/gen/cpp/sym/pose3.h @@ -30,16 +30,21 @@ namespace sym { * The tangent space is 3 elements for rotation followed by 3 elements for translation in the * non-rotated frame. * - * For Lie group enthusiasts: This class is on the PRODUCT manifold, if you really really want - * SE(3) you should use Pose3_SE3. On this class, the group operations (e.g. compose and between) - * operate as you'd expect for a Pose or SE(3), but the manifold operations (e.g. retract and - * local_coordinates) operate on the product manifold SO(3) x R3. This means that: + * For Lie group enthusiasts: This class is on the PRODUCT manifold. On this class, the group + * operations (e.g. compose and between) operate as you'd expect for a Pose or SE(3), but the + * manifold operations (e.g. retract and local_coordinates) operate on the product manifold + * SO(3) x R3. This means that: * * - retract(a, vec) != compose(a, from_tangent(vec)) * * - local_coordinates(a, b) != to_tangent(between(a, b)) * * - There is no hat operator, because from_tangent/to_tangent is not the matrix exp/log + * + * If you need a type that has these properties in symbolic expressions, you should use + * :class:`symforce.geo.unsupported.pose3_se3.Pose3_SE3`. There is no runtime equivalent of + * :class:`Pose3_SE3 `, see the docstring on that + * class for more information. */ template class Pose3 { diff --git a/gen/cpp/sym/unit3.h b/gen/cpp/sym/unit3.h index 5cf7fefe1..00f38c42b 100644 --- a/gen/cpp/sym/unit3.h +++ b/gen/cpp/sym/unit3.h @@ -23,19 +23,21 @@ namespace sym { /** * Autogenerated C++ implementation of . * - * Direction in R^3, represented as a Rot3 that transforms [0, 0, 1] to the desired direction. + * Direction in R^3, represented as a :class:`Rot3 ` that transforms + * [0, 0, 1] to the desired direction. + * * The storage is therefore a quaternion and the tangent space is 2 dimensional. - * Most operations are implemented using operations from Rot3. + * Most operations are implemented using operations from :class:`Rot3 `. * * Note: an alternative implementation could directly store a unit vector and define its boxplus * manifold as described in Appendix B.2 of [Hertzberg 2013]. This can be done by finding the * Householder reflector of x and use it to transform the exponential map of delta, which is a - * small perturbation in the tangent space (R^2). Namely, + * small perturbation in the tangent space (R^2). Namely:: * - * x.retract(delta) = x [+] delta = Rx * Exp(delta), where - * Exp(delta) = [sinc(||delta||) * delta, cos(||delta||)], and - * Rx = (I - 2 vv^T / (v^Tv))X, v = x - e_z != 0, X is a matrix negating 2nd vector component - * = I , x = e_z + * x.retract(delta) = x [+] delta = Rx * Exp(delta), where + * Exp(delta) = [sinc(||delta||) * delta, cos(||delta||)], and + * Rx = (I - 2 vv^T / (v^Tv))X, v = x - e_z != 0, X is a matrix negating 2nd vector component + * = I , x = e_z * * [Hertzberg 2013] Integrating Generic Sensor Fusion Algorithms with Sound State Representations * through Encapsulation of Manifolds diff --git a/gen/python/sym/pose2.py b/gen/python/sym/pose2.py index 216dac09c..8ceccdbb2 100644 --- a/gen/python/sym/pose2.py +++ b/gen/python/sym/pose2.py @@ -37,9 +37,10 @@ class Pose2(object): - There is no hat operator, because from_tangent/to_tangent is not the matrix exp/log - If you need a type that has these properties in symbolic expressions, you should use Pose2_SE2. - There is no runtime equivalent of Pose2_SE2, see the docstring on that class for more - information. + If you need a type that has these properties in symbolic expressions, you should use + :class:`symforce.geo.unsupported.pose2_se2.Pose2_SE2`. There is no runtime equivalent of + :class:`Pose2_SE2 `, see the docstring on that + class for more information. """ __slots__ = ["data"] @@ -135,12 +136,6 @@ def compose_with_point(self, right): # type: (Pose2, numpy.ndarray) -> numpy.ndarray """ Left-multiply with a compatible quantity. - - Args: - right: (Pose2 | R2) - - Returns: - (Pose2 | R2) """ # Total ops: 8 diff --git a/gen/python/sym/pose3.py b/gen/python/sym/pose3.py index bec14979f..fc9620437 100644 --- a/gen/python/sym/pose3.py +++ b/gen/python/sym/pose3.py @@ -26,16 +26,21 @@ class Pose3(object): The tangent space is 3 elements for rotation followed by 3 elements for translation in the non-rotated frame. - For Lie group enthusiasts: This class is on the PRODUCT manifold, if you really really want - SE(3) you should use Pose3_SE3. On this class, the group operations (e.g. compose and between) - operate as you'd expect for a Pose or SE(3), but the manifold operations (e.g. retract and - local_coordinates) operate on the product manifold SO(3) x R3. This means that: + For Lie group enthusiasts: This class is on the PRODUCT manifold. On this class, the group + operations (e.g. compose and between) operate as you'd expect for a Pose or SE(3), but the + manifold operations (e.g. retract and local_coordinates) operate on the product manifold + SO(3) x R3. This means that: - retract(a, vec) != compose(a, from_tangent(vec)) - local_coordinates(a, b) != to_tangent(between(a, b)) - There is no hat operator, because from_tangent/to_tangent is not the matrix exp/log + + If you need a type that has these properties in symbolic expressions, you should use + :class:`symforce.geo.unsupported.pose3_se3.Pose3_SE3`. There is no runtime equivalent of + :class:`Pose3_SE3 `, see the docstring on that + class for more information. """ __slots__ = ["data"] diff --git a/gen/python/sym/rot2.py b/gen/python/sym/rot2.py index 18428d21e..4c35a3a0a 100644 --- a/gen/python/sym/rot2.py +++ b/gen/python/sym/rot2.py @@ -86,9 +86,9 @@ def compose_with_point(self, right): def from_angle(theta): # type: (float) -> Rot2 """ - Create a Rot2 from an angle `theta` in radians + Create a Rot2 from an angle ``theta`` in radians - This is equivalent to from_tangent([theta]) + This is equivalent to ``from_tangent([theta])`` """ # Total ops: 2 diff --git a/gen/python/sym/unit3.py b/gen/python/sym/unit3.py index f762e0f41..903f8e93a 100644 --- a/gen/python/sym/unit3.py +++ b/gen/python/sym/unit3.py @@ -19,19 +19,21 @@ class Unit3(object): """ Autogenerated Python implementation of . - Direction in R^3, represented as a Rot3 that transforms [0, 0, 1] to the desired direction. + Direction in R^3, represented as a :class:`Rot3 ` that transforms + [0, 0, 1] to the desired direction. + The storage is therefore a quaternion and the tangent space is 2 dimensional. - Most operations are implemented using operations from Rot3. + Most operations are implemented using operations from :class:`Rot3 `. Note: an alternative implementation could directly store a unit vector and define its boxplus manifold as described in Appendix B.2 of [Hertzberg 2013]. This can be done by finding the Householder reflector of x and use it to transform the exponential map of delta, which is a - small perturbation in the tangent space (R^2). Namely, + small perturbation in the tangent space (R^2). Namely:: - x.retract(delta) = x [+] delta = Rx * Exp(delta), where - Exp(delta) = [sinc(||delta||) * delta, cos(||delta||)], and - Rx = (I - 2 vv^T / (v^Tv))X, v = x - e_z != 0, X is a matrix negating 2nd vector component - = I , x = e_z + x.retract(delta) = x [+] delta = Rx * Exp(delta), where + Exp(delta) = [sinc(||delta||) * delta, cos(||delta||)], and + Rx = (I - 2 vv^T / (v^Tv))X, v = x - e_z != 0, X is a matrix negating 2nd vector component + = I , x = e_z [Hertzberg 2013] Integrating Generic Sensor Fusion Algorithms with Sound State Representations through Encapsulation of Manifolds @@ -62,8 +64,9 @@ def __init__(self, rot3=None): def from_vector(a, epsilon): # type: (numpy.ndarray, float) -> Unit3 """ - Return a Unit3 that points along the direction of vector a. a does not have to be a unit - vector. + Return a :class:`Unit3` that points along the direction of vector ``a`` + + ``a`` does not have to be a unit vector. """ # Total ops: 35 diff --git a/symforce/codegen/geo_package_codegen.py b/symforce/codegen/geo_package_codegen.py index 56588cf05..91fd4d804 100644 --- a/symforce/codegen/geo_package_codegen.py +++ b/symforce/codegen/geo_package_codegen.py @@ -185,8 +185,6 @@ def position(self: T.Any) -> T.Any: def generate(config: CodegenConfig, output_dir: Path = None) -> Path: """ Generate the geo package for the given language. - - TODO(hayk): Take scalar_type list here. """ # Create output directory if needed if output_dir is None: diff --git a/symforce/codegen/lcm_types_codegen.py b/symforce/codegen/lcm_types_codegen.py index 35a339a4b..af1b3771d 100644 --- a/symforce/codegen/lcm_types_codegen.py +++ b/symforce/codegen/lcm_types_codegen.py @@ -10,7 +10,7 @@ def lcm_symforce_types_data() -> T.Dict[str, T.Any]: """ - Returns data for template generation with lcm_templates/symforce_types.lcm.jinja. + Returns data for template generation with ``lcm_templates/symforce_types.lcm.jinja``. """ return dict( python_util=python_util, camera_cal_class_names=cam_package_codegen.camera_cal_class_names() diff --git a/symforce/codegen/similarity_index.py b/symforce/codegen/similarity_index.py index b7cd09687..af1ce7f11 100644 --- a/symforce/codegen/similarity_index.py +++ b/symforce/codegen/similarity_index.py @@ -16,10 +16,11 @@ @dataclasses.dataclass class SimilarityIndex: """ - Contains all the information needed to assess if two Codegen objects - would generate the same function, modulo function name and docstring. + Contains all the information needed to assess if two + :class:`Codegen ` objects would generate the same function, + modulo function name and docstring. - WARNING: SimilarityIndex is hashable despite being mutable. This means + WARNING: :class:`SimilarityIndex` is hashable despite being mutable. This means you should be careful when storing it as a key of a dict, as ordinary keys are immutable. """ @@ -39,12 +40,13 @@ def __post_init__(self, sparse_matrices: T.List[str]) -> None: @staticmethod def from_codegen(co: codegen.Codegen) -> SimilarityIndex: """ - Returns the SimilarityIndex of a Codegen object. + Returns the :class:`SimilarityIndex` of a + :class:`Codegen ` object. - If co1 and co2 are two Codegen objects, then - from_codegen(co1) == from_codegen(co2) if and only if the function - generated by co1.generate_function() is the same as that of co2.generate_function() - (up to differences in function name and doc-strings). + If co1 and co2 are two :class:`Codegen ` objects, then + ``from_codegen(co1) == from_codegen(co2)`` if and only if the function + generated by ``co1.generate_function()`` is the same as that of ``co2.generate_function()`` + (up to differences in function name and docstrings). """ return SimilarityIndex( inputs=co.inputs, @@ -56,10 +58,10 @@ def from_codegen(co: codegen.Codegen) -> SimilarityIndex: def __hash__(self) -> int: """ - WARNING: SimilarityIndex is mutable, and you must be mindful of the fact that + WARNING: :class:`SimilarityIndex` is mutable, and you must be mindful of the fact that keys of dicts are supposed to be immutable. - If seeking to use a SimilarityIndex in a dict as a key, encapsulate this to + If seeking to use a :class:`SimilarityIndex` in a dict as a key, encapsulate this to make sure others aren't able to modify the object after it has been hashed. """ return hash( diff --git a/symforce/codegen/slam_factors_codegen.py b/symforce/codegen/slam_factors_codegen.py index b29a7915e..2aa832f5b 100644 --- a/symforce/codegen/slam_factors_codegen.py +++ b/symforce/codegen/slam_factors_codegen.py @@ -121,11 +121,15 @@ def inverse_range_landmark_reprojection_error_residual( landmark is fixed in the source camera and always has residual 0 there (this 0 residual is not returned, only the residual in the target camera is returned). - The norm of the residual is whitened using the Barron noise model. Whitening each component of - the reprojection error separately would result in rejecting individual components as outliers. - Instead, we minimize the whitened norm of the full reprojection error for each point. See the - docstring for `NoiseModel.whiten_norm` for more information on this, and the docstring of - `BarronNoiseModel` for more information on the noise model. + The norm of the residual is whitened using the + :class:`BarronNoiseModel `. Whitening each + component of the reprojection error separately would result in rejecting individual components + as outliers. Instead, we minimize the whitened norm of the full reprojection error for each + point. See + :meth:`ScalarNoiseModel.whiten_norm ` + for more information on this, and + :class:`BarronNoiseModel ` for more information on + the noise model. Args: source_pose: The pose of the source camera @@ -136,10 +140,13 @@ def inverse_range_landmark_reprojection_error_residual( source_pixel: The location of the landmark in the source camera target_pixel: The location of the correspondence in the target camera weight: The weight of the factor - gnc_mu: The mu convexity parameter for the Barron noise model - gnc_scale: The scale parameter for the Barron noise model + gnc_mu: The mu convexity parameter for the + :class:`BarronNoiseModel ` + gnc_scale: The scale parameter for the + :class:`BarronNoiseModel ` epsilon: Small positive value - camera_model_class: The subclass of CameraCal to use as the camera model + camera_model_class: The subclass of :class:`CameraCal ` + to use as the camera model Outputs: res: 2dof residual of the reprojection @@ -192,10 +199,12 @@ def ray_reprojection_delta( target_pose: The pose of the target camera target_calibration_storage: The storage vector of the target camera calibration source_inverse_range: The inverse range of the landmark in the source camera - p_camera_source: The location of the landmark in the source camera coordinate, will be normalized + p_camera_source: The location of the landmark in the source camera coordinate, will be + normalized target_pixel: The location of the correspondence in the target camera epsilon: Small positive value - target_camera_model_class: The subclass of CameraCal to use as the target camera model + target_camera_model_class: The subclass of + :class:`CameraCal ` to use as the target camera model Outputs: res: 2dof reprojection delta @@ -233,31 +242,39 @@ def inverse_range_landmark_ray_reprojection_error_residual( target_camera_model_class: T.Type[sf.CameraCal], ) -> sf.Vector2: """ - Return the 2dof residual of reprojecting the landmark ray into the target spherical camera and comparing - it against the correspondence. - - The landmark is specified as a camera point in the source camera with an inverse range; this means the - landmark is fixed in the source camera and always has residual 0 there (this 0 residual is not - returned, only the residual in the target camera is returned). - - The norm of the residual is whitened using the Barron noise model. Whitening each component of - the reprojection error separately would result in rejecting individual components as outliers. - Instead, we minimize the whitened norm of the full reprojection error for each point. See the - docstring for `NoiseModel.whiten_norm` for more information on this, and the docstring of - `BarronNoiseModel` for more information on the noise model. + Return the 2dof residual of reprojecting the landmark ray into the target spherical camera and + comparing it against the correspondence. + + The landmark is specified as a camera point in the source camera with an inverse range; this + means the landmark is fixed in the source camera and always has residual 0 there (this 0 + residual is not returned, only the residual in the target camera is returned). + + The norm of the residual is whitened using the + :class:`BarronNoiseModel `. Whitening each + component of the reprojection error separately would result in rejecting individual components + as outliers. Instead, we minimize the whitened norm of the full reprojection error for each + point. See + :meth:`ScalarNoiseModel.whiten_norm ` + for more information on this, and + :class:`BarronNoiseModel ` for more information on + the noise model. Args: source_pose: The pose of the source camera target_pose: The pose of the target camera target_calibration_storage: The storage vector of the target spherical camera calibration source_inverse_range: The inverse range of the landmark in the source camera - p_camera_source: The location of the landmark in the source camera coordinate, will be normalized + p_camera_source: The location of the landmark in the source camera coordinate, will be + normalized target_pixel: The location of the correspondence in the target camera weight: The weight of the factor - gnc_mu: The mu convexity parameter for the Barron noise model - gnc_scale: The scale parameter for the Barron noise model + gnc_mu: The mu convexity parameter for the + :class:`BarronNoiseModel ` + gnc_scale: The scale parameter for the + :class:`BarronNoiseModel ` epsilon: Small positive value - target_camera_model_class: The subclass of CameraCal to use as the target camera model + target_camera_model_class: The subclass of + :class:`CameraCal ` to use as the target camera model Outputs: res: 2dof whiten residual of the reprojection diff --git a/symforce/codegen/template_util.py b/symforce/codegen/template_util.py index 11b882405..ac4d3ca8f 100644 --- a/symforce/codegen/template_util.py +++ b/symforce/codegen/template_util.py @@ -105,7 +105,7 @@ def autoformat( class RelEnvironment(jinja2.Environment): """ - Override join_path() to enable relative template paths. Modified from the below post. + Override ``join_path()`` to enable relative template paths. Modified from the below post. https://stackoverflow.com/questions/8512677/how-to-include-a-template-with-relative-path-in-jinja2 """ diff --git a/symforce/codegen/types_package_codegen.py b/symforce/codegen/types_package_codegen.py index 43d922ecb..78f02faaf 100644 --- a/symforce/codegen/types_package_codegen.py +++ b/symforce/codegen/types_package_codegen.py @@ -61,24 +61,30 @@ def generate_types( Args: package_name: Package of LCM types to be generated file_name: Name of the LCM file to generate (without the extension) - values_indices: Mapping between the name each LCM type to be generated and its index (computed using Values.index()) - shared_types: Used to specify whether specific types and subtypes have already been generated, either externally or internally - (i.e. if one generated type is to represent multiple objects in values_indices). + values_indices: Mapping between the name each LCM type to be generated and its index + (computed using :meth:`Values.index `) + shared_types: Used to specify whether specific types and subtypes have already been + generated, either externally or internally (e.g. if one generated type is to represent + multiple objects in ``values_indices``). Usage examples: - shared_types={"my_values" : "external_package.my_values"} (Reuse the implementation of "my_values" defined in package - "external_package", meaning that "my_values" as defined in values_indices will not be generated. Note - that "external_package" can equal package_name, e.g. when generating multiple functions in the same package which - reuse the same types) - shared_types={"my_values.V1" : "my_subvalues_t", "my_values.V2" : "my_subvalues_t"} (Only generate one type named - "my_subvalues_t" to represent Values objects defined by "my_values.V1" and "my_values.V2". + shared_types={"my_values" : "external_package.my_values"} + (Reuse the implementation of "my_values" defined in package "external_package", + meaning that "my_values" as defined in values_indices will not be generated. + Note that "external_package" can equal package_name, e.g. when generating + multiple functions in the same package which reuse the same types) + shared_types={"my_values.V1" : "my_subvalues_t", "my_values.V2" : "my_subvalues_t"} + (Only generate one type named "my_subvalues_t" to represent Values objects + defined by "my_values.V1" and "my_values.V2"). scalar_type: Type of scalars used in LCM type definition - output_dir: Where to output the files. ".lcm" files are output in "output_dir/lcmtypes", and language-specific implementations - are generated in "output_dir/package_name". - lcm_bindings_output_dir: Where to output language-specific LCM bindings. Defaults to output_dir - templates: TemplateList used if types are being generated as part of a larger code generation (e.g. when generating the - types required by a generated function). If None, we generate both the ".lcm" files and the language-specific - implementations, else we assume the templates and language-specific type implementations will be rendered - in an external function. + output_dir: Where to output the files. ``.lcm`` files are output in ``output_dir/lcmtypes``, + and language-specific implementations are generated in ``output_dir/package_name``. + lcm_bindings_output_dir: Where to output language-specific LCM bindings. Defaults to + ``output_dir`` + templates: TemplateList used if types are being generated as part of a larger code + generation (e.g. when generating the types required by a generated function). If None, + we generate both the ``.lcm`` files and the language-specific implementations, else we + assume the templates and language-specific type implementations will be rendered in an + external function. """ # Create output directory if needed if output_dir is None: @@ -201,7 +207,8 @@ def build_types_dict( shared_types: T.Optional[T.Mapping[str, str]] = None, ) -> T.Dict[str, T.Dict[str, T.Any]]: """ - Compute the structure of the types we need to generate for the given Values. + Compute the structure of the types we need to generate for the given + :class:`Values `. """ if shared_types is None: shared_types = {} @@ -231,8 +238,8 @@ def get_subvalues_from_list_index( list_index: T.Dict[str, IndexEntry] ) -> T.Optional[T.Dict[str, IndexEntry]]: """ - Returns index of Values object if base element of list is a Values object, - otherwise returns None + Returns index of :class:`Values ` object if base element of list is a + :class:`Values ` object, otherwise returns ``None``. """ index_element = list(list_index.values())[0] datatype = index_element.datatype() @@ -253,7 +260,7 @@ def _fill_types_dict_recursive( types_dict: T.Dict[str, T.Dict[str, T.Any]], ) -> None: """ - Recursively compute type information from the key and values index and fill into types_dict. + Recursively compute type information from the key and values index and fill into ``types_dict``. """ data: T.Dict[str, T.Any] = {} diff --git a/symforce/codegen/values_codegen.py b/symforce/codegen/values_codegen.py index 9d9073b6d..513c6e3fb 100644 --- a/symforce/codegen/values_codegen.py +++ b/symforce/codegen/values_codegen.py @@ -24,7 +24,7 @@ def generate_values_keys( skip_directory_nesting: bool = False, ) -> None: """ - Generate C++ variables to easily create `sym::Key`s from the python key names + Generate C++ variables to easily create ``sym::Key``s from the python key names Args: values: Will generate an entry for each (recursive) key in the values diff --git a/symforce/geo/dual_quaternion.py b/symforce/geo/dual_quaternion.py index 2e999983f..598d4e868 100644 --- a/symforce/geo/dual_quaternion.py +++ b/symforce/geo/dual_quaternion.py @@ -26,10 +26,6 @@ class DualQuaternion(Group): def __init__(self, real_q: Quaternion, inf_q: Quaternion) -> None: """ Construct from two quaternions - a real one and an infinitesimal one. - - Args: - real_q (Quaternion): - inf_q (Quaternion): """ self.real_q = real_q self.inf_q = inf_q @@ -83,24 +79,12 @@ def inverse(self) -> DualQuaternion: def __mul__(self, right: DualQuaternion) -> DualQuaternion: """ Left-multiply with another dual quaternion. - - Args: - other (DualQuaternion): - - Returns: - DualQuaternion: """ return self.compose(right) def __div__(self, scalar: T.Scalar) -> DualQuaternion: """ Scalar division. - - Args: - scalar (Scalar): - - Returns: - DualQuaternion: """ return DualQuaternion(self.real_q / scalar, self.inf_q / scalar) @@ -109,17 +93,11 @@ def __div__(self, scalar: T.Scalar) -> DualQuaternion: def squared_norm(self) -> T.Scalar: """ Squared norm when considering the dual quaternion as 8-tuple. - - Returns: - Scalar: """ return self.real_q.squared_norm() + self.inf_q.squared_norm() def conj(self) -> DualQuaternion: """ Dual quaternion conjugate. - - Returns: - DualQuaternion: """ return DualQuaternion(self.real_q.conj(), self.inf_q.conj()) diff --git a/symforce/geo/matrix.py b/symforce/geo/matrix.py index 736bf9ccb..f93a821d1 100644 --- a/symforce/geo/matrix.py +++ b/symforce/geo/matrix.py @@ -17,10 +17,23 @@ class Matrix(Storage): """ - Matrix type that wraps the Sympy Matrix class. Care has been taken to allow this class - to create fixed-size child classes like Matrix31. Anytime __new__ is called, the appropriate - fixed size class is returned rather than the type of the arguments. The API is meant to parallel - the way Eigen's C++ matrix classes work with dynamic and fixed sizes. + Matrix type that wraps the SymPy Matrix class. Care has been taken to allow this class + to create fixed-size child classes like :class:`Matrix31`. Anytime :meth:`__new__` is called, + the appropriate fixed size class is returned rather than the type of the arguments. The API is + meant to parallel the way Eigen's C++ matrix classes work with dynamic and fixed sizes, as well + as internal use cases within SymPy and SymEngine. + + Examples:: + + 1) Matrix32() # Zero constructed Matrix32 + 2) Matrix(sm.Matrix([[1, 2], [3, 4]])) # Matrix22 with [1, 2, 3, 4] data + 3A) Matrix([[1, 2], [3, 4]]) # Matrix22 with [1, 2, 3, 4] data + 3B) Matrix22([1, 2, 3, 4]) # Matrix22 with [1, 2, 3, 4] data (must matched fixed shape) + 3C) Matrix([1, 2, 3, 4]) # Matrix41 with [1, 2, 3, 4] data - column vector assumed + 4) Matrix(4, 3) # Zero constructed Matrix43 + 5) Matrix(2, 2, [1, 2, 3, 4]) # Matrix22 with [1, 2, 3, 4] data (first two are shape) + 6) Matrix(2, 2, lambda row, col: row + col) # Matrix22 with [0, 1, 1, 2] data + 7) Matrix22(1, 2, 3, 4) # Matrix22 with [1, 2, 3, 4] data (must match fixed length) References: @@ -29,11 +42,13 @@ class Matrix(Storage): https://en.wikipedia.org/wiki/Vector_space Matrix does not implement the group or lie group concepts using instance/class methods directly, - because we want it to represent the group R^{NxM}, not GL(n), which leads to the `identity` and - `inverse` methods being confusingly named. For the group ops and lie group ops, use - `ops.GroupOps` and `ops.LieGroupOps` respectively, which use the implementation in - vector_class_lie_group_ops.py of the R^{NxM} group under matrix addition. For - the identity matrix and inverse matrix, see `Matrix.eye` and `Matrix.inv` respectively. + because we want it to represent the group R^{NxM}, not GL(n), which leads to the ``identity`` + and ``inverse`` methods being confusingly named. For the group ops and lie group ops, use + :class:`symforce.ops.group_ops.GroupOps` and :class:`symforce.ops.lie_group_ops.LieGroupOps` + respectively, which use the implementation in + :mod:`symforce.ops.impl.vector_class_lie_group_ops` of the R^{NxM} group under matrix addition. + For the identity matrix and inverse matrix, see :meth:`Matrix.eye` and :meth:`Matrix.inv` + respectively. """ # Type that represents this or any subclasses @@ -49,21 +64,8 @@ def __new__(cls, *args: _T.Any, **kwargs: _T.Any) -> Matrix: """ Beast of a method for creating a Matrix. Handles a variety of construction use cases and *always* returns a fixed size child class of Matrix rather than Matrix itself. The - available construction options depend on whether cls is a fixed size type or not. - - Generally modeled after the Eigen interface, but must also support internal use within - sympy and symengine which we cannot change. - - Examples: - 1) Matrix32() # Zero constructed Matrix32 - 2) Matrix(sm.Matrix([[1, 2], [3, 4]])) # Matrix22 with [1, 2, 3, 4] data - 3A) Matrix([[1, 2], [3, 4]]) # Matrix22 with [1, 2, 3, 4] data - 3B) Matrix22([1, 2, 3, 4]) # Matrix22 with [1, 2, 3, 4] data (must matched fixed shape) - 3C) Matrix([1, 2, 3, 4]) # Matrix41 with [1, 2, 3, 4] data - column vector assumed - 4) Matrix(4, 3) # Zero constructed Matrix43 - 5) Matrix(2, 2, [1, 2, 3, 4]) # Matrix22 with [1, 2, 3, 4] data (first two are shape) - 6) Matrix(2, 2, lambda row, col: row + col) # Matrix22 with [0, 1, 1, 2] data - 7) Matrix22(1, 2, 3, 4) # Matrix22 with [1, 2, 3, 4] data (must match fixed length) + available construction options depend on whether cls is a fixed size type or not. See the + Matrix docstring for a summary of the construction options. """ # 1) Default construction allowed for fixed size. @@ -406,8 +408,13 @@ def col_join(self, bottom: Matrix) -> Matrix: @classmethod def block_matrix(cls, array: _T.Sequence[_T.Sequence[Matrix]]) -> Matrix: """ - Constructs a matrix from block elements. For example: - [[Matrix22(...), Matrix23(...)], [Matrix11(...), Matrix14(...)]] -> Matrix35 with elements equal to given blocks + Constructs a matrix from block elements. + + For example:: + + [[Matrix22(...), Matrix23(...)], [Matrix11(...), Matrix14(...)]] + + constructs a :class:`Matrix35` with elements equal to given blocks """ # Sum rows of matrices in the first column rows = sum(mat_row[0].shape[0] for mat_row in array) @@ -461,7 +468,7 @@ def limit(self, *args: _T.Any, **kwargs: _T.Any) -> Matrix: def jacobian(self, X: _T.Any, tangent_space: bool = True) -> Matrix: """ - Compute the jacobian with respect to the tangent space of X if tangent_space = True, + Compute the jacobian with respect to the tangent space of X if ``tangent_space = True``, otherwise returns the jacobian wih respect to the storage elements of X. """ assert self.cols == 1, "Jacobian is for column vectors." @@ -480,7 +487,7 @@ def jacobian(self, X: _T.Any, tangent_space: bool = True) -> Matrix: def diff(self, *args: _T.Scalar) -> Matrix: """ - Differentiate wrt a scalar. + Differentiate w.r.t. a scalar. """ return self.__class__(self.mat.diff(*args)) @@ -520,7 +527,9 @@ def reshape(self, rows: int, cols: int) -> Matrix: def dot(self, other: Matrix) -> _T.Scalar: """ Dot product, also known as inner product. - dot only supports mapping 1 x n or n x 1 Matrices to scalars. Note that both matrices must have the same shape. + + Only supports mapping ``1 x n`` or ``n x 1`` Matrices to scalars. Note that both matrices + must have the same shape. """ if not (self.is_vector() and other.is_vector()): raise TypeError( @@ -576,10 +585,10 @@ def clamp_norm( """ Clamp a vector to the given norm in a safe/differentiable way. - Is _NOT_ safe if max_norm can be negative, or if derivatives are needed w.r.t. max_norm and - max_norm can be 0 or small enough that `max_squared_norm / squared_norm` is truncated to 0 - in the particular floating point type being used (e.g. all of these are true if max_norm is - optimized) + Is **NOT** safe if max_norm can be negative, or if derivatives are needed w.r.t. max_norm and + max_norm can be 0 or small enough that ``max_squared_norm / squared_norm`` is truncated to 0 + in the particular floating point type being used (e.g. all of these are true if ``max_norm`` + is optimized). Currently only L2 norm is supported """ @@ -597,7 +606,7 @@ def clamp_norm( def multiply_elementwise(self: MatrixT, rhs: MatrixT) -> MatrixT: """ Do the elementwise multiplication between self and rhs, and return the result as a new - Matrix + :class:`Matrix` """ assert self.shape == rhs.shape return self.__class__(self.mat.multiply_elementwise(rhs.mat)) @@ -618,8 +627,10 @@ def __iter__(self) -> _T.Iterator[_T.Any]: def __getitem__(self, item: _T.Any) -> _T.Any: """ - Get a scalar value or submatrix slice. Unlike sympy, for 1D matrices the submatrix slice is - returned as a 1D matrix instead of as a list. + Get a scalar value or submatrix slice. + + Unlike sympy, for 1D matrices the submatrix slice is returned as a 1D matrix instead of as a + list. """ ret = self.mat.__getitem__(item) if isinstance(ret, sf.sympy.Matrix): @@ -757,13 +768,13 @@ def _symengine_(self) -> "symengine.Matrix": # type: ignore[name-defined] def compute_AtA(self, lower_only: bool = False) -> Matrix: """ - Compute a symmetric product A.transpose() * A + Compute a symmetric product ``A.transpose() * A`` Args: - lower_only (bool): If given, only fill the lower half and set upper to zero + lower_only: If given, only fill the lower half and set upper to zero Returns: - (Matrix(N, N)): Symmetric matrix AtA = self.transpose() * self + (Matrix(N, N)): Symmetric matrix ``AtA = self.transpose() * self`` """ AtA = self.T * self @@ -883,13 +894,11 @@ def to_numpy(self, scalar_type: type = np.float64) -> np.ndarray: @classmethod def column_stack(cls, *columns: Matrix) -> Matrix: - """Take a sequence of 1-D vectors and stack them as columns to make a single 2-D Matrix. + """ + Take a sequence of 1-D vectors and stack them as columns to make a single 2-D Matrix. Args: - columns (tuple(Matrix)): 1-D vectors - - Returns: - Matrix: + columns: 1-D vectors """ if not columns: return cls() @@ -918,13 +927,14 @@ def __hash__(self) -> int: @classmethod def _is_fixed_size(cls) -> bool: """ - Return True if this is a type with fixed dimensions set, ie Matrix31 instead of Matrix. + Return ``True`` if this is a type with fixed dimensions set, e.g. :class:`Matrix31` instead + of :class:`Matrix`. """ return cls.SHAPE[0] > 0 and cls.SHAPE[1] > 0 def _ipython_display_(self) -> None: """ - Display self.mat in IPython, with SymPy's pretty printing + Display ``self.mat`` in IPython, with SymPy's pretty printing """ display(self.mat) # type: ignore[name-defined] # pylint: disable=undefined-variable # not defined outside of ipython @@ -933,7 +943,7 @@ def init_printing() -> None: """ Initialize SymPy pretty printing - _ipython_display_ is sufficient in Jupyter, but this covers other locations + ``_ipython_display_`` is sufficient in Jupyter, but this covers other locations """ ip = None try: @@ -1372,8 +1382,9 @@ class Matrix99(Matrix): def matrix_type_from_shape(shape: _T.Tuple[int, int]) -> _T.Type[Matrix]: """ - Return a fixed size matrix type (like Matrix32) given a shape. Either use the statically - defined ones or dynamically create a new one if not available. + Return a fixed size matrix type (like :class:`Matrix32`) given a shape + + Either uses the statically defined ones or dynamically creates a new one if not available. """ if shape not in DIMS_TO_FIXED_TYPE: DIMS_TO_FIXED_TYPE[shape] = type( diff --git a/symforce/geo/pose2.py b/symforce/geo/pose2.py index 85c4f3b8c..6982830e6 100644 --- a/symforce/geo/pose2.py +++ b/symforce/geo/pose2.py @@ -36,9 +36,10 @@ class Pose2(LieGroup): - There is no hat operator, because from_tangent/to_tangent is not the matrix exp/log - If you need a type that has these properties in symbolic expressions, you should use Pose2_SE2. - There is no runtime equivalent of Pose2_SE2, see the docstring on that class for more - information. + If you need a type that has these properties in symbolic expressions, you should use + :class:`symforce.geo.unsupported.pose2_se2.Pose2_SE2`. There is no runtime equivalent of + :class:`Pose2_SE2 `, see the docstring on that + class for more information. """ Pose2T = T.TypeVar("Pose2T", bound="Pose2") @@ -59,7 +60,7 @@ def rotation(self) -> Rot2: """ Accessor for the rotation component - Does not make a copy. Also accessible as `self.R` + Does not make a copy. Also accessible as ``self.R`` """ return self.R @@ -67,7 +68,7 @@ def position(self) -> Vector2: """ Accessor for the position component - Does not make a copy. Also accessible as `self.t` + Does not make a copy. Also accessible as ``self.t`` """ return self.t @@ -134,7 +135,7 @@ def to_tangent(self, epsilon: T.Scalar = sf.epsilon()) -> T.List[T.Scalar]: def storage_D_tangent(self) -> Matrix: """ - Note: generated from symforce/notebooks/storage_D_tangent.ipynb + Note: generated from ``symforce/notebooks/storage_D_tangent.ipynb`` """ storage_D_tangent_R = self.R.storage_D_tangent() storage_D_tangent_t = Matrix22.eye() @@ -144,7 +145,7 @@ def storage_D_tangent(self) -> Matrix: def tangent_D_storage(self) -> Matrix: """ - Note: generated from symforce/notebooks/tangent_D_storage.ipynb + Note: generated from ``symforce/notebooks/tangent_D_storage.ipynb`` """ tangent_D_storage_R = self.R.tangent_D_storage() tangent_D_storage_t = Matrix22.eye() @@ -161,10 +162,10 @@ def retract(self: Pose2, vec: T.Sequence[T.Scalar], epsilon: T.Scalar = sf.epsil Applies a tangent space perturbation vec to self. Often used in optimization to update nonlinear values from an update step in the tangent space. - Conceptually represents "self + vec" if self is a vector. + Conceptually represents ``self + vec`` if self is a vector. Implementation retracts the R and t components separately, which is different from - `compose(self, from_tangent(vec))`. See the class docstring for more information. + ``compose(self, from_tangent(vec))``. See the class docstring for more information. """ return Pose2( R=self.R.retract(vec[:1], epsilon=epsilon), @@ -178,10 +179,10 @@ def local_coordinates( Computes a tangent space perturbation around self to produce b. Often used in optimization to minimize the distance between two group elements. - Tangent space perturbation that conceptually represents "b - self" if self is a vector. + Tangent space perturbation that conceptually represents ``b - self`` if self is a vector. Implementation takes local_coordinates of the R and t components separately, which is - different from `to_tangent(between(self, b))`. See the class docstring for more + different from ``to_tangent(between(self, b))``. See the class docstring for more information. """ return self.R.local_coordinates(b.R, epsilon=epsilon) + ops.LieGroupOps.local_coordinates( @@ -203,12 +204,6 @@ def __mul__(self, right: Vector2) -> Vector2: # pragma: no cover def __mul__(self, right: T.Union[Pose2, Vector2]) -> T.Union[Pose2, Vector2]: """ Left-multiply with a compatible quantity. - - Args: - right: (Pose2 | R2) - - Returns: - (Pose2 | R2) """ if isinstance(right, Vector2): assert right.shape == (2, 1), right.shape diff --git a/symforce/geo/pose3.py b/symforce/geo/pose3.py index 9b4d5cbd8..4f23f16b4 100644 --- a/symforce/geo/pose3.py +++ b/symforce/geo/pose3.py @@ -25,16 +25,21 @@ class Pose3(LieGroup): The tangent space is 3 elements for rotation followed by 3 elements for translation in the non-rotated frame. - For Lie group enthusiasts: This class is on the PRODUCT manifold, if you really really want - SE(3) you should use Pose3_SE3. On this class, the group operations (e.g. compose and between) - operate as you'd expect for a Pose or SE(3), but the manifold operations (e.g. retract and - local_coordinates) operate on the product manifold SO(3) x R3. This means that: + For Lie group enthusiasts: This class is on the PRODUCT manifold. On this class, the group + operations (e.g. compose and between) operate as you'd expect for a Pose or SE(3), but the + manifold operations (e.g. retract and local_coordinates) operate on the product manifold + SO(3) x R3. This means that: - retract(a, vec) != compose(a, from_tangent(vec)) - local_coordinates(a, b) != to_tangent(between(a, b)) - There is no hat operator, because from_tangent/to_tangent is not the matrix exp/log + + If you need a type that has these properties in symbolic expressions, you should use + :class:`symforce.geo.unsupported.pose3_se3.Pose3_SE3`. There is no runtime equivalent of + :class:`Pose3_SE3 `, see the docstring on that + class for more information. """ Pose3T = T.TypeVar("Pose3T", bound="Pose3") @@ -59,7 +64,7 @@ def rotation(self) -> Rot3: """ Accessor for the rotation component - Does not make a copy. Also accessible as `self.R` + Does not make a copy. Also accessible as ``self.R`` """ return self.R @@ -67,7 +72,7 @@ def position(self) -> Vector3: """ Accessor for the position component - Does not make a copy. Also accessible as `self.t` + Does not make a copy. Also accessible as ``self.t`` """ return self.t @@ -139,7 +144,7 @@ def to_tangent(self: Pose3T, epsilon: T.Scalar = sf.epsilon()) -> T.List[T.Scala def storage_D_tangent(self: Pose3T) -> Matrix: """ - Note: generated from symforce/notebooks/storage_D_tangent.ipynb + Note: generated from ``symforce/notebooks/storage_D_tangent.ipynb`` """ storage_D_tangent_R = self.R.storage_D_tangent() storage_D_tangent_t = Matrix33.eye() @@ -149,7 +154,7 @@ def storage_D_tangent(self: Pose3T) -> Matrix: def tangent_D_storage(self: Pose3T) -> Matrix: """ - Note: generated from symforce/notebooks/tangent_D_storage.ipynb + Note: generated from ``symforce/notebooks/tangent_D_storage.ipynb`` """ tangent_D_storage_R = self.R.tangent_D_storage() tangent_D_storage_t = Matrix33.eye() @@ -168,10 +173,10 @@ def retract( Applies a tangent space perturbation vec to self. Often used in optimization to update nonlinear values from an update step in the tangent space. - Conceptually represents "self + vec" if self is a vector. + Conceptually represents ``self + vec`` if self is a vector. Implementation retracts the R and t components separately, which is different from - `compose(self, from_tangent(vec))`. See the class docstring for more information. + ``compose(self, from_tangent(vec))``. See the class docstring for more information. """ return self.__class__( R=self.R.retract(vec[:3], epsilon=epsilon), @@ -185,10 +190,10 @@ def local_coordinates( Computes a tangent space perturbation around self to produce b. Often used in optimization to minimize the distance between two group elements. - Tangent space perturbation that conceptually represents "b - self" if self is a vector. + Tangent space perturbation that conceptually represents ``b - self`` if self is a vector. Implementation takes local_coordinates of the R and t components separately, which is - different from `to_tangent(between(self, b))`. See the class docstring for more + different from ``to_tangent(between(self, b))``. See the class docstring for more information. """ return self.R.local_coordinates(b.R, epsilon=epsilon) + ops.LieGroupOps.local_coordinates( diff --git a/symforce/geo/rot2.py b/symforce/geo/rot2.py index dc126936a..369a2f422 100644 --- a/symforce/geo/rot2.py +++ b/symforce/geo/rot2.py @@ -95,13 +95,13 @@ def hat(cls, vec: T.Sequence[T.Scalar]) -> Matrix22: def storage_D_tangent(self) -> Matrix21: """ - Note: generated from symforce/notebooks/storage_D_tangent.ipynb + Note: generated from ``symforce/notebooks/storage_D_tangent.ipynb`` """ return Matrix21([[-self.z.imag], [self.z.real]]) def tangent_D_storage(self) -> Matrix12: """ - Note: generated from symforce/notebooks/tangent_D_storage.ipynb + Note: generated from ``symforce/notebooks/tangent_D_storage.ipynb`` """ return T.cast(Matrix12, self.storage_D_tangent().T) @@ -131,9 +131,9 @@ def __mul__(self, right: T.Union[Rot2, Vector2]) -> T.Union[Rot2, Vector2]: @classmethod def from_angle(cls, theta: T.Scalar) -> Rot2: """ - Create a Rot2 from an angle `theta` in radians + Create a Rot2 from an angle ``theta`` in radians - This is equivalent to from_tangent([theta]) + This is equivalent to ``from_tangent([theta])`` """ return cls.from_tangent([theta]) diff --git a/symforce/geo/rot3.py b/symforce/geo/rot3.py index 2e61cbb9e..d6faed297 100644 --- a/symforce/geo/rot3.py +++ b/symforce/geo/rot3.py @@ -105,7 +105,7 @@ def hat(cls, vec: T.Sequence[T.Scalar]) -> Matrix33: def storage_D_tangent(self) -> Matrix43: """ - Note: generated from symforce/notebooks/storage_D_tangent.ipynb + Note: generated from ``symforce/notebooks/storage_D_tangent.ipynb`` """ return ( sf.S.One @@ -122,7 +122,7 @@ def storage_D_tangent(self) -> Matrix43: def tangent_D_storage(self) -> Matrix34: """ - Note: generated from symforce/notebooks/tangent_D_storage.ipynb + Note: generated from ``symforce/notebooks/tangent_D_storage.ipynb`` """ return 4 * T.cast(Matrix34, self.storage_D_tangent().T) diff --git a/symforce/geo/unit3.py b/symforce/geo/unit3.py index 05ff024e6..822e47c7b 100644 --- a/symforce/geo/unit3.py +++ b/symforce/geo/unit3.py @@ -18,19 +18,21 @@ class Unit3(LieGroup): """ - Direction in R^3, represented as a Rot3 that transforms [0, 0, 1] to the desired direction. + Direction in R^3, represented as a :class:`Rot3 ` that transforms + [0, 0, 1] to the desired direction. + The storage is therefore a quaternion and the tangent space is 2 dimensional. - Most operations are implemented using operations from Rot3. + Most operations are implemented using operations from :class:`Rot3 `. Note: an alternative implementation could directly store a unit vector and define its boxplus manifold as described in Appendix B.2 of [Hertzberg 2013]. This can be done by finding the Householder reflector of x and use it to transform the exponential map of delta, which is a - small perturbation in the tangent space (R^2). Namely, + small perturbation in the tangent space (R^2). Namely:: - x.retract(delta) = x [+] delta = Rx * Exp(delta), where - Exp(delta) = [sinc(||delta||) * delta, cos(||delta||)], and - Rx = (I - 2 vv^T / (v^Tv))X, v = x - e_z != 0, X is a matrix negating 2nd vector component - = I , x = e_z + x.retract(delta) = x [+] delta = Rx * Exp(delta), where + Exp(delta) = [sinc(||delta||) * delta, cos(||delta||)], and + Rx = (I - 2 vv^T / (v^Tv))X, v = x - e_z != 0, X is a matrix negating 2nd vector component + = I , x = e_z [Hertzberg 2013] Integrating Generic Sensor Fusion Algorithms with Sound State Representations through Encapsulation of Manifolds @@ -40,7 +42,7 @@ class Unit3(LieGroup): def __init__(self, rot3: Rot3 = None) -> None: """ - Construct from a rot3, or identity if none provided. + Construct from a :class:`Rot3 `, or identity if none provided. """ self.rot3 = rot3 if rot3 is not None else Rot3.identity() assert isinstance(self.rot3, Rot3) @@ -117,8 +119,9 @@ def to_unit_vector(self) -> Vector3: @classmethod def from_vector(cls, a: Vector3, epsilon: T.Scalar = sf.epsilon()) -> Unit3: """ - Return a Unit3 that points along the direction of vector a. a does not have to be a unit - vector. + Return a :class:`Unit3` that points along the direction of vector ``a`` + + ``a`` does not have to be a unit vector. """ u = a.normalized(epsilon=epsilon) return cls(Rot3.from_two_unit_vectors(cls.E_Z, u, epsilon=epsilon)) @@ -126,7 +129,7 @@ def from_vector(cls, a: Vector3, epsilon: T.Scalar = sf.epsilon()) -> Unit3: @classmethod def random(cls, epsilon: T.Scalar = sf.epsilon()) -> Unit3: """ - Generate a random element of Unit3, by generating a random rotation first and then rotating - e_z to get a random direction. + Generate a random element of :class:`Unit3`, by generating a random rotation first and then + rotating ``e_z`` to get a random direction. """ return cls.from_vector(Rot3.random() * cls.E_Z, epsilon=epsilon) diff --git a/symforce/geo/unsupported/pose2_se2.py b/symforce/geo/unsupported/pose2_se2.py index 119b82620..789892193 100644 --- a/symforce/geo/unsupported/pose2_se2.py +++ b/symforce/geo/unsupported/pose2_se2.py @@ -22,12 +22,12 @@ class Pose2_SE2(Pose2): """ Group of two-dimensional rigid body transformations - SE(2). - There is no generated runtime analogue of this class in the `sym` package, which means you + There is no generated runtime analogue of this class in the :mod:`sym` package, which means you cannot use it as an input or output of generated functions or as a variable in an optimized - Values. This is intentional - in general, you should use the Pose2 class instead of this one, - because the generated expressions will be significantly more efficient. If you are sure that - you need the different behavior of this class, it's here for reference or for use in symbolic - expressions. + Values. This is intentional - in general, you should use the + :class:`Pose2 ` class instead of this one, because the generated + expressions will be significantly more efficient. If you are sure that you need the different + behavior of this class, it's here for reference or for use in symbolic expressions. The storage space is a complex (real, imag) for rotation followed by a position (x, y). @@ -71,7 +71,7 @@ def to_tangent(self, epsilon: T.Scalar = sf.epsilon()) -> T.List[T.Scalar]: def storage_D_tangent(self) -> Matrix: """ - Note: generated from symforce/notebooks/storage_D_tangent.ipynb + Note: generated from ``symforce/notebooks/storage_D_tangent.ipynb`` """ storage_D_tangent_R = self.R.storage_D_tangent() storage_D_tangent_t = self.R.to_rotation_matrix() @@ -81,7 +81,7 @@ def storage_D_tangent(self) -> Matrix: def tangent_D_storage(self) -> Matrix: """ - Note: generated from symforce/notebooks/tangent_D_storage.ipynb + Note: generated from ``symforce/notebooks/tangent_D_storage.ipynb`` """ tangent_D_storage_R = self.R.tangent_D_storage() tangent_D_storage_t = self.R.to_rotation_matrix().T @@ -94,8 +94,8 @@ def retract(self, vec: T.Sequence[T.Scalar], epsilon: T.Scalar = sf.epsilon()) - Applies a tangent space perturbation vec to self. Often used in optimization to update nonlinear values from an update step in the tangent space. - Implementation is simply `compose(self, from_tangent(vec))`. - Conceptually represents "self + vec" if self is a vector. + Implementation is simply ``compose(self, from_tangent(vec))``. + Conceptually represents ``self + vec`` if self is a vector. """ return LieGroup.retract(self, vec, epsilon) @@ -104,8 +104,8 @@ def local_coordinates(self, b: Pose2_SE2, epsilon: T.Scalar = sf.epsilon()) -> T Computes a tangent space perturbation around self to produce b. Often used in optimization to minimize the distance between two group elements. - Implementation is simply `to_tangent(between(self, b))`. - Tangent space perturbation that conceptually represents "b - self" if self is a vector. + Implementation is simply ``to_tangent(between(self, b))``. + Tangent space perturbation that conceptually represents ``b - self`` if self is a vector. """ return LieGroup.local_coordinates(self, b, epsilon) diff --git a/symforce/geo/unsupported/pose3_se3.py b/symforce/geo/unsupported/pose3_se3.py index 423c64eba..f573264e7 100644 --- a/symforce/geo/unsupported/pose3_se3.py +++ b/symforce/geo/unsupported/pose3_se3.py @@ -22,12 +22,12 @@ class Pose3_SE3(Pose3): """ Group of three-dimensional rigid body transformations - SE(3). - There is no generated runtime analogue of this class in the `sym` package, which means you + There is no generated runtime analogue of this class in the :mod:`sym` package, which means you cannot use it as an input or output of generated functions or as a variable in an optimized - Values. This is intentional - in general, you should use the Pose3 class instead of this one, - because the generated expressions will be significantly more efficient. If you are sure that - you need the different behavior of this class, it's here for reference or for use in symbolic - expressions. + Values. This is intentional - in general, you should use the + :class:`Pose3 ` class instead of this one, because the generated + expressions will be significantly more efficient. If you are sure that you need the different + behavior of this class, it's here for reference or for use in symbolic expressions. The storage is a quaternion (x, y, z, w) for rotation followed by position (x, y, z). @@ -79,7 +79,7 @@ def to_tangent(self, epsilon: T.Scalar = sf.epsilon()) -> T.List[T.Scalar]: def storage_D_tangent(self) -> Matrix: """ - Note: generated from symforce/notebooks/storage_D_tangent.ipynb + Note: generated from ``symforce/notebooks/storage_D_tangent.ipynb`` """ storage_D_tangent_R = self.R.storage_D_tangent() storage_D_tangent_t = self.R.to_rotation_matrix() @@ -89,7 +89,7 @@ def storage_D_tangent(self) -> Matrix: def tangent_D_storage(self) -> Matrix: """ - Note: generated from symforce/notebooks/tangent_D_storage.ipynb + Note: generated from ``symforce/notebooks/tangent_D_storage.ipynb`` """ tangent_D_storage_R = self.R.tangent_D_storage() tangent_D_storage_t = self.R.to_rotation_matrix().T @@ -102,8 +102,8 @@ def retract(self, vec: T.Sequence[T.Scalar], epsilon: T.Scalar = sf.epsilon()) - Applies a tangent space perturbation vec to self. Often used in optimization to update nonlinear values from an update step in the tangent space. - Implementation is simply `compose(self, from_tangent(vec))`. - Conceptually represents "self + vec" if self is a vector. + Implementation is simply ``compose(self, from_tangent(vec))``. + Conceptually represents ``self + vec`` if self is a vector. """ return LieGroup.retract(self, vec, epsilon) @@ -112,8 +112,8 @@ def local_coordinates(self, b: Pose3_SE3, epsilon: T.Scalar = sf.epsilon()) -> T Computes a tangent space perturbation around self to produce b. Often used in optimization to minimize the distance between two group elements. - Implementation is simply `to_tangent(between(self, b))`. - Tangent space perturbation that conceptually represents "b - self" if self is a vector. + Implementation is simply ``to_tangent(between(self, b))``. + Tangent space perturbation that conceptually represents ``b - self`` if self is a vector. """ return LieGroup.local_coordinates(self, b, epsilon) diff --git a/symforce/internal/symbolic.py b/symforce/internal/symbolic.py index 7d08169cb..03072d299 100644 --- a/symforce/internal/symbolic.py +++ b/symforce/internal/symbolic.py @@ -8,8 +8,8 @@ This represents the core functions that comprise SymForce's unified version of the SymPy API, without additional imports that would cause import cycles. This means this module is safe to be -imported from those modules within SymForce. Users should instead import `symforce.symbolic`, which -includes the entire SymForce symbolic API. +imported from those modules within SymForce. Users should instead import :mod:`symforce.symbolic`, +which includes the entire SymForce symbolic API. This combines functions available from various sources: @@ -17,10 +17,10 @@ - Additional functions defined here to override those provided by SymPy or SymEngine, or provide a uniform interface between the two. See https://symforce.org/api/symforce.symbolic.html for information on these -- Logic functions defined in `symforce.logic`, see the documentation for that module +- Logic functions defined in :mod:`symforce.logic`, see the documentation for that module It typically isn't necessary to actually access the symbolic API being used internally, but that is -available as well as `symforce.symbolic.sympy`. +available as well as :mod:`symforce.symbolic.sympy`. """ # pylint: disable=unused-import @@ -256,7 +256,7 @@ def epsilon() -> T.Any: """ The default epsilon for SymForce - Library functions that require an epsilon argument should use a function signature like: + Library functions that require an epsilon argument should use a function signature like:: def foo(x: Scalar, epsilon: Scalar = sf.epsilon()) -> Scalar: ... @@ -270,10 +270,11 @@ def foo(x: Scalar, epsilon: Scalar = sf.epsilon()) -> Scalar: in the SymForce docs here: https://symforce.org/tutorials/epsilon_tutorial.html For purely numerical code that just needs a good default numerical epsilon, see - `symforce.symbolic.numeric_epsilon`. + :data:`symforce.symbolic.numeric_epsilon`. - Returns: The current default epsilon. This is typically some kind of "Scalar", like a float or - a Symbol. + Returns: + The current default epsilon. This is typically some kind of "Scalar", like a float or a + :class:`Symbol `. """ symforce._have_used_epsilon = True # pylint: disable=protected-access @@ -363,7 +364,7 @@ def wrap_angle(x: Scalar) -> Scalar: Wrap an angle to the interval [-pi, pi). Commonly used to compute the shortest signed distance between two angles. - See also: `angle_diff` + See also: :func:`angle_diff` """ return Mod(x + pi, 2 * pi) - pi @@ -373,7 +374,7 @@ def angle_diff(x: Scalar, y: Scalar) -> Scalar: Return the difference x - y, but wrapped into [-pi, pi); i.e. the angle `diff` closest to 0 such that x = y + diff (mod 2pi). - See also: `wrap_angle` + See also: :func:`wrap_angle` """ return wrap_angle(x - y) @@ -394,8 +395,8 @@ def copysign_no_zero(x: Scalar, y: Scalar) -> Scalar: def argmax_onehot(vals: T.Iterable[Scalar]) -> T.List[Scalar]: """ - Returns a list l such that l[i] = 1.0 if i is the smallest index such that - vals[i] equals Max(*vals). l[i] = 0.0 otherwise. + Returns a list ``l`` such that ``l[i] = 1.0`` if ``i`` is the smallest index such that + ``vals[i]`` equals ``Max(*vals)``. ``l[i] = 0.0`` otherwise. Precondition: vals has at least one element @@ -418,8 +419,8 @@ def argmax_onehot(vals: T.Iterable[Scalar]) -> T.List[Scalar]: def argmax(vals: T.Iterable[Scalar]) -> Scalar: """ - Returns i (as a Scalar) such that i is the smallest index such that - vals[i] equals Max(*vals). + Returns ``i`` (as a Scalar) such that ``i`` is the smallest index such that + ``vals[i]`` equals ``Max(*vals)``. Precondition: vals has at least one element @@ -445,9 +446,13 @@ def acos_safe(x: Scalar, epsilon: Scalar = epsilon()) -> Scalar: def clamp(x: sf.Scalar, min_value: sf.Scalar, max_value: sf.Scalar) -> sf.Scalar: """ - Returns min_value if x < min_value - Returns x if min_value < x < max_value - Returns max_value if x > max_value + Clamps x between min_value and max_value + + Returns:: + + min_value if x < min_value + x if min_value <= x <= max_value + max_value if x > max_value Args: x: Value to clamp between min_value and max_value @@ -634,9 +639,9 @@ def _get_subs_dict(*args: T.Any, dont_flatten_args: bool = False, **kwargs: T.An Handle args to subs being a single key-value pair or a dict. Keyword Args: - dont_flatten_args (bool): if true and args is a single argument, assume that args is a - dict mapping scalar expressions to other scalar expressions. i.e. StorageOps flattening - will *not* occur. This is significantly faster. + dont_flatten_args: if true and args is a single argument, assume that args is a dict mapping + scalar expressions to other scalar expressions. i.e. StorageOps flattening will **not** + occur. This is significantly faster. **kwargs is unused but needed for sympy compatibility """ diff --git a/symforce/ops/interfaces/group.py b/symforce/ops/interfaces/group.py index ea1b15360..358e109ed 100644 --- a/symforce/ops/interfaces/group.py +++ b/symforce/ops/interfaces/group.py @@ -27,7 +27,7 @@ class is registered using ClassGroupOps (see bottom of this file), any @classmethod def identity(cls: T.Type[GroupT]) -> GroupT: """ - Identity element such that `compose(a, identity) = a`. + Identity element such that ``compose(a, identity) = a``. """ raise NotImplementedError() @@ -39,15 +39,16 @@ def compose(self: GroupT, other: GroupT) -> GroupT: def inverse(self: GroupT) -> GroupT: """ - Group inverse, such that `compose(a, inverse(a)) = identity`. + Group inverse, such that ``compose(a, inverse(a)) = identity``. """ raise NotImplementedError() def between(self: GroupT, b: GroupT) -> GroupT: """ - Returns the element that when composed with self produces b. For vector spaces it is `b - self`. + Returns the element that when composed with self produces b. For vector spaces it is + ``b - self``. - Implementation is simply `compose(inverse(self), b)`. + Implementation is simply ``compose(inverse(self), b)``. """ return self.inverse().compose(b)