Karana.Dynamics
===============

.. py:module:: Karana.Dynamics

.. autoapi-nested-parse::

   Classes and modules related to dynamics computation.



Submodules
----------

.. toctree::
   :maxdepth: 1

   /generated/python_api/Karana/Dynamics/SOADyn_types/index
   /generated/python_api/Karana/Dynamics/SOAFlexDyn_types/index


Attributes
----------

.. autoapisummary::

   Karana.Dynamics.tv_ids_count
   Karana.Dynamics.tv_ids_db


Classes
-------

.. autoapisummary::

   Karana.Dynamics.Algorithms
   Karana.Dynamics.BilateralConstraintBase
   Karana.Dynamics.BilateralConstraintBaseVars
   Karana.Dynamics.BilateralConstraintType
   Karana.Dynamics.BodyBase
   Karana.Dynamics.CECompoundBody
   Karana.Dynamics.CECompoundBodyVars
   Karana.Dynamics.CECompoundSubhinge
   Karana.Dynamics.CELoopKinematicsBase
   Karana.Dynamics.CELoopKinematicsBaseVars
   Karana.Dynamics.CELoopKinematicsNumeric
   Karana.Dynamics.CELoopKinematicsNumericVars
   Karana.Dynamics.CKFrozenCoordType
   Karana.Dynamics.CompoundBody
   Karana.Dynamics.CompoundBodyVars
   Karana.Dynamics.CompoundHinge
   Karana.Dynamics.CompoundSubhinge
   Karana.Dynamics.CompoundSubhingeVars
   Karana.Dynamics.ConstraintKinematicsSolver
   Karana.Dynamics.ConstraintKinematicsSolverVars
   Karana.Dynamics.ConstraintNode
   Karana.Dynamics.CoordBase
   Karana.Dynamics.CoordData
   Karana.Dynamics.CoordDataCoordOffset
   Karana.Dynamics.CoordDataVars
   Karana.Dynamics.CoordinateConstraint
   Karana.Dynamics.CoordinateConstraintVars
   Karana.Dynamics.FramePairHinge
   Karana.Dynamics.FramePairHingeVars
   Karana.Dynamics.FrameToFrameJacobianGenerator
   Karana.Dynamics.HingeBase
   Karana.Dynamics.HingeNode
   Karana.Dynamics.HingeOnode
   Karana.Dynamics.HingeOnodeATBIFilterVectors
   Karana.Dynamics.HingeOnodeATBIMatrices
   Karana.Dynamics.HingeOnodeATBISmootherVectors
   Karana.Dynamics.HingeParams
   Karana.Dynamics.HingePnode
   Karana.Dynamics.HingePnodeATBIFilterVectors
   Karana.Dynamics.HingePnodeATBIMatrices
   Karana.Dynamics.HingePnodeATBISmootherVectors
   Karana.Dynamics.HingeType
   Karana.Dynamics.HybridNonLinearSolverStatus
   Karana.Dynamics.LevenbergMarquardtStatus
   Karana.Dynamics.Linear3Subhinge
   Karana.Dynamics.LinearSubhinge
   Karana.Dynamics.LockedSubhinge
   Karana.Dynamics.LoopConstraintBase
   Karana.Dynamics.LoopConstraintBaseVars
   Karana.Dynamics.LoopConstraintConVel
   Karana.Dynamics.LoopConstraintConVelVars
   Karana.Dynamics.LoopConstraintCutJoint
   Karana.Dynamics.LoopConstraintCutJointVars
   Karana.Dynamics.MMFunctions
   Karana.Dynamics.MMOptionsModelManager
   Karana.Dynamics.MMSolverType
   Karana.Dynamics.ModalAnalysis
   Karana.Dynamics.ModelManager
   Karana.Dynamics.ModelManagerVars
   Karana.Dynamics.MultiJacobianGenerator
   Karana.Dynamics.Multibody
   Karana.Dynamics.Node
   Karana.Dynamics.NodeDeformationProvider
   Karana.Dynamics.NodeVars
   Karana.Dynamics.NonlinearSolver
   Karana.Dynamics.Physical1DofSubhinge
   Karana.Dynamics.PhysicalBody
   Karana.Dynamics.PhysicalBodyParams
   Karana.Dynamics.PhysicalBodyVars
   Karana.Dynamics.PhysicalHinge
   Karana.Dynamics.PhysicalSubhinge
   Karana.Dynamics.PhysicalSubhingeVars
   Karana.Dynamics.PhysicalSubhinge_T_0_0
   Karana.Dynamics.PhysicalSubhinge_T_1_1
   Karana.Dynamics.PhysicalSubhinge_T_3_3
   Karana.Dynamics.PhysicalSubhinge_T_4_3
   Karana.Dynamics.PinSubhinge
   Karana.Dynamics.PrePostCallbackRegistry
   Karana.Dynamics.Scheduler
   Karana.Dynamics.ScrewSubhinge
   Karana.Dynamics.SolverType
   Karana.Dynamics.SpOptions
   Karana.Dynamics.SpStatusEnum
   Karana.Dynamics.SphericalQuatSubhinge
   Karana.Dynamics.SphericalSubhinge
   Karana.Dynamics.StatePropagator
   Karana.Dynamics.StatePropagatorCounters
   Karana.Dynamics.StatePropagatorVars
   Karana.Dynamics.StickPartsConfig
   Karana.Dynamics.SubGraph
   Karana.Dynamics.SubGraphVars
   Karana.Dynamics.SubTree
   Karana.Dynamics.SubTreeDumpTreeOptions
   Karana.Dynamics.SubTreeVars
   Karana.Dynamics.SubhingeBase
   Karana.Dynamics.SubhingeType
   Karana.Dynamics.TerminateCrossingCallbackRegistry
   Karana.Dynamics.TimeKeeper
   Karana.Dynamics.TimeKeeperVars
   Karana.Dynamics.TimedEvent
   Karana.Dynamics.ZeroCrossingCallbackRegistry
   Karana.Dynamics.ModalNodeDeformationProvider
   Karana.Dynamics.PhysicalModalBody
   Karana.Dynamics.PhysicalModalBodyParams
   Karana.Dynamics.PhysicalModalBodyVars


Package Contents
----------------

.. py:data:: tv_ids_count
   :value: 0


.. py:data:: tv_ids_db

.. py:class:: Algorithms

   Class with static methods for various system level algorithms.

   This is a container class for static methods to compute various
   multibody algorithms. See :ref:`algorithms_sec` section for more
   information.


   .. py:method:: constraintKinematicsSolver(sg: SubGraph) -> ConstraintKinematicsSolver
      :staticmethod:


      Return a constraint/inverse kinematics solver instance

      Creates a constraint kinematics (CK) solver for the specified SubGraph
      and its coordinates and loop constraints. The CK solver uses the
      CoordData for the SubGraph for the coordinates to solver for.
      Coordinates can be frozen during the solution process. Only the
      subhinge coordinates are solved for, and deformation coordinates - if
      any - are not used.


      See the :ref:`kinematics_algorithms_sec` section for more information.

      :param sg: SubGraph instance

      :returns: The constraint kinematics solver instance



   .. py:method:: evalCentroidalMomentum(st: SubTree) -> Karana.Math.SpatialVector
      :staticmethod:


      Calculate the centroidal spatial momentum for the SubTree

      This is the same as the sub-tree's spatial momentum (computed by
      evalSpatialMomentum()), except that this value is referenced about the
      sub-tree's center of mass location, though still represented in the
      virtual root frame. Note that this quantity is conserved in the
      absence of external forces on the system.

      This method does not support deformable bodies.


      See the :ref:`embedded_control_algorithms_sec` section for more
      information.

      :param st: SubTree instance

      :returns: Spatial momentum.



   .. py:method:: evalCentroidalMomentumMatrix(st: SubTree) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Calculate the centroidal momentum matrix for the SubTree

      This returns the centroidal momentum matrix (CMM) that defines the
      mapping between the system generalized velocities and the system's
      centroidal momentum. Note that this matrix is configuration dependent.
      This matrix is used in the context the control of legged robots and
      managing the motion of their CM for stable walking.


      See the :ref:`embedded_control_algorithms_sec` section for more
      information.

      :param st: SubTree instance

      :returns: The 6xnU centroidal momentum matrix (CMM).



   .. py:method:: evalCmLocation(st: SubTree) -> Annotated[numpy.typing.NDArray[numpy.float64], [3, 1]]
      :staticmethod:


      Return the location of the sub-tree CM from the virtual root.

      Return the current location of the center-of-mass frame for the
       whole sub-tree with respect to the virtual root.


      See the :ref:`embedded_control_algorithms_sec` section for more
      information.

      :param st: SubTree instance

      :returns: The position of the CM with respect to the virtual root.



   .. py:method:: evalComputedTorque(st: SubTree) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]
      :staticmethod:


      Calculate the computed torque using NE algorithm

      Method to compute the "computed torque", i.e. the generalized forces
      needed - usually for a specific generalized acceleration inputs. This
      assumes that the state (generalized coordinates (Q) and velocities (U)
      have been set to the desired values in the multibody system, as have
      the generalized accelerations (Udot).

      This method should not to be used for systems with deformable bodies.
      Systems with deformable bodies are under-actuated, while computed
      torque only applies to fully actuated systems. Prescribed subhinges
      and constraints are ignored in this computation.


      See the :ref:`embedded_control_algorithms_sec` section for more
      information.

      :param st: SubTree instance

      :returns: The computed T generalized forces



   .. py:method:: evalConstraintPoseGradientMatrix(sg: SubGraph) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Compute the gradient matrix for the constraint pose errors.

      Compute the gradient matrix for the constraint pose errors for the
      bilateral constraints on the SubGraph.

      Note that the returned matrix may not have full row rank when the
      constraints are not all independent.

      The SubGraph::constraintErrorAt() and the
      SubGraph::constraintResidualAt() methods and can be used to
      look up the constraint instance associated with any specific row index
      in the returned matrix (based on whether with_constraint is 'true' or
      'false' respectively). Similarly, the SubGraph::coordAt() method can
      be used to look up the coordinate instance for a specific column index
      in the returned matrix.

      See the :ref:`constraints_kin_algorithms_sec` section for more
      information.

      :param sg: SubGraph instance

      :returns: The gradient matrix for the constraint pose errors.



   .. py:method:: evalDependentVelCoordinatesMatrix(sg: SubGraph, indep_indices: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]] = ..., full: bool = False) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Compute the dependent velocity coordinates matrix map for the
      specified set of independent coordinates

      For a SubGraph with constraints, only a subset of the velocity
      coordinates are independent. This method computes the matrix X that
      can be used to compute the dependent velocity coordinates, U_d, for
      the specified set of independent velocity coordinates, U_i, via U_d =
      X * U_i,

      See the :ref:`constraints_kin_algorithms_sec` section for more
      information.

      :param sg: SubGraph instance
      :param indep_indices: the list of independent U indices
      :param full: if true, the matrix also includes columns for the
                   independent coordinates, else only for the dependent
                   coordinates

      :returns: the dependent coordinates mapping matrix



   .. py:method:: evalExternalSpatialForce(st: SubTree) -> Karana.Math.SpatialVector
      :staticmethod:


      Calculate the overall external spatial force for for the SubTree about
      its CM

      The computed value includes external force contributions from all of
      the force nodes on all the bodies (including active contact nodes) as
      well as any constraint forces from constraint nodes. The returned
      value is referenced about, and represented in the sub-tree's center of
      mass frame.

      See the :ref:`embedded_control_algorithms_sec` section for more
      information.

      :param st: SubTree instance

      :returns: The overall external spatial force.



   .. py:method:: evalForwardDynamics(st: SubTree) -> None
      :staticmethod:


      Compute the forward dynamics for a system.

      This uses tree-augmented forward dynamics if there are with loop
      constraints, and tree forward dynamics if there are no loop
      constraints.

      The tree-augmented algorithm solves the graph system forward dynamics
      using recursive {{ SOA }} recursive algorithms with exact enforcement
      of the loop constraints. This algorithm does not require the
      computation of inversion of the mass matrix.

      The tree forward dynamics uses Articulated Body Inertia (ATBI) based
      forward dynamics.

      See the :ref:`simulation_algorithms_sec` section for more information.

      :param st: SubTree instance



   .. py:method:: evalFramesOSCM(st: SubTree, body_frames: collections.abc.Sequence[Karana.Frame.Frame], subhinges: collections.abc.Sequence[PhysicalSubhinge] = []) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Calculate the tree system operational space compliance matrix (OSCM)

      The OSCM is defined at J*M^{-1}*J^*, where J is the Jacobian matrix,
      and M is the mass matrix of the system. This method does not use this
      brute force expression. Instead it uses the {{ SOA }} recursive
      methods to do this computation without ever computing the mass matrix
      or its inverse, or even the Jacobian matrix itself.

      In addition, one or more subhinges can also be provided. The returned
      matrix will include additional mass matrix inverse rows and columns
      for these subhinges. This is equivalent to computing the OSCM for the
      "extended Jacobian" defined as [J \\ E], where E is a selector matrix
      that picks out a subset of the subhinges in the system. While the rows
      and columns associated with the frames define a mapping between
      spatial forces and spatial accelerations, the subhinge rows and
      columns define the mapping between generalized forces and generalized
      accelerations. The off-diagonal sub-blocks define cross-term mappings.

      If no subhinges are specified, the returned matrix is the regular
      OSCM, and if no frames are specified, the returned matrix is the sub-
      block of the mass matrix inverse with rows and columns for the
      specified subhinges. This more general form of the OSCM allows users
      to properly handle a mix of constraints from the task and joint
      spaces.


      See the :ref:`mass_prop_algorithms_sec` section for more information.

      :param st: SubTree instance
      :param body_frames: list of Frame instances to compute the OSCM for
      :param subhinges: list of physical subhinge mass matrix inverse
                        contributions to include

      :returns: The tree OSCM matrix



   .. py:method:: evalGravityCompensation(st: SubTree) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]
      :staticmethod:


      Compute the gravity compensation torque for the system

      Compute the generalized forces needed to support the gravitational
      load on the system. This method automatically takes into account
      additional bodies that are attached or detached from the system.


      See the :ref:`embedded_control_algorithms_sec` section for more
      information.

      :param st: SubTree instance

      :returns: The vector of generalized forces.



   .. py:method:: evalIndepPoseConstraintIndices(sg: SubGraph) -> Annotated[numpy.typing.NDArray[numpy.int32], [m, 1]]
      :staticmethod:


      Compute the indices for best independent bilateral constraints on the
      system based on the pose gradients matrix map.

      For a SubGraph with constraints, only a subset of the Q pose-level
      constraints may be independent. This method computes the indices of
      the independent constraints.

      Since the pose and velocity level constraints may not be the same, the
      results from this method may not match the constraint and coordinate
      indices returned by the evalIndepVelConstraintCoordIndices() method.

      See the :ref:`constraints_kin_algorithms_sec` section for more
      information.

      :param sg: SubGraph instance

      :returns: a pair consisting of a list of independent constraint indices, and
                a list of independent coordinate indices based on the pose-level
                constraints



   .. py:method:: evalIndepPoseCoordIndices(sg: SubGraph, available_indices: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]] = ...) -> Annotated[numpy.typing.NDArray[numpy.int32], [m, 1]]
      :staticmethod:


      Compute the best indices for independent Q coordinates for the
      bilateral constraints on the system

      For a SubGraph with constraints, only a subset of the Q pose-level
      coordinates are independent. This method computes the indices of the
      coordinates in the Q vector that are best choice for independent
      coordinates (at the current configuration).  A non-empty
      available_indices list can be used to restrict the pool of indices to
      pick the independent coordinates from.

      Since the pose and velocity level constraints may not be the same, the
      results from this method may not match the constraint and coordinate
      indices returned by the evalIndepVelConstraintCoordIndices() method.

      See the :ref:`constraints_kin_algorithms_sec` section for more
      information.

      :param sg: SubGraph instance
      :param available_indices: If non-empty, the indices to pick the
                                independent coordinates from

      :returns: a list of independent coordinate indices based on the pose-level
                constraints



   .. py:method:: evalIndepVelConstraintCoordIndices(sg: SubGraph, available_indices: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]] = ...) -> tuple[Annotated[numpy.typing.NDArray[numpy.int32], [m, 1]], Annotated[numpy.typing.NDArray[numpy.int32], [m, 1]]]
      :staticmethod:


      Compute the best indices for independent constraints and velocity
      coordinates using the velocity constraint matrix

      For a SubGraph with constraints, only a subset of the U velocity
      coordinates are independent (and not all constraints may be
      independent). This method computes the indices of the independent
      constraints, and the indices of the coordinates in the U vector that
      are best choice for independent velocity coordinates (at the current
      configuration).

      Since the pose and velocity level constraints may not be the same, the
      results from this method may not match the constraint and coordinate
      indices returned by the evalIndepPoseCoordIndices() and
      evalIndepPoseConstraintIndices() methods.

      See the :ref:`constraints_kin_algorithms_sec` section for more
      information.

      :param sg: SubGraph instance
      :param available_indices: the list of indices to pick the independent
                                ones from

      :returns: a pair consisting of a list of independent constraint indices, and
                a list of independent coordinate indices  based on the velocity-
                level constraints



   .. py:method:: evalInverseDynamics(st: SubTree) -> None
      :staticmethod:


      Evaluate Newton-Euler inverse dynamics


      See the :ref:`embedded_control_algorithms_sec` section for more
      information.

      :param st: SubTree instance



   .. py:method:: evalKineticEnergy(st: SubTree) -> float
      :staticmethod:


      Calculate the overall kinetic energy of the component bodies in the
      SubTree

      See the :ref:`mass_prop_algorithms_sec` section for more information.

      :param st: SubTree instance

      :returns: Kinetic energy.



   .. py:method:: evalSerialChainMassMatrixInverse(subtree: SubTree, coord_data: CoordData = None) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Calculate serial-chain system mass matrix inverse using {{ SOA }}
      operator-based decomposition expressions

      This method does not require the mass matrix or matrix inversions to
      compute the mass matrix inverse! The algorithm instead takes advantage
      of an analytical operator based decomposition of the mass matrix
      inverse to carry out the computation much lower cost.

      A CoordData argument can be specified to set the specific order for
      the rows and columns in the computed mass matrix inverse. This method
      cannot be used for systems containing deformable bodies. This mass
      matrix inverse computation can also be done via the more general
      evalTreeMassMatrixInverse() which also works for deformable bodies. We
      however also have this method since it is considerably simpler for the
      simpler serial-chain topology.

      This method does not allow internal 6 dof hinges to avoid ambiguities
      about whether mass properties should be coupled across such hinges.
      Also the prescribed motion flag for any subhinge that has been enabled
      is reset. This is to ensure that the mass matrix computed from this
      method are consistent with the results from the alternative dynamics
      based computation methods.


      See the :ref:`mass_prop_algorithms_sec` section for more information.

      :param st: SubTree instance
      :param coord_data: CoordData to specify the order of the mass matrix
                         inverse's rows and columns

      :returns: The serial-chain mass matrix inverse



   .. py:method:: evalSpatialInertia(st: SubTree, ref_frame: Karana.Frame.Frame = None) -> Karana.Math.SpatialInertia
      :staticmethod:


      Calculate the overall  spatial inertia for a sub-tree

      Return the overall spatial inertia of all the bodies in the sub-tree
      about the reference frame. The multibody virtual root serves as the
      default reference frame.


      See the :ref:`mass_prop_algorithms_sec` section for more information.

      :param st: SubTree instance
      :param ref_frame: reference frame for the spatial inertia (default: the
                        virtual root)

      :returns: The overall tree spatial inertia



   .. py:method:: evalSpatialMomentum(st: SubTree) -> Karana.Math.SpatialVector
      :staticmethod:


      Calculate the overall spatial momentum for the SubTree

      The returned value is by default is referenced about, and represented
      in the virtual root frame. Note that this quantity is conserved in the
      absence of external forces on the system.


      See the :ref:`embedded_control_algorithms_sec` section for more
      information.

      :param st: SubTree instance

      :returns: Spatial momentum.



   .. py:method:: evalSqueezeMatrix(sg: SubGraph) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Return a matrix for computing squeeze generalized forces

      Compute the squeeze matrix, S, whose column space consists of
      "squeeze" generalized forces, i.e. generalized forces that only effect
      internal forces within the constrained multibody and do not induce any
      motion. Thus, the generalized force, S*x, for any vector x will not
      induce any motion. The row dimension is nU(), while the column
      dimension is the size of the constraints on the system.

      Note that the returned matrix may not have full column rank when the
      constraints are not all independent. The
      evalIndepVelConstraintCoordIndices() method can be used to check for
      the columns that are independent.


      See the :ref:`constraints_kin_algorithms_sec` section for more
      information.

      :param sg: SubGraph instance

      :returns: The squeeze matrix.



   .. py:method:: evalTreeMassMatrixCRB(subtree: SubTree, coord_data: CoordData = None) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Calculate the tree system mass matrix using CRB approach

      This method uses the composite rigid body inertias (CRB) recursive
      method for computing the mass matrix

      See the :ref:`mass_prop_algorithms_sec` section for more information.

      This method does not allow internal 6 dof hinges to avoid ambiguities
      about whether mass properties should be coupled across such hinges.
      Also the prescribed motion flag for any subhinge that has been enabled
      is reset. This is to ensure that the mass matrix computed from this
      method are consistent with the results from the alternative dynamics
      based computation methods.

      :param st: SubTree instance
      :param coord_data: CoordData to specify the order of the mass matrix rows
                         and columns

      :returns: The tree mass matrix



   .. py:method:: evalTreeMassMatrixInvDyn(subtree: SubTree, coord_data: CoordData = None) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Calculate the tree system mass matrix using Newton-Euler inverse
      dynamics

      Calculate the tree system mass matrix using NE inverse dynamics. A
      CoordData argument can be specified to set the specific order for the
      rows and columns in the computed mass matrix.

      This method does not currently support deformable bodies.

      This method does not allow internal 6 dof hinges to avoid ambiguities
      about whether mass properties should be coupled across such hinges.
      Also the prescribed motion flag for any subhinge that has been enabled
      is reset. This is to ensure that the mass matrix computed from this
      method are consistent with the results from the alternative dynamics
      based computation methods.


      See the :ref:`mass_prop_algorithms_sec` section for more information.

      :param st: SubTree instance
      :param coord_data: CoordData to specify the order of the mass matrix rows
                         and columns

      :returns: The tree mass matrix



   .. py:method:: evalTreeMassMatrixInvFwdDyn(subtree: SubTree, coord_data: CoordData = None) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Calculate the tree system mass matrix inverse using forward dynamics

      Calculate the tree system mass matrix inverse using ATBI forward
      dynamics. A CoordData argument can be specified to set the specific
      order for the rows and columns in the computed mass matrix inverse.
      This method currently supports physical rigid and flexible bodies, but
      not compound bodies.

      This method does not allow internal 6 dof hinges to avoid ambiguities
      about whether mass properties should be coupled across such hinges.
      Also the prescribed motion flag for any subhinge that has been enabled
      is reset. This is to ensure that the mass matrix computed from this
      method are consistent with the results from the alternative dynamics
      based computation methods.


      See the :ref:`mass_prop_algorithms_sec` section for more information.

      :param st: SubTree instance
      :param coord_data: CoordData to specify the order of the mass matrix
                         inverse's rows and columns

      :returns: The tree mass matrix inverse



   .. py:method:: evalTreeMassMatrixInverse(subtree: SubTree, coord_data: CoordData = None) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Calculate the tree system mass matrix inverse using {{ SOA }}
      decomposition expressions

      This method does not require the mass matrix or matrix inversions to
      compute the mass matrix inverse! The algorithm instead takes advantage
      of an analytical operator based decomposition of the mass matrix
      inverse to carry out the computation much lower cost. For serial-chain
      system, the mass matrix inverse can also be computed using the
      evalSerialChainMassMatrixInverse() specifically for such systems.

      A CoordData argument can be specified to set the specific order for
      the rows and columns in the computed mass matrix inverse. This method
      is currently limited to physical and rigid bodies.

      This method supports both rigid and deformable bodies.

      This method does not allow internal 6 dof hinges to avoid ambiguities
      about whether mass properties should be coupled across such hinges.
      Also the prescribed motion flag for any subhinge that has been enabled
      is reset. This is to ensure that the mass matrix computed from this
      method are consistent with the results from the alternative dynamics
      based computation methods.


      See the :ref:`mass_prop_algorithms_sec` section for more information.

      :param st: SubTree instance
      :param coord_data: CoordData to specify the order of the mass matrix
                         inverse's rows and columns

      :returns: The tree mass matrix inverse



   .. py:method:: evalVelCoordinatePartitioning(sg: SubGraph, available_indices: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]] = ...) -> tuple[Annotated[numpy.typing.NDArray[numpy.int32], [m, 1]], Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]]
      :staticmethod:


      Compute the best indices for independent and dependent velocity
      coordinates matrix map

      For a SubGraph with constraints, only a subset of the velocity
      coordinates are independent. This method computes the indices of the
      coordinates in the U vector that are best choice for independent
      velocity coordinates (at the current configuration). It also returns a
      matrix X that can be used to compute the dependent velocity
      coordinates, U_d, for a set of independent velocity coordinates, U_i,
      via U_d = X * U_i,


      See the :ref:`constraints_kin_algorithms_sec` section for more
      information.

      :param sg: SubGraph instance
      :param available_indices: the list of indices to pick the independent
                                ones from

      :returns: The list of independent coordinate indices and the dependent
                coordinate mapping matrix



   .. py:method:: evalVelocityConstraintMatrix(sg: SubGraph, with_constraints: bool) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]
      :staticmethod:


      Compute the velocity constraint matrix.

      Compute the velocity constraint matrix, Gc, such that Gc * U = 0, i.e.
      the matrix whose null space contains the generalized velocity U values
      that satisfy the loop and coordinate constraints on the SubGraph.

      If "with_constraints" is true, then Gc's columns include ones for the
      loop hinge constraint coordinates, and the block row for each
      constraint contain the mapping to their constraint errors.

      On the other hand, if "with_constraints" is false, Gc's columns
      exclude ones for the constraint coordinates, and the block row for
      each loop hinge constraint maps to the residual vector for each
      constraint. In the latter case, the number of columns and rows shrink
      equally by the number of constraint coordinates.

      Note that the returned matrix may not have full row rank when the
      constraints are not all independent. The
      evalIndepVelConstraintCoordIndices() method can be used to check for
      the rows that are independent.

      The SubGraph::constraintErrorAt() and the
      SubGraph::constraintResidualAt() methods and can be used to
      look up the constraint instance associated with any specific row index
      in the returned matrix (based on whether with_constraint is 'true' or
      'false' respectively). Similarly, the SubGraph::coordAt() method can
      be used to look up the coordinate instance for a specific column index
      in the returned matrix.

      See the :ref:`constraints_kin_algorithms_sec` section for more
      information.

      :param sg: SubGraph instance
      :param with_constraints: If true, columns for the cutjoint loop
                               constraint coords are included

      :returns: The velocity constraint matrix.



   .. py:method:: jacobianGenerator(f2fs: collections.abc.Sequence[Karana.Frame.FrameToFrame], cd: CoordData) -> MultiJacobianGenerator
      :staticmethod:


      Return a Jacobian generator for the subtree

      Create a Jacobian generator object for the specified SubGraph and its
      coordinates and the list source/target frame pairs in the list of
      frame2frames. Note that the resulting jacobian and pose gradient
      matrices will exclude columns for any coordinates frozen in the coord
      data of the subtree.


      See the :ref:`kinematics_algorithms_sec` section for more information.

      :param f2fs: list of FrameToFrames to compute the Jacobian for
      :param cd: the CoordData that specify the columns in the computed
                 Jacobian

      :returns: The Jacobian generator instance



   .. py:method:: modalAnalysis(mm: ModelManager, tol: SupportsFloat | SupportsIndex = 0.001) -> ModalAnalysis
      :staticmethod:


      Perform a modal analysis for the sub-tree.

      This creates a state space model of the system about the current
      configuration, and then solves an eigenproblem to get the frequencies
      and mode shapes.


      See the :ref:`gnc_algorithms_sec` section for more information.

      :param mm: The ModelManager whose SubTree and models will be used for the
                 modal analysis.
      :param tol: The tolerance used to eliminate rigid-body modes.

      :returns: the eigen problem solution for the state space modal



   .. py:method:: stateSpaceGenerator(mm: ModelManager, n_inputs: SupportsInt | SupportsIndex, n_outputs: SupportsInt | SupportsIndex, u_fn: collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], None], y_fn: collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], Annotated[numpy.typing.NDArray[numpy.float64], [m, 1], flags.writeable]], None]) -> Karana.Math.StateSpace
      :staticmethod:


      Create generator for linearized state space representation of the
      system

      Method to create a StateSpace object for creating (A,B,C,D) state
      space linear system matrices for sub-tree multibody system. The
      returned state space generation object's generate(x,u) can be called
      to compute the state space matrices at the state and input vector set
      point values about which the linearization should be carried out.

      The first two inputs are the size of the inputs and outputs for the
      state space system. The u_fn argument is a user-defined function that
      takes (x,u) arguments and sets the appropriate forces, gravity etc
      values for the in the multibody system for dynamics computations. The
      y_fn argument takes (x, u, y) arguments and computes the outputs y for
      the (x, u) and state and input values.


      See the :ref:`gnc_algorithms_sec` section for more information.

      :param mm: The ModelManager whose SubTree and models will be used to
                 generate the StateSpace.
      :param n_inputs: number of inputs
      :param n_outputs: number of outputs
      :param u_fn: function to evaluate the state derivative value for an input
                   value
      :param y_fn: function to evaluate the output value for a given state

      :returns: State space generator instance



.. py:class:: BilateralConstraintBase

   Bases: :py:obj:`Karana.Core.LockingBase`


   Base class for bilateral constraints

   See the :ref:`coordinate_constraints_sec` section for more discussion
   on bilateral constraints.


   .. py:method:: accelError() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the current constraint spatial acceleration error
      :returns: the acceleration error



   .. py:method:: nResiduals() -> int

      Return the size of residuals for the constraint
      :returns: the residuals size for the constraint



   .. py:method:: poseError() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the 6 size pose residual term for the constraint

      Used for computing the pose configuration kinematics

      :returns: The pose error



   .. py:method:: type() -> BilateralConstraintType

      Return the bilateral constraint type
      :returns: the bilateral constraint type



   .. py:method:: velError() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the current constraint spatial velocity error
      :returns: the spatial velocity error as a 6-vector



.. py:class:: BilateralConstraintBaseVars

   Bases: :py:obj:`Karana.Core.LockingBaseVars`


   The Vars for the BilateralConstraintBase class.


   .. py:property:: accel_error
      :type: Karana.Core.VarVec


      accel error


   .. py:property:: n_residuals
      :type: Karana.Core.VarInt


      number of residuals


   .. py:property:: pose_error
      :type: Karana.Core.VarVec


      pose error


   .. py:property:: type
      :type: Karana.Core.VarString


      The constraint type


   .. py:property:: vel_error
      :type: Karana.Core.VarVec


      vel error


.. py:class:: BilateralConstraintType(*args, **kwds)

   Bases: :py:obj:`enum.Enum`


   Create a collection of name/value pairs.

   Example enumeration:

   >>> class Color(Enum):
   ...     RED = 1
   ...     BLUE = 2
   ...     GREEN = 3

   Access them by:

   - attribute access:

     >>> Color.RED
     <Color.RED: 1>

   - value lookup:

     >>> Color(1)
     <Color.RED: 1>

   - name lookup:

     >>> Color['RED']
     <Color.RED: 1>

   Enumerations can be iterated over, and know how many members they have:

   >>> len(Color)
   3

   >>> list(Color)
   [<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

   Methods can be added to enumerations, and members can have their own
   attributes -- see the documentation for details.


   .. py:attribute:: ALL
      :type:  ClassVar[BilateralConstraintType]


   .. py:attribute:: CONVEL_LOOP
      :type:  ClassVar[BilateralConstraintType]


   .. py:attribute:: COORDINATE
      :type:  ClassVar[BilateralConstraintType]


   .. py:attribute:: CUTJOINT_LOOP
      :type:  ClassVar[BilateralConstraintType]


.. py:class:: BodyBase

   Bases: :py:obj:`CoordBase`


   


   .. py:method:: isCompoundBody() -> bool

      Return flag indicating whether this is a CompoundBody

      :returns: true is the body is a CompoundBody



   .. py:method:: isRootBody() -> bool

      Return true is this body is the Multibody's virtual root body

      The default return value if false, since only physical bodies can
      possibly be the virtual root body.

      :returns: true if this is the virtual root body



   .. py:method:: multibody() -> Multibody

      Return the Multibody system that the body belongs to

      :returns: the parent Multibody instance



   .. py:method:: parentHinge() -> HingeBase

      Return the parent hinge for the body.

      For a PhysicalBody, parent hinge is a PhysicalHinge, while for a
      CompoundBody the parent hinge is a CompoundHinge

      :returns: The parent HingeBase instance



   .. py:method:: physicalParentBody() -> PhysicalBody

      Return the PhysicalBody inboard parent body for the body.

      For a PhysicalBody this is simply the inboard body connected to it via
      a PhysicalHinge. For a CompoundBody, this is the single PhysicalBody
      to which the base pnodes in the CompoundBody are connected to.

      :returns: the parent PhysicalBody body instance



.. py:class:: CECompoundBody(name: str, parent_subtree: SubGraph, aggregated_bodies_tree: SubGraph, indep_bodies: collections.abc.Sequence[PhysicalBody], rank_threshold: SupportsFloat | SupportsIndex = 1e-08)
              CECompoundBody(name: str, parent_subtree: SubGraph, subtree: SubGraph, indep_indices_U: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]], indep_indices_Q: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]] = ..., rank_threshold: SupportsFloat | SupportsIndex = 1e-08)

   Bases: :py:obj:`CompoundBody`


   Represents a compound body with embedded constraints (for constraint
   embedding)

   This class is for compound bodies with embedded constraints


   .. py:method:: create(name: str, parent_subtree: SubGraph, aggregated_bodies_tree: SubGraph, indep_bodies: collections.abc.Sequence[PhysicalBody], rank_threshold: SupportsFloat | SupportsIndex = 1e-08) -> CECompoundBody
      :staticmethod:


      Constructs a CECompoundBody with list of independent bodies

      The CECompoundBody will own the SubGraph passed in. That means the
      CECompoundBody will attempt to discard the SubGraph when it is
      discarded.

      :param name: instance name
      :param parent_subtree: the parent SubGraph this the body will belong to
      :param component_bodies: SubGraph with bodies being embedded
      :param indep_bodies: the bodies whose coordinates should be independent
      :param rank_threshold: threshold to use when computing error Jacobian
                             rank

      :returns: a CECompoundBody instance



   .. py:method:: createFromIndices(name: str, parent_subtree: SubGraph, subtree: SubGraph, indep_indices_U: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]], indep_indices_Q: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]] = ..., rank_threshold: SupportsFloat | SupportsIndex = 1e-08) -> CECompoundBody
      :staticmethod:


      Constructs a CECompoundBody with list of independent coord indices

      The option of specifying independent coordinates at the indices level
      gives finer-grain control than the other create() method. Also, this
      method allows specifying different values for the independent Q and U
      coordinates. The U coordinates are used if the Q list is empty. If
      empty indices are specified, then the required number of independent
      coordinate indices will be auto picked.

      The CECompoundBody will own the SubGraph passed in. That means the
      CECompoundBody will attempt to discard the SubGraph when it is
      discarded.

      :param name: instance name
      :param parent_subtree: the parent SubGraph this the body will belong to
      :param component_bodies: SubGraph with bodies being embedded
      :param indep_indices_U: the list of independent U coordinate indices
      :param indep_indices_Q: the list of independent Q coordinate indices
      :param rank_threshold: threshold to use when computing error Jacobian
                             rank

      :returns: a CECompoundBody instance



   .. py:method:: getVars() -> CECompoundBodyVars


   .. py:method:: loopSolver() -> CELoopKinematicsBase

      Return the CELoopKinematicsSolver for the compound body

      :returns: the CE loop solver



.. py:class:: CECompoundBodyVars

   Bases: :py:obj:`CompoundBodyVars`


   


.. py:class:: CECompoundSubhinge

   Bases: :py:obj:`CompoundSubhinge`


   Represents the articulation subhinge class for compound body subhinge
   with embedded constraints


.. py:class:: CELoopKinematicsBase

   Bases: :py:obj:`Karana.Core.Base`


   


   .. py:method:: getIndependentIndicesQ() -> Annotated[numpy.typing.NDArray[numpy.int32], [m, 1]]

      Return the indices of the independent Q coordinates.
      :returns: the independent Q coordinate indices



   .. py:method:: getIndependentIndicesU() -> Annotated[numpy.typing.NDArray[numpy.int32], [m, 1]]

      Return the indices of the independent U coordinates.
      :returns: the independent U coordinate indices



.. py:class:: CELoopKinematicsBaseVars

   Bases: :py:obj:`Karana.Core.BaseVars`


   The Vars for the  CELoopKinematicsBase class.


   .. py:property:: dep_indices_U
      :type: Karana.Core.VarVecInt


      dependent U coord indices


   .. py:property:: indep_indices_Q
      :type: Karana.Core.VarVecInt


      independent Q coord indices


   .. py:property:: indep_indices_U
      :type: Karana.Core.VarVecInt


      independent U coord indices


   .. py:property:: inert_indices_U
      :type: Karana.Core.VarVecInt


      inert U coord indices


.. py:class:: CELoopKinematicsNumeric

   Bases: :py:obj:`CELoopKinematicsBase`


   The numerical iterations based CE kinematics loop solver


   .. py:method:: setIndependentIndices(indep_indices_U: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]], indep_indices_Q: Annotated[numpy.typing.ArrayLike, numpy.int32, [m, 1]] = []) -> None

      Set the independent Q and U coordinate indices.

      If the Q indices are unspecified, they are assumed to be the same as
      the U indices.

      :param indep_indices_U: the independent U coordinate indices
      :param indep_indices_Q: the independent Q coordinate indices



.. py:class:: CELoopKinematicsNumericVars

   Bases: :py:obj:`CELoopKinematicsBaseVars`


   The Vars for the  CELoopKinematicsNumeric class.


   .. py:property:: rows_Y
      :type: Karana.Core.VarVecInt


      independent rows of the Y matrix


.. py:class:: CKFrozenCoordType(*args, **kwds)

   Bases: :py:obj:`enum.Enum`


    Enum with values to classify the type of coordinate to
   freeze


   .. py:attribute:: Q
      :type:  ClassVar[CKFrozenCoordType]


   .. py:attribute:: Q_U
      :type:  ClassVar[CKFrozenCoordType]


   .. py:attribute:: U
      :type:  ClassVar[CKFrozenCoordType]


.. py:class:: CompoundBody(name: str, parent_subtree: SubTree, subtree: SubTree)

   Bases: :py:obj:`BodyBase`, :py:obj:`Karana.Core.LockingBase`


   


   .. py:method:: create(name: str, parent_subtree: SubTree, subtree: SubTree) -> CompoundBody
      :staticmethod:


      Factory create method for a CompoundBody

      The CompoundBody will own the SubTree passed in. That means the
      CompoundBody will attempt to discard the SubTree when it is discarded.

      :param parent_subtree: the parent SubTree for the compound body
      :param name: body name
      :param component_bodies: SubTree with the bodies behind aggregated

      :returns: the CompoundBody instance



   .. py:method:: bodiesTree() -> SubTree

      Return the SubTree for the aggregated bodies

      :returns: the aggregated bodies SubTree



   .. py:method:: containsBody(bd: BodyBase) -> bool

      Return true if the specified BodyBase body is embedded at some level
      within this compound body

      :param bd: the input body

      :returns: true if the body belongs to the subtree



   .. py:method:: flatten(child_cpbd: CompoundBody) -> None

       Replace the embedded child compound body with the embedded
      physical bodies it contains with this compound body.

      The child compound body is discarded by this method after the transfer
      has been completed.

      :param child_cpbd: the embedded compound body to be flattened



   .. py:method:: flattenAll() -> None

      Flatten all the embedded compound bodies within this body.



   .. py:method:: getInterBodyForceTreeFwdDyn() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the stacked vector of interbody forces for the embedded
      physical bodies (at their onodes)

      :returns: the onode referenced interbody forces vector



   .. py:method:: getVars() -> CompoundBodyVars


   .. py:method:: physicalBodiesTree() -> SubTree

      Return the SubTree with aggregated physical bodies

      The returned tree only has physical bodies, and is obtained by
      recursively expanding out any compound bodies within the aggregated
      bodies in this compound body

      :returns: the SubTree with all aggregated physical bodies



.. py:class:: CompoundBodyVars

   Bases: :py:obj:`Karana.Core.LockingBaseVars`, :py:obj:`Karana.Core.BaseVars`


   The Vars for the CompoundBody class.


.. py:class:: CompoundHinge

   Bases: :py:obj:`HingeBase`, :py:obj:`Karana.Core.LockingBase`


   


   .. py:method:: compoundBody() -> CompoundBody

      Returns the CompoundBody for the hinge

      :returns: the outboard CompoundBody instance



.. py:class:: CompoundSubhinge

   Bases: :py:obj:`Karana.Core.LockingBase`, :py:obj:`SubhingeBase`


   


   .. py:method:: getVars() -> CompoundSubhingeVars


.. py:class:: CompoundSubhingeVars

   Bases: :py:obj:`Karana.Core.LockingBaseVars`


   The Vars for the CompoundSubhinge class.


   .. py:property:: Q
      :type: Karana.Core.VarVec


      The Q coordinates


   .. py:property:: Qdot
      :type: Karana.Core.VarVec


      The Qdot coordinates


   .. py:property:: T
      :type: Karana.Core.VarVec


      The T coordinates


   .. py:property:: U
      :type: Karana.Core.VarVec


      The U coordinates


   .. py:property:: Udot
      :type: Karana.Core.VarVec


      The Udot coordinates


.. py:class:: ConstraintKinematicsSolver(name: str, subgraph: SubGraph)

   Bases: :py:obj:`Karana.Core.LockingBase`


   Class for solving for coordinates that satisfy closure constraints

   This class is the base class for bodies from which physical and
   compound body classes are derived. See
   :ref:`constraint_kinematics_sec` section for more information.


   .. py:method:: create(name: str, subgraph: SubGraph) -> ConstraintKinematicsSolver
      :staticmethod:


      Factory method to create a ConstraintKinematicsSolver instance

      Creates constraint kinematics solver for the specified SubGraph's
      coordinates and constraints. Frozen_coordinates can be set in the
      SubGraph's CoordData to specify ones that should be frozen and not
      changed by the kinematics solver.

      :param name: instance name
      :param sg: the SubGraph to use for coordinates and constraints

      :returns: new ConstraintKinematicsSolver instance.



   .. py:method:: clearFrozenCoords() -> None

      Method to empty out list of Q and U frozen coordinates



   .. py:method:: freezeCoord(cb: CoordBase, index: SupportsInt | SupportsIndex, ctype: CKFrozenCoordType = CKFrozenCoordType.Q_U) -> None

      Method to freeze a coordinate component

      The frozen coordinate element values are not changed by the solveQ(),
      solveU() and solveUdot() methods used for solving the constraint
      kinematics.

      :param coord: The coordinate whose element is being frozen
      :param index: The index for the coordinate element  being frozen
      :param type: The coordinate type to freeze



   .. py:method:: frozenCoords(Q_type: bool = True) -> Annotated[numpy.typing.NDArray[numpy.int32], [m, 1]]

      Return the list of frozen coordinate indices.

      :param Q_type: If true, the Q frozen coord indices are returned, else the
                     U ones

      :returns: the list of frozen coordinate indices.



   .. py:method:: getNonfrozenQ() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the non-frozen Q coordinates as an array

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :returns: Array of values



   .. py:method:: getNonfrozenU() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the non-frozen U velocity coordinates as an array


      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :returns: Array of values



   .. py:method:: getNonfrozenUdot() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the non-frozen Udot acceleration coordinates as an array

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :returns: Array of values



   .. py:method:: getVars() -> ConstraintKinematicsSolverVars


   .. py:method:: setNonfrozenQ(Q: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None

      Set the non-frozen Q coordinates.

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :param Q: Array of values.



   .. py:method:: setNonfrozenU(U: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None

      Set the non-frozen U velocity coordinates.

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :param U: Array of values.



   .. py:method:: setNonfrozenUdot(u_dot: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None

      Set the non-frozen Udot acceleration coordinates.

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :param u_dot: Array of values.



   .. py:method:: solveQ() -> float

      Solve for the Q generalized coordinates to satisfy constraints

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: The final error.



   .. py:method:: solveU() -> float

      Solve for the U velocity coordinates to satisfy velocity level
      constraints

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: The final error.



   .. py:method:: solveUdot() -> float

      Solve for the Udot accel coordinates to satisfy accel level
      constraints

      Solve for the Udot gen accel coordinates to zero out constraints
      acceleration error. Unlike, solveQ() and solveU(), this method does
      change the frozen gen accel values.

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: The final error.



   .. py:method:: unfreezeCoord(cb: CoordBase, index: SupportsInt | SupportsIndex, ctype: CKFrozenCoordType = CKFrozenCoordType.Q_U) -> None

      Method to unfreeze a coordinate component

      :param coord: The coordinate whose element is being unfrozen
      :param index: The index for the coordinate element  being unfrozen
      :param type: The coordinate type to unfreeze



.. py:class:: ConstraintKinematicsSolverVars

   Bases: :py:obj:`Karana.Core.LockingBaseVars`


   The Vars for the ConstraintKinematicsSolver class.


   .. py:property:: dependent_indices_Q
      :type: Karana.Core.VarVecInt


      dependent  Q coord indices


   .. py:property:: frozen_indices_Q
      :type: Karana.Core.VarVecInt


      frozen Q coord indices


   .. py:property:: frozen_indices_U
      :type: Karana.Core.VarVecInt


      frozen U coord indices


   .. py:property:: pose_error_norm
      :type: Karana.Core.VarDouble


      pose error


   .. py:property:: pose_gradient_rank
      :type: Karana.Core.VarInt


      pose gradient matrix rank


   .. py:property:: pose_gradient_size
      :type: Karana.Core.VarVecInt


      pose gradient matrix size


   .. py:property:: vel_error_norm
      :type: Karana.Core.VarDouble


      vel error


   .. py:property:: vel_jacobian_rank
      :type: Karana.Core.VarInt


      velocity Jacobian matrix rank


   .. py:property:: vel_jacobian_size
      :type: Karana.Core.VarVecInt


      velocity Jacobian matrix size


.. py:class:: ConstraintNode

   Bases: :py:obj:`Node`


   


   .. py:method:: lookupOrCreate(name: str, bd: PhysicalBody) -> ConstraintNode
      :staticmethod:


      Factory method to create a ConstraintNode instance.

      This method first checks if a detached constraint node is available
      for use. If not, the method creates a new ConstraintNode for the body.

      :param bd: the physical parent body
      :param name: the name for the node

      :returns: a ConstraintNode instance



   .. py:method:: loopConstraint() -> LoopConstraintBase

      Return the loop constraint using this constraint node

      :returns: the loop constraint using this node.



.. py:class:: CoordBase

   Represents the base class for Q, U etc coordinate data providers.

   This class is the base class for subhinges, compound subhinges, and
   bodies that can contribute motion degrees of freedom to the system.
   These degrees of freedom are associated with coordinates designated Q,
   U etc.

   See :ref:`coords_sec` section for discussion on Q, U etc coordinates.


   .. py:method:: accumT(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  accumT(fill_value: SupportsFloat | SupportsIndex) -> None

      Accumulate the T generalized forces to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value to add to the current generalized forces.



   .. py:method:: getQ() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the global (chart) Q coordinates

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: Array of values.



   .. py:method:: getQdot() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the Qdot rate coordinates

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: Array of values.



   .. py:method:: getT() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the T generalized forces

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: Array of values.



   .. py:method:: getU() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the U velocity coordinates

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: Array of values.



   .. py:method:: getUdot() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the Udot acceleration coordinates

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: Array of values.



   .. py:method:: id() -> int

      Return the object's id.

      :returns: The object's id.



   .. py:method:: nQ() -> int

      The number of generalized coords for the CoordBase.

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: the number of generalized coordinates



   .. py:method:: nU() -> int

      The number of velocity coords for the CoordBase_T.

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: the number of velocity coordinates



   .. py:method:: name() -> str

      Return the object's name.

      :returns: The object's string name.



   .. py:method:: setQ(val: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setQ(fill_value: SupportsFloat | SupportsIndex) -> None

      Set the global (chart) Q coordinates to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value.



   .. py:method:: setT(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setT(fill_value: SupportsFloat | SupportsIndex) -> None

      Set the T generalized forces to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value.



   .. py:method:: setU(val: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setU(fill_value: SupportsFloat | SupportsIndex) -> None

      Set the U velocity coordinates to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value.



   .. py:method:: setUdot(val: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setUdot(fill_value: SupportsFloat | SupportsIndex) -> None

      Set the Udot acceleration coordinates to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value.



.. py:class:: CoordData(arg0: str, arg1: collections.abc.Sequence[CoordBase])
              CoordData(arg0: str, arg1: collections.abc.Sequence[CoordBase])

   Bases: :py:obj:`Karana.Core.LockingBase`


   


   .. py:method:: create(arg0: str, arg1: collections.abc.Sequence[CoordBase]) -> CoordData
      :staticmethod:


      CoordData creation static factory method.

      :param name: instance name
      :param coordobjs_list: list of CoordBase objects to manage

      :returns: a new CoordData instance



   .. py:method:: accumT(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  accumT(fill_value: SupportsFloat | SupportsIndex) -> None

      Accumulate the T generalized forces to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value to add to the current generalized forces.



   .. py:method:: coordAt(u_offset: SupportsInt | SupportsIndex) -> tuple[CoordBase, int]

      Returns coord obj and its coord offset corresponding to overall U
      offset

      The CoordData has get/set methods to pack and unpack the coordinate
      values for its set of CoordBase instances. This method returns the
      CoordBase and its local coordinate offset corresponding to the
      specified overall U offset value.

      :param u_offset: the input overall U offset value

      :returns: The CoordBase instance and its local U coord offset



   .. py:method:: coordBases() -> list[CoordBase]

      Get a vector of the CoordBase instances for this CoordData
      :returns: A vector of CoordBase instances.



   .. py:method:: coordOffsets(arg0: CoordBase) -> CoordDataCoordOffset

      Returns the packing offset for the specified CoordBase

      The CoordData has get/set methods to pack and unpack the coordinate
      values for its set of CoordBase instances. This method returns the
      offsets for the Q and U values for the specified CoordBase in these
      arrays.

      :param c: The CoordBase to check for

      :returns: A CoordOffset struct with the Q and U offsets



   .. py:method:: dumpState(prefix: str = '', filter: collections.abc.Sequence[str] = ['ALL']) -> None

      Print out the coordinate values for all the coordinates

      The filter values for controlling output are any combination of:
         'Q', 'U', 'Udot', 'T', 'ALL'

      :param prefix: The prefix to add to each output line
      :param filter: Filter output to the specified coordinate types.



   .. py:method:: getQ() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the Q coordinates as an array

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: Array of values



   .. py:method:: getT() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the T generalized forces as an array

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: Array of values



   .. py:method:: getU() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the U velocity coordinates as an array

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: Array of values



   .. py:method:: getUdot() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the Udot acceleration coordinates as an array

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: Array of values



   .. py:method:: getVars() -> CoordDataVars


   .. py:method:: nQ() -> int

      The number of Q generalized coords for the CoordBase.

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: the number of coordinates



   .. py:method:: nU() -> int

      The number of U velocity coords for the CoordBase.

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :returns: the number of velocity coordinates



   .. py:method:: parent(cb: CoordBase) -> CoordBase

      Return the CoordBase that is the closed parent to the specified one

      :param cb: the CoordBase to check for

      :returns: the CoordBase parent if it exists



   .. py:method:: setQ(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setQ(val: SupportsFloat | SupportsIndex) -> None

      Set the Q coordinates to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value.



   .. py:method:: setT(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setT(fill_value: SupportsFloat | SupportsIndex) -> None

      Set the T generalized forces to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value.



   .. py:method:: setU(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setU(val: SupportsFloat | SupportsIndex) -> None

      Set the U velocity coordinates to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value.



   .. py:method:: setUdot(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setUdot(val: SupportsFloat | SupportsIndex) -> None

      Set the Udot acceleration coordinates to a constant value

      See :ref:`coords_sec` section for discussion on Q, U etc coordinates.

      :param fill_value: Fill value.



   .. py:method:: toDS() -> Karana.Dynamics.SOADyn_types.CoordDataDS

      Create a CoordDataDS from this CoordData model.

      :returns: * *CoordDataDS*
                * *A CoordDataDS instance with values set to match this model.*



   .. py:method:: toMap() -> dict[str, list[Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]]]

      Dump the CoordData to a map. They keys are named after the
             CoordBase objects, and the values are a vector of the Coord
             Base data.

      Helper method used by the DataStruct methods.

      :returns: A map representation of the CoordData object.



.. py:class:: CoordDataCoordOffset

   .. py:property:: Q
      :type: int


      offset for the generalized coordinates


   .. py:property:: U
      :type: int


      offset for the generalized velocity coordinates


.. py:class:: CoordDataVars

   Bases: :py:obj:`Karana.Core.LockingBaseVars`, :py:obj:`Karana.Core.BaseVars`


   The Vars for the CoordData class.


   .. py:property:: nQ
      :type: Karana.Core.VarInt


      nQ


   .. py:property:: nU
      :type: Karana.Core.VarInt


      nU


   .. py:property:: n_coord_base
      :type: Karana.Core.VarInt


      number of CoordBases


.. py:class:: CoordinateConstraint(name: str, mb: Multibody, oshg: PhysicalSubhinge, pshg: PhysicalSubhinge)

   Bases: :py:obj:`BilateralConstraintBase`, :py:obj:`Karana.Core.LockingBase`


   


   .. py:method:: create(name: str, mb: Multibody, oshg: PhysicalSubhinge, pshg: PhysicalSubhinge) -> CoordinateConstraint
      :staticmethod:


      Factory method for creating a CoordinateConstraint instance

      :param mb: The Multibody instance
      :param osh: the first Karana::Dynamics::PhysicalSubhinge instance
      :param psh: the second Karana::Dynamics::PhysicalSubhinge instance
      :param name: the name for the loop constraint instance

      :returns: a CoordinateConstraint instance



   .. py:method:: getScaleRatio() -> float

      Return the Q(pshg)/Q(oshg) coordinate scale ratio

      :returns: The scale ratio



   .. py:method:: getVars() -> CoordinateConstraintVars


   .. py:method:: osubhinge() -> PhysicalSubhinge

      Return the first subhinge for this coordinate constraint

      :returns: The first subhinge.



   .. py:method:: psubhinge() -> PhysicalSubhinge

      Return the second subhinge for this coordinate constraint

      :returns: The second subhinge.



   .. py:method:: setScaleRatio(arg0: SupportsFloat | SupportsIndex) -> None

      Set the Q(pshg)/Q(oshg) coordinate scale ratio

      :param scale_ratio: The scale ratio



.. py:class:: CoordinateConstraintVars

   Bases: :py:obj:`BilateralConstraintBaseVars`


   


   .. py:property:: scale_ratio
      :type: Karana.Core.VarDouble


      The scale ratio for the CoordinateConstraint.


.. py:class:: FramePairHinge

   Bases: :py:obj:`HingeBase`, :py:obj:`Karana.Frame.OrientedChainedFrameToFrame`


   Represents the articulation class used by PhysicalHinge  and
   LoopConstraintCutJoint physical articulation classes

   See :ref:`body_hinge_sec` section for more discussion on hinges.


   .. py:method:: fitQ(T: Karana.Math.HomTran, f_to_f: Karana.Frame.FrameToFrame = None) -> Karana.Math.HomTran

      Method to find best fit Q coordinates for the hinge for the input
      transform

      This method can be used to initialize the hinge's Q coordinates to
      values that best fit the input transform T. If f_to_f is non-null,
      then T is assumed to be the desired relative transform for the f_to_f,
      and if null then this hinge is used as the f_to_f.

      :param T: Input transform
      :param f_to_f: The frame to frame instance the T transform is for

      :returns: The residual error transform



   .. py:method:: fitU(V: Karana.Math.SpatialVelocity, f_to_f: Karana.Frame.FrameToFrame = None) -> Karana.Math.SpatialVelocity

      Method to find best fit U velocity coordinates for the input spatial
      velocity vector

      This method can be used to initialize the hinge U velocity coordinates
      to values that best fit the input spatial velocity for the hinge. If
      f_to_f is non-null, then V is assumed to be the desired spatial
      velocity for this f_to_f , and if null then this hinge is used as the
      f_to_f .

      :param V: Input spatial velocity
      :param f_to_f: The frame to frame instance the V spatial velocity is for

      :returns: The residual spatial velocity error



   .. py:method:: fitUdot(A: Karana.Math.SpatialAcceleration, f_to_f: Karana.Frame.FrameToFrame = None) -> Karana.Math.SpatialAcceleration

      Method to find best fit Udot accel coordinates for the input spatial
      acceleration vector

      This method can be used to initialize the hinge Udot acceleration
      coordinates to values that best fit the input spatial acceleration for
      the hinge. If f_to_f is non-null, then A is assumed to be the desired
      spatial accel for this f_to_f , and if null then this hinge is used as
      the f_to_f .

      :param alpha: Input spatial acceleration
      :param f_to_f: The frame to frame instance the A spatial acceleration is
                     for

      :returns: The residual spatial acceleration error



   .. py:method:: getVars() -> FramePairHingeVars


   .. py:method:: subhinge(index: SupportsInt | SupportsIndex) -> PhysicalSubhinge

      Return the SubhingeBase subhinge instance at the specified index

      :param index: the subhinge index

      :returns: the subhinge object



   .. py:method:: subhinges() -> list[PhysicalSubhinge]

      Return the list of SubhingeBase subhinges
      :returns: the list of subhinges



.. py:class:: FramePairHingeVars

   Bases: :py:obj:`Karana.Frame.OrientedChainedFrameToFrameVars`


   


   .. py:property:: hinge_type
      :type: Karana.Core.VarString


      The hinge type


   .. py:property:: nQ
      :type: Karana.Core.VarInt


      The number of Q coordinates


   .. py:property:: nU
      :type: Karana.Core.VarInt


      The number of U coordinates


   .. py:property:: n_subhinges
      :type: Karana.Core.VarInt


      The number of subhinges


.. py:class:: FrameToFrameJacobianGenerator(name: str, f_to_f: Karana.Frame.FrameToFrame, coord_data: CoordData)

   Bases: :py:obj:`Karana.Core.LockingBase`


   


   .. py:method:: create(name: str, f_to_f: Karana.Frame.FrameToFrame, coord_data: CoordData) -> FrameToFrameJacobianGenerator
      :staticmethod:


      Factory method for creating a FrameToFrameJacobianGenerator

      :param name: name for the new object
      :param f_to_f: the Karana::Frame::FrameToFrame instance to compute the
                     relative Jacobian for
      :param coord_data: the list of CoordData with the coordinates

      :returns: the new FrameToFrameJacobianGenerator instance



   .. py:method:: jacobian(analytical: bool = True) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]

      Method to compute the Jacobian matrix

      Return the overall assembled 6xnU Jacobian to the target frame spatial
      velocity (represented in the target frame) with respect to the path
      map's source frame from the U generalized velocities of all the
      component coordinate providers. Use the component analytical Jacobians
      if analytical is true, or the numerical differencing approach
      otherwise. If not provided, the source frame is assumed to be the
      newtonian frame. This Jacobian is such that the following will be
      true:

         f2f.relSpVel() == f2f.relTransform().getUnitQuaternion() (jac *
         getU())

      The input polarity map must be compatible with the same source/target
      frame values used when calling this method. It will be created if it
      is not provided. Coordinate providers not in the polarity map are
      assumed to not have an effect on the target frame, and zero sub-matrix
      entries are assigned for them.

      For normal inverse kinematics (e.g., with respect to inertial frame),
      we normally exclude coordinate providers that are outboard of (or on a
      separate branch from) the target frame of interest.

      Otherwise, the polarity map value for each coordinate provider is used
      to negate the sub-matrix entries for the ones with opposed polarity.
      We include such opposed polarity coordinate provider elements for
      cases where the source frame is not the inertial frame, and the
      coordinate provider is on the path from the source to the target
      frame, but may be on a different branch and o the path from the source
      frame to the common ancestor frame. In this case, the coordinate
      provider's effect is the negative of the normal effect on the target
      frame.

      :param analytical: If true, use the analytical process, else numerical
                         differencing

      :returns: the Jacobian matrix



   .. py:method:: jacobianDot(analytical: bool = True, mb: Multibody = None) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]

      Method to compute the time derivative of the Jacobian matrix

      The multibody argument is required when analytical is false, since a
      total time derivative of the Jacobian needs to be computed, and this
      requires that all the multibody coordinates be perturbed.

      :param analytical: If true, use the analytical process, else numerical
                         differencing
      :param mb: the multibody system

      :returns: the time derivative of the Jacobian matrix



   .. py:method:: poseGradient(analytical: bool = True) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]

      Method to compute the pose gradient matrix

      Return the overall assembled 6xnU gradient for the target frame pose
      with respect to the Q generalized coordinates of all the component
      coordinate providers. Use the component analytical gradient
      contributions if analytical is true, or the numerical differencing
      approach otherwise.

      The input polarity map must be compatible with the same source/target
      frame values used when calling this method. It will be created if it
      is not provided. Coordinate providers not in the polarity map are
      assumed to not have an effect on the target frame, and zero sub-matrix
      entries are assigned for them. For normal inverse kinematics (e.g.,
      with respect to inertial frame), we exclude coordinate providers that
      are outboard of (or on a separate branch from) the target frame of
      interest.

      Otherwise, the polarity map value for each coordinate provider is used
      to negate the sub-matrix entries for the ones with opposed polarity.
      We include such opposed polarity coordinate provider elements for
      cases where the source frame is not the inertial frame, and the
      coordinate provider is on the path from the source to the target
      frame, but may be on a different branch and o the path from the source
      frame to the common ancestor frame. In this case, the coordinate
      provider's effect is the negative of the normal effect on the target
      frame.

      We can choose to eliminate some columns from the computed matrix by
      specifying the corresponding coordinate providers in the skip_coords
      list. An alternative option is to set the columns to zero values, but
      this is non-optimal since the column values would need to be computed
      (only to be discarded), and the returned matrix would be larger.

      :param analytical: If true, use the analytical process, else numerical
                         differencing

      :returns: the pose gradient matrix



.. py:class:: HingeBase

   


   .. py:method:: getHookeHingeParams(arg0: Karana.Math.UnitQuaternion) -> HingeParams
      :staticmethod:


      Helper method to compute the onode, pnode transform and axis params
      for a
      HingeType::HOOKE hinge

      For a HingeType::HOOKE joint, an outboard body's frame's Y-axis is
      constrained to remain perpendicular to an inboard body frame's X-axis,
      and the pair of frames to remain co-located.

      :param ij_q: the inboard to outboard frames relative orientation unit
                   quaternion

      :returns: struct with the hinge onode, pnode and axis parameter values



   .. py:method:: getInlineHingeParams() -> HingeParams
      :staticmethod:


      Helper method to compute  the onode, pnode transform and axis params
      for an
      HingeType::INLINE hinge

      For an HingeType::INLINE joint, an outboard body frame is constrained
      to translate only along an inboard body frame's Z-axis

      :returns: struct with the hinge onode, pnode and axis parameter values



   .. py:method:: getInplaneHingeParams() -> HingeParams
      :staticmethod:


      Helper method to compute  the onode, pnode transform and axis params
      for an
      HingeType::INPLANE hinge

      For an HingeType::INPLANE joint, an outboard body frame is constrained
      to translate only within the inboard frame's XY-plane

      :returns: struct with the hinge onode, pnode and axis parameter values



   .. py:method:: getParallelHingeParams() -> HingeParams
      :staticmethod:


      Helper method to compute  the onode, pnode transform and axis params
      for a
      HingeType::PARALLEL hinge

      For a HingeType::PARALLEL joint, an outboard body frame's Z-axis is
      constrained to remain parallel to an inboard body frame's Z-axis. It
      is assumed that the outboard frame's Z-axis is parallel to the inboard
      frame's Z-axis to begin with.

      :returns: struct with the hinge onode, pnode and axis parameter values



   .. py:method:: getPerpendicularHingeParams(arg0: Karana.Math.UnitQuaternion) -> HingeParams
      :staticmethod:


      Helper method to compute  the onode, pnode transform and axis params
      for a
      HingeType::PERPENDICULAR hinge

      For a HingeType::PERPENDICULAR joint, an outboard body frame's Z-axis
      is constrained to remain perpendicular to an inboard body frame's
      Z-axis

      :param ij_q: the inboard to outboard frames relative orientation unit
                   quaternion

      :returns: struct with the hinge onode, pnode and axis parameter values



   .. py:method:: hingeTypeString(arg0: HingeType) -> str
      :staticmethod:


      Helper method to return the string name for a HingeType hinge type
      :param htype: the hinge type

      :returns: the hinge type as a string



   .. py:method:: coordData() -> CoordData

      Return the CoordData for the hinge's list of subhinges

      :returns: the CoordData for the subhinges



   .. py:method:: hingeType() -> HingeType

      Return the HingeType hinge type for this hinge.
       @returns The hinge type used by this body.



   .. py:method:: nSubhinges() -> int

      Return the number of subhinges in the hinge
      :returns: the number of subhinges



   .. py:method:: nU() -> int

      Return the total nU dofs from all the subhinges

      :returns: the total number of U coordinates across the subhinges



   .. py:method:: subhinge(index: SupportsInt | SupportsIndex) -> SubhingeBase

      Return the SubhingeBase subhinge instance at the specified index

      :param index: the subhinge index

      :returns: the subhinge object



   .. py:method:: subhinges() -> list[SubhingeBase]

      Return the list of SubhingeBase subhinges
      :returns: the list of subhinges



.. py:class:: HingeNode

   Bases: :py:obj:`Node`


   Represents the base class for physical HingePnode and HingeOnode
   classes


   .. py:method:: hinge() -> PhysicalHinge

      Return the PhysicalHinge hinge the node is attached to

      :returns: The attached PhysicalHinge instance



.. py:class:: HingeOnode

   Bases: :py:obj:`HingeNode`


   


   .. py:method:: getInterBodyForceTAFwdDyn() -> Karana.Math.SpatialVector

      Return the interbody force at the onode for Tree Augmented (TA)
      dynamics with constraints

      This method returns the interbody force at the onode when doing TA
      dynamics for the system in the presence of loop constraints. This is
      only meant to be used for regular hinges (not cut-joint hinges)

      :returns: the inter-body spatial force



   .. py:method:: getInterBodyForceTreeFwdDyn() -> Karana.Math.SpatialVector

      Return the inter-body spatial force at the hinge

      While the spatial force is at the onode, and in the onode frame, its
      sign is that for the version applying on the outboard (the pnode)
      body. This values should be negated to get the equal and opposite
      spatial force on the onode's body.

      :returns: the inter-body spatial force



.. py:class:: HingeOnodeATBIFilterVectors

   .. py:attribute:: zplus
      :type:  Karana.Math.SpatialVector


   .. py:attribute:: zplus_extra
      :type:  Karana.Math.SpatialVector


.. py:class:: HingeOnodeATBIMatrices

   .. py:property:: Pplus
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [6, 6]]



.. py:class:: HingeOnodeATBISmootherVectors

   .. py:attribute:: alpha_plus
      :type:  Karana.Math.SpatialVector


   .. py:attribute:: alpha_plus_extra
      :type:  Karana.Math.SpatialVector


.. py:class:: HingeParams

    Struct with hinge parameters for the HingeType::HOOKE,
   HingeType::INLINE etc hinge types defined by motion
   constraints between a pair of frames on the inboard and outboard
   bodies.

   This struct is used to specify the parameter data for a hinge that is
   being specified as a constraint (such as a HOOKE, INLINE,
   PERPENDICULAR) between arbitrary frames attached to the the parent and
   child bodies ('i' denotes the constraint frame attached to the inboard
   body, and 'j' the constraint frame attached to the outboard body).
   Helper methods such as getHookeHingeParams(), getInlineHingeParams()
   etc compute the required poses of the onode and pnode frames, and
   subhinge axes in a HingeParams instance needed to meet the constraint
   objectives so that it can be used to set up the desired hinge.


   .. py:attribute:: i_to_onode_q
      :type:  Karana.Math.UnitQuaternion


   .. py:attribute:: j_to_pnode_q
      :type:  Karana.Math.UnitQuaternion


   .. py:property:: axes
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]


      3xm matrix with columns defining the 1-dof subhinge axes


.. py:class:: HingePnode

   Bases: :py:obj:`HingeNode`


   


   .. py:method:: crbInertiaMatrix() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]

       Update and return the CRB spatial inertia for the body referenced to
       the pnode.

       This is a (nmodes+6) size square, symmetric, positive
      semi-definite matrix

       @return the CRB inertia matrix.



.. py:class:: HingePnodeATBIFilterVectors

   .. py:attribute:: z
      :type:  Karana.Math.SpatialVector


.. py:class:: HingePnodeATBIMatrices

   .. py:property:: P
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [6, 6]]



.. py:class:: HingePnodeATBISmootherVectors

.. py:class:: HingeType(*args, **kwds)

   Bases: :py:obj:`enum.Enum`


   Create a collection of name/value pairs.

   Example enumeration:

   >>> class Color(Enum):
   ...     RED = 1
   ...     BLUE = 2
   ...     GREEN = 3

   Access them by:

   - attribute access:

     >>> Color.RED
     <Color.RED: 1>

   - value lookup:

     >>> Color(1)
     <Color.RED: 1>

   - name lookup:

     >>> Color['RED']
     <Color.RED: 1>

   Enumerations can be iterated over, and know how many members they have:

   >>> len(Color)
   3

   >>> list(Color)
   [<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

   Methods can be added to enumerations, and members can have their own
   attributes -- see the documentation for details.


   .. py:attribute:: BALL
      :type:  ClassVar[HingeType]


   .. py:attribute:: BALL_QUAT
      :type:  ClassVar[HingeType]


   .. py:attribute:: COMPOUND
      :type:  ClassVar[HingeType]


   .. py:attribute:: CUSTOM
      :type:  ClassVar[HingeType]


   .. py:attribute:: CYLINDRICAL
      :type:  ClassVar[HingeType]


   .. py:attribute:: FULL6DOF
      :type:  ClassVar[HingeType]


   .. py:attribute:: GIMBAL
      :type:  ClassVar[HingeType]


   .. py:attribute:: HELICAL
      :type:  ClassVar[HingeType]


   .. py:attribute:: HOOKE
      :type:  ClassVar[HingeType]


   .. py:attribute:: INLINE
      :type:  ClassVar[HingeType]


   .. py:attribute:: INPLANE
      :type:  ClassVar[HingeType]


   .. py:attribute:: LOCKED
      :type:  ClassVar[HingeType]


   .. py:attribute:: PARALLEL
      :type:  ClassVar[HingeType]


   .. py:attribute:: PERPENDICULAR
      :type:  ClassVar[HingeType]


   .. py:attribute:: PLANAR
      :type:  ClassVar[HingeType]


   .. py:attribute:: REVOLUTE
      :type:  ClassVar[HingeType]


   .. py:attribute:: SLIDER
      :type:  ClassVar[HingeType]


   .. py:attribute:: TRANSLATIONAL
      :type:  ClassVar[HingeType]


   .. py:attribute:: TRANSLATIONAL3
      :type:  ClassVar[HingeType]


   .. py:attribute:: UJOINT
      :type:  ClassVar[HingeType]


   .. py:method:: to_yaml(representer, node)
      :classmethod:


      Class method used to represent HingeType in a yaml file.



   .. py:method:: from_yaml(_, node) -> Self
      :classmethod:


      Construct a HingeType from yaml file data.



   .. py:method:: to_json(o: HingeType) -> dict[str, Any]
      :staticmethod:


      Class method used to represent HingeType in a json file.



   .. py:method:: from_json(d: dict[str, Any]) -> Self
      :classmethod:


      Construct a HingeType from json file data.



.. py:class:: HybridNonLinearSolverStatus(*args, **kwds)

   Bases: :py:obj:`enum.Enum`


   Status of the HybridNonLinearSolver solver


   .. py:attribute:: ImproperInputParameters
      :type:  ClassVar[HybridNonLinearSolverStatus]


   .. py:attribute:: NotMakingProgressIterations
      :type:  ClassVar[HybridNonLinearSolverStatus]


   .. py:attribute:: NotMakingProgressJacobian
      :type:  ClassVar[HybridNonLinearSolverStatus]


   .. py:attribute:: RelativeErrorTooSmall
      :type:  ClassVar[HybridNonLinearSolverStatus]


   .. py:attribute:: Running
      :type:  ClassVar[HybridNonLinearSolverStatus]


   .. py:attribute:: TolTooSmall
      :type:  ClassVar[HybridNonLinearSolverStatus]


   .. py:attribute:: TooManyFunctionEvaluation
      :type:  ClassVar[HybridNonLinearSolverStatus]


   .. py:attribute:: UserAsked
      :type:  ClassVar[HybridNonLinearSolverStatus]


.. py:class:: LevenbergMarquardtStatus(*args, **kwds)

   Bases: :py:obj:`enum.Enum`


   Status of the LevenbergMarquardt solver


   .. py:attribute:: CosinusTooSmall
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: FtolTooSmall
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: GtolTooSmall
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: ImproperInputParameters
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: NotStarted
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: RelativeErrorAndReductionTooSmall
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: RelativeErrorTooSmall
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: RelativeReductionTooSmall
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: Running
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: TooManyFunctionEvaluation
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: UserAsked
      :type:  ClassVar[LevenbergMarquardtStatus]


   .. py:attribute:: XtolTooSmall
      :type:  ClassVar[LevenbergMarquardtStatus]


.. py:class:: Linear3Subhinge

   Bases: :py:obj:`PhysicalSubhinge_T_3_3`


   Represents a 3 dof translational subhinge


   See :ref:`subhinges_sec` section for more information on physical
   subhinges.


.. py:class:: LinearSubhinge

   Bases: :py:obj:`Physical1DofSubhinge`


   Represents a 1 dof translational subhinge


   See :ref:`subhinges_sec` section for more information on physical
   subhinges.


.. py:class:: LockedSubhinge

   Bases: :py:obj:`PhysicalSubhinge_T_0_0`


   Represents a locked subhinge

   See :ref:`subhinges_sec` section for more information on physical
   subhinges.


.. py:class:: LoopConstraintBase

   Bases: :py:obj:`BilateralConstraintBase`


   Base class for loop constraints See the :ref:`constraints_sec` section
   for more discussion on loop constraints.


   .. py:method:: constraintFrameToFrame() -> Karana.Frame.FrameToFrame

      Return the Karana::Frame::FrameToFrame whose oframe/pframe define the
      constraint

      When the constraint is satisfied, the relative configuration, velocity
      and accel values across the
      Karana::Frame::FrameToFrame f2f are constrained to those
      satisfied by the associated constraint hinge

      :returns: the constraint FrameToFrame instance



   .. py:method:: sourceNode() -> ConstraintNode | None

      Return the source (oframe) node for the constraint

      Return the source frame as a constraint node, if the source frame is
      attached to a non-virtual root body. Return a null pointer if the
      source frame is not attached to a multibody body.

      :returns: the source constraint node.



   .. py:method:: targetNode() -> ConstraintNode | None

      Return the target (pframe) node for the constraint

      Return the target frame as a constraint node, if the target frame is
      attached to a non-virtual root body. Return a null pointer if the
      target frame is not attached to a multibody body.

      :returns: the source constraint node.



.. py:class:: LoopConstraintBaseVars

   Bases: :py:obj:`BilateralConstraintBaseVars`


   The Vars for the LoopConstraintBase class.


   .. py:property:: has_source_node
      :type: Karana.Core.VarBool


      has source node


   .. py:property:: has_target_node
      :type: Karana.Core.VarBool


      has target node


   .. py:property:: rel_Q
      :type: Karana.Core.VarMat


      The rel_Q matrix


   .. py:property:: source_Q
      :type: Karana.Core.VarMat


      The source_Q matrix


   .. py:property:: target_Q
      :type: Karana.Core.VarMat


      The target_Q matrix


.. py:class:: LoopConstraintConVel(name: str, mb: Multibody, constraint_f_to_f: Karana.Frame.FrameToFrame)

   Bases: :py:obj:`LoopConstraintBase`


   Class for constant velocity loop constraints

   This constraint requires that a component of the relative
   angular/linear velocity of a pair of body constraint nodes projected
   onto a unit axis be equal. This constraint only applies at the
   velocity and acceleration levels, and not the positional level.

   See the :ref:`convel_loop_constraints_sec` section for more discussion
   on convel loop constraints.


   .. py:method:: create(name: str, mb: Multibody, constraint_f_to_f: Karana.Frame.FrameToFrame) -> LoopConstraintConVel
      :staticmethod:


      Factory method for creating a LoopConstraintConVel instance

      :param mb: The Multibody instance
      :param constraint_f_to_f: the Karana::Frame::FrameToFrame defining the
                                constrained Frame pair
      :param name: the name for the loop constraint instance

      :returns: a LoopConstraintCutJoint instance



   .. py:method:: getUnitAxis() -> Annotated[numpy.typing.NDArray[numpy.float64], [3, 1]]

      Get the unit axis to which the convel constraint applies.

      :returns: The unit axis vector in the source node frame



   .. py:method:: getVars() -> LoopConstraintConVelVars


   .. py:method:: isRotational() -> bool

      Get whether the constraint is on relative angular velocity

      :returns: If the constraint is angular, else linear



   .. py:method:: setInput(arg0: SupportsFloat | SupportsIndex, arg1: SupportsFloat | SupportsIndex) -> None

      Set the velocity and acceleration inputs for the convel constraint.

      The input is used to set the difference between the source
       and target component velocity and acceleration component values.

      :param vel: The input velocity
      :param accel: The input accel



   .. py:method:: setUnitAxis(arg0: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], arg1: bool) -> None

      Set the unit axis long which the convel constraint applies.

      :param axis: The unit axis vector in the source node frame
      :param is_rotational: If true, the constraint is assumed to on relative
                            angular velocity, else translational



.. py:class:: LoopConstraintConVelVars

   Bases: :py:obj:`LoopConstraintBaseVars`


   


   .. py:property:: unit_axis
      :type: Karana.Core.VarVec3


      the unit axis


.. py:class:: LoopConstraintCutJoint(name: str, mb: Multibody, constraint_f_to_f: Karana.Frame.FrameToFrame, htype: HingeType, subhinge_types: collections.abc.Sequence[SubhingeType] = [])

   Bases: :py:obj:`LoopConstraintBase`


   Class for loop constraints that are based on a hinge to define the
   constraint See the :ref:`cutjoint_constraints_sec` section for more
   discussion on cutjoint loop constraints.


   .. py:method:: create(name: str, mb: Multibody, constraint_f_to_f: Karana.Frame.FrameToFrame, htype: HingeType, subhinge_types: collections.abc.Sequence[SubhingeType] = []) -> LoopConstraintCutJoint
      :staticmethod:


      Factory method for creating a LoopConstraintCutJoint instance

      :param mb: The Multibody instance
      :param constraint_f_to_f: the Karana::Frame::FrameToFrame defining the
                                constrained Frame pair
      :param name: the name for the loop constraint instance
      :param htype: the HingeBase::HingeType defining the constraint type
      :param subhinge_types: the list of SubhingeType subhinge types for a
                             custom hinge type

      :returns: a LoopConstraintCutJoint instance



   .. py:method:: toPhysicalHinge(lc: LoopConstraintCutJoint, reverse: bool) -> PhysicalHinge
      :staticmethod:


      Convert this loop constraint into an inter-body PhysicalHinge

      Replaces the loop constraint with a hinge between the constraint nodes
      to make one body the child of the other. This method can only be
      called when the new child body (either of source or target) is a base
      body with a 6 dof hinge. This requirement allows us to preserve the
      system's tree topology. If reverse false, the target node's body is
      made the child of the source node's body, and the converse if reverse
      is true. The original loop constraint is discarded by this method.

      :param lc: The loop constraint to replace with a hinge
      :param reverse: If true, reverse the polarity of the hinge

      :returns: the new hinge



   .. py:method:: errorFrameToFrame() -> Karana.Frame.FrameToFrame

      the Karana::Frame::FrameToFrame that measures the constraint residual
      error

      The constraint is fully satisfied only when this f2f relative
      transform, spatial velocity and acceleration values are zero, i.e. its
      oframe and pframe are coincident

      :returns: the error FrameToFrame instance



   .. py:method:: getInterBodyForceTAFwdDyn() -> Karana.Math.SpatialForce

      Return the interbody spatial force at the source node for TA dynamics

      This method returns the interbody force at the source when doing TA
      dynamics for the loop constraint. The force has the sign as if acting
      on the target node (this is consistent with our general convention to
      book keep the pnode's inter-body force at the onode). The term also
      includes contributions from any generalized forces at the cut-joint.

      The method should only be called after TA forward dynamics has been
      called, since it expects the constraint forces to be set in the
      constraint nodes. Also this method assumes that the T value in the
      CoordData member is the cutjoint generalized force value.

      :returns: the inter-body spatial force



   .. py:method:: getVars() -> LoopConstraintCutJointVars


   .. py:method:: hinge() -> FramePairHinge

      Return the FramePairHinge hinge associated with this loop constraint

      When the constraint is satisfied, the relative configuration, velocity
      and accel values across the f2f are constrained to those satisfied by
      the associated constraint hinge

      :returns: the FramePairHinge instance



   .. py:method:: spExternalForceFromT(arg0: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], arg1: bool) -> None

      Apply the input T generalized force at the constraint hinge as an
      external force.

      This method is used to handle any generalized forces at cut-joints.
      Once the joint is cut, its generalized forces are no longer included
      in the normal dynamics. The workaround is to convert the cut-joint
      generalized forces into equivalent equal and opposite external forces
      at the constraint nodes for the cut-joint.

      :param T: the input generalized forces
      :param no_accumulate: if true, then accumulate the input forces at the
                            constraint nodes



.. py:class:: LoopConstraintCutJointVars

   Bases: :py:obj:`LoopConstraintBaseVars`


   The Vars for the LoopConstraintCutJoint class.


.. py:class:: MMFunctions

    Struct with optional user-defined functions to be used by the
   model manager


   .. py:property:: post_deriv_fns
      :type: PrePostCallbackRegistry


      



      Optional function called after evaluating system derivative. Useful
       for
      passing state derivative values to models that needs them, and to
      perform data logging.


   .. py:property:: post_hop_fns
      :type: PrePostCallbackRegistry


      Optional function called at the end of a hop
      step. Useful for processing external models that use the new state to
      set sensor inputs for closed-loop controllers, data logging, updating
      visualization, cleaning up the state to null out constraint errors
      etc.


   .. py:property:: pre_deriv_fns
      :type: PrePostCallbackRegistry


      



      Optional function called before evaluating system derivative. Useful
       for
      setting gravity accel and other forces on the system.


   .. py:property:: pre_hop_fns
      :type: PrePostCallbackRegistry


      Optional function called at the start of a hop
      step. Useful for propagating discrete states, sanitizing the input
      state (e.g., for changing coordinate chart origin), calling FSM step
      functions, processing external models to apply force inputs from
      closed-loop controllers etc.


   .. py:property:: step_validate_fn
      :type: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], bool]


      Optional function called at the end of a integration
      step to decide whether to accept the new state, or to roll back to the
      state at the start of the hop. Useful for repeating a the time step
      when the new state has invalid values.


   .. py:property:: terminate_advance_to_fns
      :type: TerminateCrossingCallbackRegistry


      Optional function called to check whether to terminate the
      state propagation prematurely before the state advancement end time
      has been reached. Handy when the simulation has already reached an end
      state (possibly for an FSM) and there is no value in continuing on
      with the state propagation. This check is only done at the end of a
      hop, so there may be some timing slop in the check for an end state.
      This is in contrast with the zero-crossing check which is done within
      a hop to end the hop precisely when the zero-crossing condition is
      met.


   .. py:property:: zero_crossing_fns
      :type: ZeroCrossingCallbackRegistry


      Optional function used for terminating a hop when a
      zero-crossing condition has been met. Useful for getting a simulation
      hop to terminate precisely when the implicitly defined zero-crossing
      condition occurs instead of continuing till the specified hop end
      time. See the :ref:`zero_crossings_sec` section for more discussion on
      zero crossing detection.

      The zero crossing functions return a bool. This should be true if the
      zero has been crossed. The second argument to the function is a
      boolean. This will be true when we have reached the zero, and false
      otherwise.


.. py:class:: MMOptionsModelManager

   Options for the model manager


   .. py:method:: create() -> MMOptionsModelManager
      :staticmethod:


      Create an instance of MMOptions.

      :returns: A pointer to the newly created MMOptions.



   .. py:property:: baumgarte_alpha
      :type: float


      the Baumgarte damping coefficient


   .. py:property:: baumgarte_beta
      :type: float


      the Baumgarte stiffness coefficient


.. py:class:: MMSolverType(*args, **kwds)

   Bases: :py:obj:`enum.Enum`


    Enum with values to classify the reason for the termination of a
   step


   .. py:attribute:: INVERSE_DYNAMICS
      :type:  ClassVar[MMSolverType]


   .. py:attribute:: KINEMATICS
      :type:  ClassVar[MMSolverType]


   .. py:attribute:: TREE_AUGMENTED_DYNAMICS
      :type:  ClassVar[MMSolverType]


   .. py:attribute:: TREE_DYNAMICS
      :type:  ClassVar[MMSolverType]


   .. py:attribute:: UNDEFINED
      :type:  ClassVar[MMSolverType]


.. py:class:: ModalAnalysis

   .. py:property:: phi
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]



   .. py:property:: w
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]



.. py:class:: ModelManager(st: SubTree, sp_opts: MMOptionsModelManager | None = None, solver_type: MMSolverType = MMSolverType.UNDEFINED)

   Bases: :py:obj:`Karana.Core.LockingBase`


   
    Class to manage the multibody dynamics and KModels

    See :ref:`system_level_models_sec` section for more information on
   the ModelManager class.


   .. py:attribute:: trace_state_propagator
      :type:  bool


   .. py:method:: create(st: SubTree, sp_opts: MMOptionsModelManager | None = None, solver_type: MMSolverType = MMSolverType.UNDEFINED) -> ModelManager
      :staticmethod:


      Create an instance of the ModelManager.

      If the solver type is not specified, the constructor will use
      TREE_DYNAMICS if the specified st argument is a pure subtree (and not
      SubGraph), or if is the multibody instance itself with no bilateral
      constraints. For all other st, an error will be raised - and a legal
      solver type must be explicitly specified since there is no good way to
      infer one.

      :param st: the SubTree instance
      :param mm_opts: options for the model manager
      :param solver_type: the solver type

      :returns: An instance of the ModelManager.



   .. py:method:: __deepcopy__(arg0: Any) -> ModelManager


   .. py:method:: assembleState() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Combine the current associated SubTree state and continuous KModel
      states
             into one vector.

      This state vector reflects the current state of the Multibody and
      KModels' continuous states, which may be different than the state
      vector in the integrator.

      The packing order is the same as the integrator. This can be used to
      create an initial state for the integrator as
      follows:
      state_propagator->setState(state_propagator->assembleState()).

      :returns: A state vector representing the Multibody and KModels' continuous
                states of this ModelManager.



   .. py:method:: assembleStateDeriv() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Combine the current associated SubTree state derivative and continuous
      KModel state derivatives into one vector.

      This state derivative vector reflects the current state of the
      Multibody and KModels' continuous states' derivatives, which may be
      different than the state vector in the integrator.

      The packing order is the same as the integrator.

      :returns: A state vector derivative representing the Multibody and KModels'
                continuous states' derivatives of this ModelManager.



   .. py:method:: derivFunction(t: SupportsFloat | SupportsIndex | numpy.timedelta64, x: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], dx: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1], flags.writeable]) -> None
                  derivFunction(t: SupportsInt | SupportsIndex, x: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], dx: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1], flags.writeable]) -> None

      Invoke the derivative function for use by the integrator

      This method is used to compute the state derivative by the
       numerical integrator for propagating system state.

      :param t: the current time
      :param x: the current state
      :param dx: the computed state derivative



   .. py:method:: equilibrateSciPy(qcols, method='least_squares')

      Equilibrate the state using inverse dynamics and the SciPy nonlinear solver.

          Parameters
          ----------
          self : ModelManager
              The state propagator
          qcols: list[int] | None
              The Q coordinate indices to use as independent ones
          method: The SciPy nonlinear solver method to use




   .. py:method:: getRegisteredModel(arg0: str) -> Karana.Models.BaseKModel

      Return the registered model with the specified name

      :param name: the name of the model being sought

      :returns: The registered model or null if there is no model with matching
                name



   .. py:method:: getRegisteredModels() -> list[Karana.Models.BaseKModel]

      Return a vector or registered models.

      :returns: A vector of registered models.



   .. py:method:: getSubTree() -> SubTree

      Return the SubTree used by this ModelManager.

      :returns: The SubTree used by this ModelManager.



   .. py:method:: getTime() -> numpy.timedelta64

      Return the current state propagation time value
      :returns: the Ktime time value



   .. py:method:: getTimeKeeper() -> TimeKeeper

      Return the TimeKeeper used by this ModelManager.

      :returns: The TimeKeeper used by this ModelManager.



   .. py:method:: getVars() -> ModelManagerVars


   .. py:method:: hardReset() -> None

      Reset the size of the internal state vector to match the size of the
      SubTree state + the size of all the continuous model states.

      This method also makeNotReadys the state, so setState must be called
      afterwards.



   .. py:method:: nstates() -> int

      Return the state vector size
      :returns: the state vector size



   .. py:method:: registerModel(model: Karana.Models.BaseKModel) -> None

      Register the provided BaseKModel model instance with the model
      manager.

      See :ref:`kmodels_sec` section for more discussion on component models
      and the :ref:`model_register_sec` section on registering models.

      Registering a model is a way to activate a model so that it is used in
      the physics computations. See :ref:`kmodels_sec` section for more
      discussion on component models.

      :param model:
                    - The model to register.



   .. py:method:: setSolverType(arg0: MMSolverType) -> None

      Set the solver type for the propagator

      :param solver_type: the new solver type



   .. py:method:: setState(x: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> None

      Reset the integrator to the new state values

      This is also referred to as a *soft reset*. This method assumes that
      only the state values have changed, and there have been no
      configuration changes causing changes to the size or structure of the
      state vector. The input state vector elements for subhinges should
      contain *global* coordinate values. This method resets the chart
      offsets for all regular and constraint subhinges for the sub graph.

      The state itself is often created using the assembleState method.


      $See also:

      assembleState

      :param x: the new state value



   .. py:method:: setSubTree(st: SubTree, solver_type: MMSolverType = MMSolverType.UNDEFINED) -> None

      Set the SubTree used by this ModelManager.

      :param st: The new SubTree for this ModelManager to use.
      :param solver_type: The solver_type to use for the new SubTree.



   .. py:method:: setTime(t: SupportsFloat | SupportsIndex | numpy.timedelta64) -> None

      Reset the integrator to the new time value

      This is also referred to as a *soft reset*. If the time set is
      different than the current time, this will attempt to rescheduled all
      TimedEvents appropriately; however, since TimedEvents can have
      arbitrary reschedule_fns, it is impossible to meet all corner cases.
      Use this with caution when you have non-uniform TimedEvents.  See
      :ref:`system_state_sec` section for more on this topic.

      :param t: the new time



   .. py:method:: solverType() -> MMSolverType

      Return the solver type for the propagator

      :returns: the solver type



   .. py:method:: unregisterModel(model: Karana.Models.BaseKModel) -> None

      Unregister the provided BaseKModel model from the model manager.

      Unregistering a model is a way to deactivate a model so that it is no
      longer used in the physics computations. See the :ref:`kmodels_sec`
      section for more discussion on component models and the
      :ref:`model_register_sec` section on registering models.

      :param model:
                    - The model to unregister.



   .. py:property:: fns
      :type: MMFunctions


      User defined functions to tailor the behavior of the state
      propagator


.. py:class:: ModelManagerVars

   Bases: :py:obj:`Karana.Core.LockingBaseVars`


   The Vars for the ModelManager class.


   .. py:property:: n_subtree_states
      :type: Karana.Core.VarInt


      number of SubTree states


   .. py:property:: nstates
      :type: Karana.Core.VarInt


      number of states


   .. py:property:: solver_type
      :type: Karana.Core.VarString


      solver type


   .. py:property:: time
      :type: Karana.Core.VarDouble


      current time


.. py:class:: MultiJacobianGenerator(arg0: str, arg1: collections.abc.Sequence[Karana.Frame.FrameToFrame], arg2: CoordData)

   Bases: :py:obj:`Karana.Core.LockingBase`


   Class for the Jacobian generator for a list of
   Karana::Frame::FrameToFrame related frame pairs for a list of
   CoordData

   This class builds on the FrameToFrameJacobianGenerator class to
   support multiple Karana::Frame::FrameToFrame instances. This class is
   used by the ConstraintKinematicsSolver to compute Jacobians needed for
   the iterative constraint kinematics algorithms. See the
   :ref:`jacobian_sec` section for more discussion on Jacobians.

   CAUTION: When using the "analytical" computation approach
   (recommended), an important assumption is that the f2f paths contains
   only regular edges, i.e. one whose transform values that depend on
   coordinate values do so via regular subhinges and body coordinates,
   and not in come non-standard way (e.g., subtree CM frames, ephemeris
   frames). Since this Jacobian generator will not know about these non-
   standard dependencies, it will not be able to take them into account
   when computing the Jacobians, so use the "numerical" approach for
   these situations.


   .. py:method:: create(arg0: str, arg1: collections.abc.Sequence[Karana.Frame.FrameToFrame], arg2: CoordData) -> MultiJacobianGenerator
      :staticmethod:


      Factory method for creating a new MultiJacobianGenerator instance

      :param name: the name for the new object.
      :param f2fs: the list of FrameToFrame's for the Jacobian generator
      :param coord_data: the CoordDatas to use for the Jacobian columns

      :returns: a new MultiJacobianGenerator instance



   .. py:method:: jacobian(analytical: bool = True) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]

      Return the Jacobian matrix

      Return the Jacobian matrix map from the free U velocity coordinate to
      the f2fs relative velocity.

      :param analytical: If true, use the analytical method, else numerical
                         differencing

      :returns: the Jacobian matrix



   .. py:method:: jacobianDot(analytical: bool = True, mb: Multibody = None) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]

      Method to compute the time derivative of the Jacobian matrix

      The multibody argument is required when analytical is false, since a
      total time derivative of the Jacobian needs to be computed, and this
      requires that all the multibody coordinates be perturbed.

      :param analytical: If true, use the analytical method, else numerical
                         differencing
      :param mb: the multibody system

      :returns: the time derivative of the Jacobian matrix



   .. py:method:: poseGradient(analytical: bool = True) -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]

      Return the pose gradient matrix

      Return the gradient matrix map from the free Q configuration
      coordinates to the f2fs relative pose

      :param analytical: If true, use the analytical method, else numerical
                         differencing

      :returns: the pose gradient matrix



.. py:class:: Multibody(name: str, fc: Karana.Frame.FrameContainer, mbroot_frame: Karana.Frame.Frame | None = None, newtonian_frame: Karana.Frame.Frame | None = None)

   Bases: :py:obj:`SubGraph`


   


   .. py:method:: create(name: str, fc: Karana.Frame.FrameContainer, mbroot_frame: Karana.Frame.Frame | None = None, newtonian_frame: Karana.Frame.Frame | None = None) -> Multibody
      :staticmethod:


      Factory method to create a new Multibody instance.

      The virtual root body is attached to the multibody root frame. If the
      multibody root frame is not specified, then the method uses the
      newtonian frame, and if that is unspecified as well, then the method
      uses the frame container's root frame as the root frame.

      :param name: The name for the new Multibody instance
      :param fc: The Karana::Frame::FrameContainer to use
      :param mbroot_frame: The parent Karana::Frame::Frame for the virtual root
                           body
      :param newtonian_frame: The inertial Karana::Frame::FrameToFrame frame

      :returns: a new Multibody instance



   .. py:method:: constraints() -> list[BilateralConstraintBase]

      Return the list of existing constraint instances (enabled and
      disabled)

      :returns: constraints list



   .. py:method:: frameContainer() -> Karana.Frame.FrameContainer

      Return the Karana::Frame::FrameContainer frame container for the
      multibody system

      See the :ref:`manual_creation_sec` section for more information.
      :returns: the Karana::Frame::FrameContainer instance



   .. py:method:: getConstraint(arg0: str) -> BilateralConstraintBase

      Look up a existing constraint by name (enabled or disabled) See
      :ref:`constraints_sec` section for more info on constraints.
      :param name: the constraint's name

      :returns: the CoordinateConstraint instance



   .. py:method:: getNewtonianFrame() -> Karana.Frame.Frame

      Return the Newtonian Karana::Frame::Frame

      See the :ref:`manual_creation_sec` section for more information.
      :returns: the Newtonian Frame instance



   .. py:method:: getNodeAncestor(frame: Karana.Frame.Frame) -> Node

       Look up and return the closest Node ancestor for a
       Karana::Frame::Frame.

       Return null if the Karana::Frame::Frame is not the descendant
      of a body Node. See :ref:`body_nodes_sec` section for information on
      body nodes.

       @param frame the input Karana::Frame::Frame @return the ancestor Node
       for the Frame.



   .. py:method:: getScene() -> Karana.Scene.ProxyScene | None

      Get the Karana::Scene::ProxyScene scene member for the multibody
      system See :ref:`proxyscene_sec` section for more information on
      Karana::Scene::ProxyScene.

      :returns: The scene member



   .. py:method:: setScene(scene: Karana.Scene.ProxyScene | None) -> None

      Set the Karana::Scene::ProxyScene instance for the multibody system

      See :ref:`proxyscene_sec` section for more information on
      Karana::Scene::ProxyScene.

      :param scene: The scene instance



   .. py:method:: toDS() -> Karana.Dynamics.SOADyn_types.SubGraphDS

      Create a SubGraphDS from this Multibody model.

      :returns: * *SubGraphDS*
                * *A SubGraphDS instance with values set to match this model.*



   .. py:method:: toFullyAugmentedModel() -> None

      Convert all PhysicalHinges into LoopConstraintCutJoints to create a
      fully augmented (FA) model

      The FA model consists of independent physical bodies, where the couple
      hinges are replaced with equivalent loop constraints. The FA model is
      also referred to as the absolute coordinates model. The main purpose
      of this method is to create FA models to compare and benchmark
      performance of absolute coordinate dynamics with the minimal
      coordinate methods. This method introduces constraints, and hence the
      TA algorithm must be used for dynamics computations for the FA model.
      See :ref:`FA_TA_models_sec` section for discussion of FA models.



   .. py:method:: virtualRoot() -> PhysicalBody

      Returns the virtual root BodyBase body for the tree.
      :returns: The virtual root body.



   .. py:method:: fromDS(mbody_ds: Karana.Dynamics.SOADyn_types.SubGraphDS, fc: Karana.Frame.FrameContainer, newtonian_frame: Optional[Karana.Frame.Frame] = None, scene: Optional[Karana.Scene.WebScene] = None) -> Self
      :classmethod:


      Convert the SubGraphDS to a Multibody.

      :param mbody_ds: The Multibody DataStruct to convert to a multibody.
      :type mbody_ds: SubGraphDS
      :param fc: The FrameContainer to use for the Multibody.
      :type fc: FrameContainer

      :returns: The Multibody created from the SubGraphDS.
      :rtype: Multibody



   .. py:method:: tui() -> Karana.KUtils.MultibodyTUI.MultibodyTUI

      Create the TUI for this multibody system.



   .. py:method:: setupGraphics(*, port: int = 29523, axes: float = 1.0, client_type: Literal['auto', 'electron', 'notebook', 'webbrowser', 'selenium'] | None = 'auto', origin_frame: Optional[Karana.Frame.Frame] = None, wait_for_clients: int = 0, wait_for_clients_timeout: float = 0.0, stick_parts: Literal['auto', 'always', 'never'] = 'auto') -> tuple[Callable[[], None], Karana.Scene.WebScene]

      Helper to easily set up graphics

      :param port: Port to bind the WebUI server to. Use 0 to request an arbitrary unused
                   port.
      :type port: int = 29523
      :param axes: Length of axes visualization on root frame.
      :type axes: float = 1.0
      :param client_type:
                          Policy for launching a client.
                              "auto": pick the best option for the environment and OS
                              "electron": always launch the electron client
                              "notebook": always open an IFrame in IPython
                              "webbrowser": always open a browser tab
                              "selenium": always open a chrome driver using selenium
                              None: don't automatically open a client
                          Defaults to "auto".
      :type client_type: Literal["auto", "electron", "notebook", "webbrowser", "selenium"] | None
      :param origin_frame: Frame to use as the world origin for the graphics scene. If None, use
                           the Multibody's virtualRoot.
      :type origin_frame: Optional[Frame] = None
      :param wait_for_clients: Number of client connections to wait for before continuing.
      :type wait_for_clients: int = 0
      :param wait_for_clients_timeout: Number of seconds to wait before raising an error if wait_for_clients
                                       is positive.
      :type wait_for_clients_timeout: float = 0.0
      :param stick_parts:
                          Policy for creating stick parts. Defaults to "auto".
                              "auto": create stick parts if the ProxyScene is empty
                              "always": unconditionally create stick parts
                              "never": unconditionally don't create stick parts
      :type stick_parts: Literal["auto", "always", "never"] = "auto"

      :returns: A tuple containing the a cleanup callable and the graphics scene.
      :rtype: tuple[Callable, WebScene]



   .. py:method:: gui(port=29534, client_type: Literal['auto', 'electron', 'notebook', 'webbrowser', 'selenium'] | None = 'auto', wait_for_clients: int = 0, wait_for_clients_timeout: float = 0.0, stick_parts: Literal['auto', 'always', 'never'] = 'auto', stick_parts_config: Karana.Dynamics.StickPartsConfig | None = None, name_to_label_map: dict[str, str] | None = None, sp: Karana.Dynamics.StatePropagator | None = None, sim: Karana.KUtils.Sim.Sim | None = None, time_display_period: float | None = 0.01, graphics_origin_frame: Optional[Karana.Frame.Frame] = None) -> Karana.KUtils.MultibodyWebUI.MultibodyWebUI

      Create the GUI for this multibody system.

      :param self: The multibody instance
      :type self: Multibody
      :param port: Port to bind the WebUI server to. Use 0 to request an arbitrary unused
                   port. Defaults to 29534.
      :type port: int
      :param client_type:
                          Policy for launching a client.
                              "auto": pick the best option for the environment and OS
                              "electron": always launch the electron client
                              "notebook": always open an IFrame in IPython
                              "webbrowser": always open a browser tab
                              "selenium": always open a chrome driver using selenium
                              None: don't automatically open a client
                          Defaults to "auto".
      :type client_type: Literal["auto", "electron", "notebook", "webbrowser", "selenium"] | None
      :param wait_for_clients: Number of client connections to wait for before continuing.
                               Defaults to 0.
      :type wait_for_clients: int
      :param wait_for_clients_timeout: Number of seconds to wait before raising an error if wait_for_clients
                                       is positive. Defaults to 0.
      :type wait_for_clients_timeout: float
      :param graphics_origin_frame: If given, and the GUI needs to setup graphics, use this as the
                                    origin frame instead of the multibody virtual root.
      :type graphics_origin_frame: Optional[Frame]
      :param stick_parts:
                          Policy for creating stick parts. Defaults to "auto".
                              "auto": create stick parts if the ProxyScene is empty
                              "always": unconditionally create stick parts
                              "never": unconditionally don't create stick parts
      :type stick_parts: Literal["auto", "always", "never"] = "auto"
      :param stick_parts_config: Configuration parameters for the stick parts.
      :type stick_parts_config: StickPartsConfig | None
      :param name_to_label_map: Dictionary defining the labels to use for each body in the visjs graphs
                                display
      :type name_to_label_map: dict[str, str] | None
      :param sp: The state propagator to use if available.
      :type sp: StatePropagator | None
      :param sim: The Sim instance if available
      :type sim: Sim | None
      :param time_display_period: If not None and sp is given, add a time display refreshing
                                  with this period in simulation time. Defaults to 0.01.
      :type time_display_period: float | None



.. py:class:: Node

   Bases: :py:obj:`Karana.Frame.Frame`


   Represents the body node base class

   This class is for nodes attached to PhysicalBody instances. See
   :ref:`body_nodes_sec` section for more information on the Node class.


   .. py:method:: lookupOrCreate(name: str, bd: PhysicalBody, force_node: bool = False) -> Node
      :staticmethod:


      Factory method to create a Node instance.

      This method first checks if a detached node is available for use. If
      not, the method creates a new Node for the body.

      :param bd: the physical parent body
      :param name: the name for the node
      :param force_node: if true, the node is marked as one that can apply
                         forces

      :returns: a Node instance



   .. py:method:: lookupOrCreateContact(bd: PhysicalBody, T: Karana.Math.HomTran, name: str = '') -> Node
      :staticmethod:


      Factory method to create a Node instance that is used for contact
      forces.

      A contact force node is one whose forces will only apply for for one
      dynamics calculation. Whenever the externals are cleared, these nodes
      will become inactive. These nodes are always force nodes. If no name
      is provided, one will be given to them automatically.

      This method first checks if a detached node is available for use. If
      not, the method creates a new Node for the body.

      :param bd: The physical parent body
      :param T: The transform of the node relative to the body.
      :param name: instance name

      :returns: a Node instance



   .. py:method:: deformationProvider() -> NodeDeformationProvider

      Return the <NodeDeformationProvider deformation provider for the node
      :returns: the NodeDeformationProvider instance



   .. py:method:: detach() -> None

      Method to detach the node from the current parent body

      Once detached, the node is put in the pool of detached nodes for
      possible reuse when new nodes are needed.



   .. py:method:: getBodyToNodeTransform() -> Karana.Math.HomTran

      Return the node's transform with respect to the parent PhysicalBody's
      body frame

      This transform defines the Node's location for an undeformed
      PhysicalBody parent body. Use Karana::Frame::FrameToFrame queries to
      find the actual location of a Node after body deformation.

      :returns: the node's offset transform



   .. py:method:: getSpForce() -> Karana.Math.SpatialForce

       Get the external spatial force at the node represented in the node
       frame.
      :returns: the spatial force vector



   .. py:method:: getVars() -> NodeVars


   .. py:method:: isExternalForceNode() -> bool

      Check whether the Node is a force node

      A force node is one that has been designated as one that can apply
      forces on the body. See :ref:`body_nodes_sec` section for more on
      force nodes.

      :returns: true if the node is a force node



   .. py:method:: parentBody() -> PhysicalBody

      Return the PhysicalBody parent body for the node.
      :returns: the parent PhysicalBody instance



   .. py:method:: setBodyToNodeTransform(t: Karana.Math.HomTran) -> None

      Set the node's transform with respect to the parent PhysicalBody's
      body frame

      This transform defines the Node's location for an undeformed
      PhysicalBody parent body. Use Karana::Frame::FrameToFrame queries to
      find the actual location of a Node after body deformation.

      :param t: the offset transform



   .. py:method:: setExternalSpForce(spforce: Karana.Math.SpatialForce, ref_frame: Karana.Frame.Frame = None) -> None

      Set the external spatial force at the node represented in the
      specified Karana::Frame::Frame frame.

      This method resets the specified spatial force to the currently set
      spatial force in the node. If no frame is specified, then the spatial
      force is assumed to be represented in the local node frame, else the
      force is immediately rotated from the specified frame into the node's
      local frame.  Note that most algorithms will check this node for a
      spatial force only it has been registered as a force node - so make
      sure that the node has bee registered as a force node.

      :param spforce: The spatial force value
      :param ref_frame: The reference Karana::Frame::Frame frame for the
                        spatial force values



.. py:class:: NodeDeformationProvider

   Bases: :py:obj:`Karana.Core.Base`


   Base abstract class node deformation

   See :ref:`modal_flex_body_sec` section for more information of
   deformation provider classes.

   Base abstract class that provides data and methods for modeling node
   deformation


.. py:class:: NodeVars

   Bases: :py:obj:`Karana.Frame.FrameVars`, :py:obj:`Karana.Core.LockingBaseVars`, :py:obj:`Karana.Core.BaseVars`


   


   .. py:property:: external_spforce
      :type: Karana.Core.VarSpatialForce


      external force on the node


   .. py:property:: force_node
      :type: Karana.Core.VarBool


      True if this is a force node


   .. py:property:: parent_body
      :type: Karana.Core.VarString


      parent body


.. py:class:: NonlinearSolver(name: str, input_dim: SupportsInt | SupportsIndex, value_dim: SupportsInt | SupportsIndex, f: collections.abc.Callable[[Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]], Annotated[numpy.typing.NDArray[numpy.float64], [m, 1], flags.writeable]], None], j: collections.abc.Callable[[Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]], Annotated[numpy.typing.NDArray[numpy.float64], [m, n], flags.writeable, flags.c_contiguous]], None] = None)

   Bases: :py:obj:`Karana.Core.LockingBase`


   NonlinearSolver class manages a nonlinear problem and associated
   solver.


   .. py:method:: create(name: str, input_dim: SupportsInt | SupportsIndex, value_dim: SupportsInt | SupportsIndex, f: collections.abc.Callable[[Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]], Annotated[numpy.typing.NDArray[numpy.float64], [m, 1], flags.writeable]], None], j: collections.abc.Callable[[Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]], Annotated[numpy.typing.NDArray[numpy.float64], [m, n], flags.writeable, flags.c_contiguous]], None] = None) -> NonlinearSolver
      :staticmethod:


      NonlinearSolver constructor. This is a container that holds the
      information needed to solve a nonlinear problem. However, the solver
      itself is not added during construction. You must either pass in a
      solver with setSolver or create one with createSolver.

      :param name: The name of the Nonlinear solver.
      :param input_dim: The number of inputs.
      :param value_dim: The number of values (outputs).
      :param f: The cost function. This should take in a vector of inputs and
                output a vector of outputs.
      :param j: The jacobian function. This is optional, if not specified, the
                jacobian will be computed by forward numerical differentiation.

      :returns: A ks_ptr to a new Nonlinear solver instance.



   .. py:method:: createSolver(solver: SolverType) -> None

      Create a solver of the given type. This will return a copy of the
      shared pointer to the solver as well as set the solver for this
      NonlinearSolver.
      :param solver: The solver type to create.

      :returns: The solver that was created.



   .. py:method:: getCachedJacobian() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]

      Get the current Jacobian matrix being used by the solver.

      :returns: The current Jacobian matrix being used by the solver.



   .. py:method:: getF() -> collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], None]

      Get the cost function.
      :returns: The cost function.



   .. py:method:: getJac() -> collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], Annotated[numpy.typing.ArrayLike, numpy.float64, [m, n]]], None]

      Get the jacobian function.
      :returns: The jacobian function.



   .. py:method:: setF(f: collections.abc.Callable[[Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]], Annotated[numpy.typing.NDArray[numpy.float64], [m, 1], flags.writeable]], None]) -> None

      Set the cost function. After setting the function, you will need to
      re-create the
             solver if one has already been set. Otherwise, the solver will
             still retain the
      old cost function.
      :param f: The cost function.



   .. py:method:: setJac(jac: collections.abc.Callable[[Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]], Annotated[numpy.typing.NDArray[numpy.float64], [m, n], flags.writeable, flags.c_contiguous]], None]) -> None

      Set the jacobian function. After setting the jacobian.function, you
      will need to re-create the solver if one has already been set.
      Otherwise, the solver will still retain the old cost function.
      :param jac: The jacobian function.



   .. py:method:: solve(x: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1], flags.writeable]) -> float

      Solve the nonlinear system.

      :param x: The initial guess.

      :returns: The norm squared of the final cost error.



   .. py:property:: status
      :type: LevenbergMarquardtStatus | HybridNonLinearSolverStatus



.. py:class:: Physical1DofSubhinge

   Bases: :py:obj:`PhysicalSubhinge_T_1_1`


   Base class for 1 degree of freedom physical subhinges

   See :ref:`subhinges_sec` section for more information on physical
   subhinges.


   .. py:method:: getGearRatio() -> float

      Return the gear ratio for the 1 dof subhinge
      :returns: the gear ratio value



   .. py:method:: getJointLimits() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the lower/upper pair of joint limit values for the 1 dof
      subhinge
      :returns: array with the lower and upper joint limit values



   .. py:method:: getUnitAxis() -> Annotated[numpy.typing.NDArray[numpy.float64], [3, 1]]

      Get the unit axis for the pin hinge.
      :returns: The unit axis for the pin hinge.



   .. py:method:: setGearRatio(arg0: SupportsFloat | SupportsIndex) -> None

      Set the gear ratio for the 1 dof subhinge
      :param gear_ratio: the gear ratio



   .. py:method:: setJointLimits(arg0: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> None

      Set the lower/upper pair of joint limit values for the 1 dof subhinge
      :param limits: the lower and upper limit values



   .. py:method:: setUnitAxis(arg0: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]]) -> None

      Set the unit axis for the pin hinge.
      :param axis: The unit axis for the pin hinge.



.. py:class:: PhysicalBody(name: str, mb: Multibody)

   Bases: :py:obj:`BodyBase`, :py:obj:`Karana.Frame.Frame`


   


   .. py:method:: addSerialChain(name: str, nbodies: SupportsInt | SupportsIndex, root: PhysicalBody, htype: HingeType = HingeType.REVOLUTE, params: PhysicalBodyParams = None) -> list[PhysicalBody]
      :staticmethod:


      Add a serial chain of rigid PhysicalBody instances to the multibody
      system

      Add a serial chain of rigid bodies to the multibody system to the
      specified root body with the specified mass properties, hinge type and
      hinge connection properties. This method is mainly used for
      procedurally generating large test systems. See
      :ref:`multibody_procedural_sec` section for more discussion on this
      topic.

      :param name: prefix string to use for the new body names
      :param nbodies: number of bodies
      :param root: the parent body to attach the chain to
      :param htype: the hinge type
      :param params: the body params for each body

      :returns: the list of new rigid bodies



   .. py:method:: addTree(name: str, branch_length: SupportsInt | SupportsIndex, nbranches: SupportsInt | SupportsIndex, depth: SupportsInt | SupportsIndex, root: PhysicalBody, htype: HingeType = HingeType.REVOLUTE, params: PhysicalBodyParams = None) -> list[PhysicalBody]
      :staticmethod:


      Add a sub-tree of rigid PhysicalBody instances to the multibody system

      Add a sub-tree of rigid bodies to the multibody system to the
      specified root body with the specified mass properties, hinge type and
      hinge connection properties. This method is mainly used for
      procedurally generating large test systems. See the
      :ref:`multibody_procedural_sec` section for more discussion on this
      topic.

      :param name: prefix string to use for the new body names
      :param branch_length: the number of bodies in a branch
      :param nbranches: the number of children branches
      :param depth: the number of branching levels to create
      :param root: the parent body to attach the chain to
      :param htype: the hinge type
      :param params: the body params for each body

      :returns: the list of new rigid bodies



   .. py:method:: create(name: str, mb: Multibody) -> PhysicalBody
      :staticmethod:


      Creates a new PhysicalBody with the given name.
      :param name: The name of the frame to create.
      :param mb: The Multibody instance.

      :returns: The created body.



   .. py:method:: __deepcopy__(arg0: Any) -> PhysicalBody


   .. py:method:: accumGravAccel(g: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]], ref_frame: Karana.Frame.Frame = None) -> None

      Accumulate the gravitational linear acceleration for the body
      represented in the specified frame.

      If no frame is specified, then the linear acceleration is assumed to
      be represented in the body frame

      :param g: the gravitational linear acceleration vector
      :param ref_frame: the representation frame for the input gravity accel
                        vector



   .. py:method:: accumGravityGradient(g: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]], ref_frame: Karana.Frame.Frame = None) -> None

      Accumulate the gravity gradient moment vector for the body represented
      in the specified frame.

      If no frame is specified, then the moment is assumed to be represented
      in the body frame

      :param grav_gradient: the gravity gradient vector
      :param ref_frame: the representation frame for the input gravity accel
                        vector



   .. py:method:: activeContactNodeList() -> list[Node]

      Return a list of the active contact nodes on this body.
      :returns: A list of active contact nodes on the body



   .. py:method:: addScenePartSpec(new_part_spec: Karana.Scene.ScenePartSpec) -> None

      Add a ScenePart description to the body to be realized whenever a
      ProxyScene is available.

      The new scene part spec's name must not conflict with the name of an
      existing scene part spec of scene part for the body.

      :param scene_part_spec: The ScenePart description



   .. py:method:: constraintNodeList() -> list[ConstraintNode]

      Get a list of the constraint nodes on this body.
      :returns: A list of constraint nodes on the body



   .. py:method:: detach() -> None

      Reattach the body to the virtual root via a 6 dof hinge.

      Reattach the body to the virtual root via a 6 dof hinge (while
      preserving the inertial pose, spatial velocity and spatial
      acceleration. See :ref:`mbody_config_changes_sec` section for
      information.



   .. py:method:: externalSpatialForce(arg0: bool) -> Karana.Math.SpatialVector

      Return the overall spatial force on the body at its reference frame
      and in the body frame

      This method will accumulate the external spatial forces from all the
      force nodes (including active contact nodes) on the body. If
      with_constraints is true, then constraint spatial forces from the
      constraint nodes will also be accumulated in the returned value.

      :param with_constraints: set to true to include constraint node
                               contributions

      :returns: the overall spatial force on the body, at the body reference frame
                in the body frame



   .. py:method:: getBodyToJointTransform() -> Karana.Math.HomTran

      Return the body frame to body HingePnode pnode transform.

      For a deformable body, this is the transform value in the undeformed
      configuration.

      :returns: the transform



   .. py:method:: getConstraintNode(arg0: str) -> ConstraintNode

      Retrieve the constraint node with the specified name.

      Return nullptr if there is no constraint node with the specified name.

      :param node_name: the node's name

      :returns: The constraint node on the body with the specified name.



   .. py:method:: getGravAccel() -> Annotated[numpy.typing.NDArray[numpy.float64], [3, 1]]

      Return the gravity linear acceleration at the body in the body frame
      :returns: the gravity acceleration vector



   .. py:method:: getNode(arg0: str) -> Node
                  getNode(node_name: str) -> Node

      Retrieve the node with the specified name.

      Return nullptr if there is no node with the specified name.

      :param node_name: the node's name

      :returns: The node on the body with the specified name.



   .. py:method:: getScenePart(arg0: str) -> Karana.Scene.ProxyScenePart

      Return the ScenePart with the specified name

      See :ref:`proxyscene_sec` section for proxy scene related discussion.

      :param nm: the name of the scene part

      :returns: The scene part with machine name, or nullptr if none found



   .. py:method:: getScenePartSpecs() -> list[Karana.Scene.ScenePartSpec]

      Return a list of copies of ScenePartSpecs. Do not modify these
      directly; use replaceScenePartSpec instead.

      See :ref:`proxyscene_sec` section for proxy scene related discussion.

      :returns: The list of scene part specs



   .. py:method:: getSceneParts() -> list[Karana.Scene.ProxyScenePart]

      Return a list of SceneParts created from Karana::Scene::ScenePartSpec
      values

      See :ref:`proxyscene_sec` section for proxy scene related discussion.

      :returns: The list of scene parts



   .. py:method:: getSpatialInertia() -> Karana.Math.SpatialInertia

      Return the body's Karana::Math::SpatialInertia spatial inertia about
      the body frame
      :returns: the spatial inertia



   .. py:method:: getVars() -> PhysicalBodyVars


   .. py:method:: kineticEnergy() -> float

      Return the kinetic energy contribution for the body
      :returns: the kinetic energy value



   .. py:method:: nodeList() -> list[Node]

      Get a list of the nodes on this body. This does not include pnodes or
      onodes.
      :returns: A list of nodes on the body, not including pnodes or onodes.



   .. py:method:: onode() -> HingeOnode

      Return the onode for the parent hinge

      See :ref:`body_hinge_sec` section for more on body pnodes and onodes.
      :returns: the HingeOnode instance



   .. py:method:: parentHinge() -> PhysicalHinge

      Return the parent hinge for the body.

      For a PhysicalBody, parent hinge is a PhysicalHinge, while for a
      CompoundBody the parent hinge is a CompoundHinge

      :returns: The parent HingeBase instance



   .. py:method:: pnode() -> HingePnode

      Return the pnode for the parent hinge

      See :ref:`body_hinge_sec` section for more on body pnodes and onodes.
      :returns: the HingePnode instance



   .. py:method:: reattach(new_parent: PhysicalBody, hinge_type: HingeType = HingeType.FULL6DOF) -> None

      Reattach the body to the specified parent PhysicalBody

      Reattach this PhysicalBody to the new parent PhysicalBody body via a
      hinge of the specified type. If the new hinge type is a 6-dof hinge,
      then the inertial pose, spatial velocity and spatial acceleration of
      the body are preserved after reattachment. For a non 6-dof hinge, no
      such pose preservation is done, and follow up steps to set the hinge
      parameters (e.g., axes) and initial state will be required.

      See :ref:`mbody_config_changes_sec` section for information.

      :param new_parent: The new parent body
      :param hinge_type: The new hinge type



   .. py:method:: relocateCutJoint(prev_cutjoint: LoopConstraintCutJoint) -> LoopConstraintCutJoint

      Replace an existing cut-joint loop constraint with one at this body

      This method can be used to change the choice of cut-joint in a graph
      topology system by replacing an existing cut-joint with a new one at
      this body. It is required that (a) the new cut-joint body be the
      ancestor of one, and only one of the bodies that are the attachments
      of the input cut-joint. This method will discard the input cut-joint,
      and replace the parent hinge of the new cut-joint body and replace it
      with an equivalent cut-joint constraint.

      :param prev_cutjoint: the cut-joint constraint to be replace

      :returns: the new cut-joint constraint



   .. py:method:: removeScenePartSpec(spec_name: str) -> None

      Remove a scene part description from the body *and* all associated
      scene parts in the ProxyScene, if one is available.

      Note that this will also remove the scene part from any existing
      client scenes. Specs are looked up by name;an exception will be thrown
      if no matching spec exists.

      :param name: The name of the spec to remove.



   .. py:method:: replaceScenePartSpec(new_part_spec: Karana.Scene.ScenePartSpec) -> None

      Replace a scene part spec by name

      This allows you to edit scene part specs before any scenes have been
      constructed

      :param new_part_spec: The new spec to use in place; its name will be
                            matched against the ones that already exist.

      :raises std::invalid_argument: If a scene part already exists with that
          name, or if no matching spec exists.



   .. py:method:: scaleStickParts(arg0: SupportsFloat | SupportsIndex) -> None

      Scale stick parts for the body.

      :param scaling: the scaling to apply



   .. py:method:: setBodyToJointTransform(T: Karana.Math.HomTran) -> None

      Set the the body frame to body HingePnode pnode transform.

      For a deformable body, this is the transform value in the undeformed
      configuration. This method should only be used for body pnodes. The
      Node::setBodyToNodeTransform() method should be used for all other
      nodes.

      :param T: The input transform



   .. py:method:: setGravAccel(g: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]], ref_frame: Karana.Frame.Frame = None) -> None

      Set the gravitational linear acceleration for the body represented in
      the specified frame.

      If no frame is specified, then the linear acceleration is assumed to
      be represented in the body frame, else the gravity vector is
      immediately rotated from the specified frame into the local body
      frame.

      :param g: the gravitational linear acceleration vector
      :param ref_frame: the representation frame for the input gravity accel
                        vector



   .. py:method:: setGravityGradient(g: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]], ref_frame: Karana.Frame.Frame = None) -> None

      Set the gravity gradient moment vector for the body represented in the
      specified frame.

      If no frame is specified, then the moment is assumed to be represented
      in the body frame

      :param grav_gradient: the gravity gradient vector
      :param ref_frame: the representation frame for the input gravity accel
                        vector



   .. py:method:: setParams(arg0: PhysicalBodyParams) -> None

      Set the PhysicalBody parameters
      :param params: the parameters to set



   .. py:method:: setSpatialInertia(spI: Karana.Math.SpatialInertia, ref_frame: Karana.Frame.Frame = None) -> None

      Set the Karana::Math::SpatialInertia spatial inertia for the body in
      the specified reference Karana::Frame::Frame frame

      If no frame is specified, then the spatial inertia is assumed to be
      represented in and about the body frame

      :param sp_i: the input spatial inertia
      :param ref_frame: the reference frame for the input spatial inertia



   .. py:method:: shiftBaseBody() -> None

      Convert this body into a floating base body.

      Given a body with parent PhysicalBody body that is a 6-dof floating
      base body, reverse the connecting parent hinge to make this body into
      a 6-dof floating base body. This operation maintains the required tree
      structure for the multibody system. The new hinge has the same
      subhinges as the original hinge - but in reversed order. The subhinge
      parameters preserve the original params while taking into account the
      orientation reversals. The end result is that the poses of the bodies
      remains unaffected. See the :ref:`mbody_config_changes_sec` for more
      on Multibody configuration changes.



   .. py:method:: spatialMomentum() -> Karana.Math.SpatialVector

      Return the spatial momentum contribution for the body
      :returns: the spatial momentum vector



   .. py:method:: toCutJointConstraint() -> LoopConstraintCutJoint

      Replace the parent hinge with an equivalent loop constraint

      The method removes the hinge between a parent/child body pair, and
      replaces it with an equivalent cut-joint LoopConstraintCutJoint
      between the bodies. The child body is attached to the virtual root via
      a 6 dof hinge. The parameters are set so that there is no change in
      the pose, velocities etc, and the new system is kinematically and
      dynamically equivalent - albeit one with redundant coordinates and
      constraints. See :ref:`FA_TA_models_sec` sec for discussion about the
      duality between PhysicalHinge and LoopConstraintCutJoint classes in
      Multibody representations.

      :returns: the new LoopConstraint instance



   .. py:method:: toDS() -> Karana.Dynamics.SOADyn_types.BodyDS

      Create a BodyDS from this PhysicalBody model.

      :returns: * *BodyDS*
                * *A BodyDS instance with values set to match this model.*



   .. py:method:: toStateDS() -> Karana.Dynamics.SOADyn_types.BodyStateDS

      Create a BodyStateDS from this PhysicalBody model.

      :returns: * *BodyStateDS*
                * *A BodyStateDS instance with values set to match this model.*



.. py:class:: PhysicalBodyParams(spI: Karana.Math.SpatialInertia = ..., axes: collections.abc.Sequence[Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]]] = ..., body_to_joint_transform: Karana.Math.HomTran = ..., inb_to_joint_transform: Karana.Math.HomTran = ..., scene_part_specs: collections.abc.Sequence[Karana.Scene.ScenePartSpec] = [])

   Struct with parameters for a PhysicalBody rigid physical body


   .. py:attribute:: body_to_joint_transform
      :type:  Karana.Math.HomTran


   .. py:attribute:: inb_to_joint_transform
      :type:  Karana.Math.HomTran


   .. py:attribute:: sp_i
      :type:  Karana.Math.SpatialInertia


   .. py:property:: axes
      :type: list[Annotated[numpy.typing.NDArray[numpy.float64], [3, 1]]]



   .. py:property:: scene_part_specs
      :type: list[Karana.Scene.ScenePartSpec]



.. py:class:: PhysicalBodyVars

   Bases: :py:obj:`Karana.Frame.FrameVars`


   


   .. py:property:: local_gravity_accel
      :type: Karana.Core.VarVec3


      The local frame gravitational acceleration


   .. py:property:: mass
      :type: Karana.Core.VarDouble


      The mass of the PhysicalBody.


   .. py:property:: physical_parent
      :type: Karana.Core.VarString


      The physical parent body name


.. py:class:: PhysicalHinge(parent: PhysicalBody, child: PhysicalBody, htype: HingeType, subhinge_types: collections.abc.Sequence[SubhingeType] = [])

   Bases: :py:obj:`FramePairHinge`


   


   .. py:method:: create(parent: PhysicalBody, child: PhysicalBody, htype: HingeType, subhinge_types: collections.abc.Sequence[SubhingeType] = []) -> PhysicalHinge
      :staticmethod:


      Factory method to create a PhysicalHinge instance.

      :param parent: The parent body
      :param child: The child body
      :param htype: The hinge type
      :param subhinge_types: The list of subhinge types for a custom hinge type

      :returns: A new PhysicalHinge instance



   .. py:method:: onode() -> HingeOnode

      Return the onode for the hinge See :ref:`body_hinge_sec` section for
      more information on onodes and pnodes.
      :returns: the HingeOnode instance



   .. py:method:: pnode() -> HingePnode

      Return the pnode for the hinge See :ref:`body_hinge_sec` section for
      more information on onodes and pnodes.
      :returns: the HingePnode instance



.. py:class:: PhysicalSubhinge

   Bases: :py:obj:`SubhingeBase`, :py:obj:`Karana.Frame.EdgeFrameToFrame`


   Represents the abstract base class for physical articulation subhinges

   This class is the base class for subhinges from which physical
   subhinge classes are derived. See :ref:`subhinges_sec` section for
   more information on physical subhinges.


   .. py:method:: __deepcopy__(arg0: Any) -> PhysicalSubhinge


   .. py:method:: getIndex() -> int

      Return the slot index for the subhinge in the parent hinge's list of
      subhinges

      :returns: the subhinge index



   .. py:method:: getVars() -> PhysicalSubhingeVars


   .. py:method:: parentHinge() -> FramePairHinge

      Return the parent hinge for the subhinge
      :returns: the PhysicalHinge parent hinge



.. py:class:: PhysicalSubhingeVars

   Bases: :py:obj:`Karana.Frame.FrameToFrameVars`


   The Vars for the PhysicalSubhinge class.


   .. py:property:: Q
      :type: Karana.Core.VarVec


      The Q coordinates


   .. py:property:: Qdot
      :type: Karana.Core.VarVec


      The Qdot coordinates


   .. py:property:: T
      :type: Karana.Core.VarVec


      The T coordinates


   .. py:property:: U
      :type: Karana.Core.VarVec


      The U coordinates


   .. py:property:: Udot
      :type: Karana.Core.VarVec


      The Udot coordinates


.. py:class:: PhysicalSubhinge_T_0_0

   Bases: :py:obj:`PhysicalSubhinge`


   Represents the abstract base class for physical articulation subhinges

   This class is the base class for subhinges from which physical
   subhinge classes are derived. See :ref:`subhinges_sec` section for
   more information on physical subhinges.


.. py:class:: PhysicalSubhinge_T_1_1

   Bases: :py:obj:`PhysicalSubhinge`


   Represents the abstract base class for physical articulation subhinges

   This class is the base class for subhinges from which physical
   subhinge classes are derived. See :ref:`subhinges_sec` section for
   more information on physical subhinges.


.. py:class:: PhysicalSubhinge_T_3_3

   Bases: :py:obj:`PhysicalSubhinge`


   Represents the abstract base class for physical articulation subhinges

   This class is the base class for subhinges from which physical
   subhinge classes are derived. See :ref:`subhinges_sec` section for
   more information on physical subhinges.


.. py:class:: PhysicalSubhinge_T_4_3

   Bases: :py:obj:`PhysicalSubhinge`


   Represents the abstract base class for physical articulation subhinges

   This class is the base class for subhinges from which physical
   subhinge classes are derived. See :ref:`subhinges_sec` section for
   more information on physical subhinges.


.. py:class:: PinSubhinge

   Bases: :py:obj:`Physical1DofSubhinge`


   


.. py:class:: PrePostCallbackRegistry

   .. py:attribute:: trace_callback_registry
      :type:  bool


   .. py:method:: __contains__(arg0: str) -> bool

      Check whether the given callback is contained within the registry.
      :param item: The name of the callback to check for.
      :type item: str

      :returns: True if the item is in the CallbackRegistry, False otherwise.
      :rtype: bool



   .. py:method:: __getitem__(key: str | SupportsInt | SupportsIndex) -> collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], None]

      Get a function by name



   .. py:method:: __len__() -> int

      Get the number of callbacks registered to the CallbackRegistry.

      :returns: Number of callbacks registered in the CallbackRegistry.
      :rtype: int



   .. py:method:: __setitem__(key: str | SupportsInt | SupportsIndex, func: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], None]) -> None

      Set a function with a string name or integer index



   .. py:method:: clear() -> None

      Clear out the entire CallbackRegistry. All callbacks will be removed.



   .. py:method:: dump(prefix: str = '') -> None

      Print out the string from `dumpString`. See `dumpString` for more details.



   .. py:method:: dumpString(prefix: str = '') -> str

      Create a string that lists all the functions by name.



   .. py:method:: erase(name: str, okay_not_exists: bool = False) -> None
                  erase(index: SupportsInt | SupportsIndex) -> None

      Erase the callback at the provided index.

      :param name: The index of the callback to erase.
      :type name: int



   .. py:method:: execute(arg0: SupportsFloat | SupportsIndex | numpy.timedelta64, arg1: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> None

      Execute all functions in the registry.



   .. py:method:: executeAndPopReverse(arg0: SupportsFloat | SupportsIndex | numpy.timedelta64, arg1: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> None

      Execute all functions in the registry in reverse and delete them as we go.



   .. py:method:: executeReverse(arg0: SupportsFloat | SupportsIndex | numpy.timedelta64, arg1: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> None

      Execute all functions in the registry in reverse.



   .. py:method:: insertAfter(item: str, name: str, fn: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], None]) -> None

      Insert a function after another in the registry.
      :param item: The name of the item to insert this new one after.
      :type item: str
      :param name: The name of the new item.
      :type name: str
      :param fn: The callback associated with the new item.
      :type fn: Callable



   .. py:method:: insertBefore(item: str, name: str, fn: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], None]) -> None

      Insert a function before another in the registry.
      :param item: The name of the item to insert this new one before.
      :type item: str
      :param name: The name of the new item.
      :type name: str
      :param fn: The callback associated with the new item.
      :type fn: Callable



   .. py:method:: pop(name: str) -> collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], None]
                  pop(index: SupportsInt | SupportsIndex) -> collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], None]

      Pop the callback at the provided index.

      :param name: The index of the callback to pop.
      :type name: int



   .. py:method:: size() -> int

      Get the number of callbacks registered to the CallbackRegistry.

      :returns: Number of callbacks registered in the CallbackRegistry.
      :rtype: int



.. py:class:: Scheduler

   The schedule class for the state propagator


   .. py:method:: executePostHopEvents(t: SupportsFloat | SupportsIndex | numpy.timedelta64) -> None

      Execute all the post-hop events for the provided time.
      :param t:
                - The time to execute all post-hop events for.



   .. py:method:: executePreHopEvents(t: SupportsFloat | SupportsIndex | numpy.timedelta64) -> None

      Execute all the pre-hop events for the provided time.
      :param t:
                - The time to execute all pre-hop events for.



   .. py:method:: getNextExplicitHopEndTime() -> numpy.timedelta64

      Get the next explicit hop end time.
      :returns: The next explicit hop end time.



   .. py:method:: hasRegisteredTimedEvent(name: str, pre_hop: bool) -> bool

      Determine whether a TimedEvent with the given name exists.

      :param name:
                   - The name of the TimedEvent.
      :param pre_hop:
                      - Whether this is a pre_hop timed event or not.

      :returns: true if a TimedEvent with the given name and pre_hop setting
                exists, false otherwise.



   .. py:method:: registerTimedEvent(timed_event: TimedEvent, curr_time: SupportsFloat | SupportsIndex | numpy.timedelta64) -> None

      Register a TimedEvent.
      :param timed_event:
                          - The TimedEvent to register.
      :param curr_time:
                        - The current time. Used for error checking.



   .. py:method:: unregisterTimedEvent(name: str, pre_hop: bool, okay_not_exists: bool) -> None

      Unregister a TimedEvent.
      :param name:
                   - The name of the TimedEvent.
      :param pre_hop:
                      - Whether this is a pre_hop timed event or not.
      :param okay_not_exists:
                              - If true, then do not error out if a timed event
                              by this name does not exist with the given
                              pre_hop setting, otherwise, error our if the
                              given event is not found.



.. py:class:: ScrewSubhinge

   Bases: :py:obj:`Physical1DofSubhinge`


   Represents a 1 dof helical subhinge with coupled rotation/translation
   about a common axis

   See :ref:`subhinges_sec` section for more information on physical
   subhinges.


   .. py:method:: getPitch() -> float

      Return the pitch value for the subhinge

      The pitch is defined as meters of translation/radian.

      :returns: the pitch value



   .. py:method:: setPitch(arg0: SupportsFloat | SupportsIndex) -> None

      Set the pitch value for the subhinge

      The pitch is defined as meters of translation/radian.

      :param pitch: the pitch value



.. py:class:: SolverType(*args, **kwds)

   Bases: :py:obj:`enum.Enum`


   Solver types used by the Nonlinear solver


   .. py:attribute:: HYBRID_NON_LINEAR_SOLVER
      :type:  ClassVar[SolverType]


   .. py:attribute:: LEVENBERG_MARQUARDT
      :type:  ClassVar[SolverType]


.. py:class:: SpOptions

   Bases: :py:obj:`MMOptionsModelManager`


   Options for the state propagator


   .. py:method:: create() -> SpOptions
      :staticmethod:


      Create an instance of SpOptions.

      :returns: A pointer to the newly created SpOptions.



   .. py:property:: max_step_size
      :type: numpy.timedelta64


      Define the step size that advanceTo() should use to break up the
      overall time advancement into sub-steps. This is especially useful for
      fixed-step integrators to ensure that integrator steps are not too
      large. Also for cases where external interactions and data logging
      needs to be done at fixed step intervals.


   .. py:property:: update_state_derivatives_hop_end
      :type: bool


      If true, then update the multibody state derivatives with the
      integrator states at the end of each hop.


.. py:class:: SpStatusEnum(*args, **kwds)

   Bases: :py:obj:`enum.Enum`


    Enum with values to classify the reason for the termination of a
   step


   .. py:attribute:: FAILED_STEP_VALIDATION
      :type:  ClassVar[SpStatusEnum]


   .. py:attribute:: REACHED_END_TIME
      :type:  ClassVar[SpStatusEnum]


   .. py:attribute:: REACHED_TERMINATION_CONDITION
      :type:  ClassVar[SpStatusEnum]


   .. py:attribute:: REACHED_ZERO_CROSSING
      :type:  ClassVar[SpStatusEnum]


   .. py:attribute:: UNKNOWN
      :type:  ClassVar[SpStatusEnum]


.. py:class:: SphericalQuatSubhinge

   Bases: :py:obj:`PhysicalSubhinge_T_4_3`


   Represents a 3 dof rotational subhinge using unit quaternion for
   generalized coords


   See :ref:`subhinges_sec` section for more information on physical
   subhinges.


.. py:class:: SphericalSubhinge

   Bases: :py:obj:`PhysicalSubhinge_T_3_3`


   Represents a 1 dof rotational subhinge using minimal RotationVector
   coords

   See :ref:`subhinges_sec` section for more information on physical
   subhinges.


   .. py:method:: getChartOffset() -> Karana.Math.UnitQuaternion

      Return the current offset for the RotationVector coordinates chart
      :returns: the chart offset UnitQuaternion



   .. py:method:: getMaxChartAngle() -> float

      Return the threshold for the RotationVector coordinates chart
      recentering

      Return the max allowed angle before the chart is recentered when
      sanitizeCoords() is called.

      :returns: the threshold value



   .. py:method:: resetChart() -> None


   .. py:method:: setMaxChartAngle(arg0: SupportsFloat | SupportsIndex) -> None

      Set the threshold for the RotationVector coordinates chart recentering

      Set the max allowed angle before the chart is recentered when
      sanitizeCoords() is called.

      :param val: the threshold value



.. py:class:: StatePropagator(st: SubTree, integrator_type: Karana.Integrators.IntegratorType = Karana.Math.IntegratorType.RK4, integ_opts: Karana.Integrators.IntegratorOptions | None = None, sp_opts: SpOptions | None = None, solver_type: MMSolverType = MMSolverType.UNDEFINED)

   Bases: :py:obj:`ModelManager`


   
    Class to integrate and propagate system state

    See :ref:`time_domain_sim_sec` section for more information on
   the StatePropagator class.


   .. py:method:: create(st: SubTree, integrator_type: Karana.Integrators.IntegratorType = Karana.Math.IntegratorType.RK4, integ_opts: Karana.Integrators.IntegratorOptions | None = None, sp_opts: SpOptions | None = None, solver_type: MMSolverType = MMSolverType.UNDEFINED) -> Karana.Dynamics.StatePropagator
      :staticmethod:


      Create an instance of the StatePropagator.

      If the solver type is not specified, the constructor will use
      TREE_DYNAMICS if the specified st argument is a pure subtree (and not
      SubGraph), or if is the multibody instance itself with no bilateral
      constraints. For all other st, an error will be raised - and a legal
      solver type must be explicitly specified since there is no good way to
      infer one.

      :param st: the SubTree instance
      :param integrator_type: the numerical integrator type
      :param integ_opts: options for the numerical integrator
      :param sp_opts: options for the state propagator
      :param solver_type: the solver type

      :returns: An instance of the StatePropagator.



   .. py:method:: __deepcopy__(arg0: Any) -> Karana.Dynamics.StatePropagator


   .. py:method:: advanceBy(delta_time: SupportsFloat | SupportsIndex | numpy.timedelta64) -> SpStatusEnum
                  advanceBy(delta_time: SupportsInt | SupportsIndex) -> SpStatusEnum

      Method to advance the system state by a time interval

      :param delta_time: the time to advance by

      :returns: advancement status value



   .. py:method:: advanceTo(to_time: SupportsFloat | SupportsIndex | numpy.timedelta64) -> SpStatusEnum

      Method to advance the system state to a new time in the future

      :param to_time: the desired future time

      :returns: advancement status value



   .. py:method:: counters() -> StatePropagatorCounters

      Return the Counters struct that tracks propagation statistics

      :returns: the Counters counters struct



   .. py:method:: getIntegrator() -> Karana.Integrators.Integrator

      Return the integrator instance

      See :ref:`integrator_sec` section for more information on numerical
      integrators.

      :returns: the Integrator instance



   .. py:method:: getMaxStepSize() -> numpy.timedelta64

      Get the step size that advanceTo() is using to break up the
             overall time advancement into sub-steps.

      This is especially useful for fixed-step integrators to ensure that
      integrator steps are not too large. Also for cases where external
      interactions and data logging needs to be done at fixed step
      intervals.

      :returns: The maximum step size that advanceTo will use.



   .. py:method:: getUpdateStateDerivativesHopEnd() -> bool

      Get the setting for updating the derivatives at hop end.

      If true, then update the multibody state derivatives with the
      integrator states at the end of each hop.

      :returns: The the setting for updating the derivatives at hop end.



   .. py:method:: getVars() -> StatePropagatorVars


   .. py:method:: hasRegisteredTimedEvent(name: str, pre_hop: bool) -> bool

      Determine whether a TimedEvent with the given name exists.

      :param name:
                   - The name of the TimedEvent.
      :param pre_hop:
                      - Whether this is a pre_hop timed event or not.

      :returns: true if a TimedEvent with the given name and pre_hop setting
                exists, false otherwise.



   .. py:method:: isPaused() -> bool

      Return whether the StatePropagator is paused or not.

      :returns: true if paused, false otherwise.



   .. py:method:: pause() -> None

      Pause the sim on the next hop.

      This will keep the thread running advanceTo spinning until resume is
      called.



   .. py:method:: registerTimedEvent(timed_event: TimedEvent) -> None

      Register a TimedEvent. See :ref:`timed_events_sec` section for more on
      using the TimedEvent class.

      :param timed_event: The TimedEvent to register.



   .. py:method:: resume() -> None

      Resume simulation advancing to the last requested advanceTo time.

      If the advance-to time was already reached, then this is a no-op.

      If the simulation was paused, then this will let the thread running
      advanceTo continue. If the simulation was stopped, then this will run
      the advanceTo and block until complete.



   .. py:method:: setIntegrator(integrator_type: Karana.Integrators.IntegratorType, integ_opts: Karana.Integrators.IntegratorOptions | None = None) -> None
                  setIntegrator(integrator: Karana.Integrators.Integrator) -> None

      Change to the specified integrator.

      If there was a previous integrator, the time and state values are
      transferred as well.

      See :ref:`integrator_sec` section for more information on numerical
      integrators.

      :param integrator: the new integrator



   .. py:method:: setMaxStepSize(max_step_size: SupportsFloat | SupportsIndex | numpy.timedelta64) -> None

      Set the step size that advanceTo() will use to break up the
             overall time advancement into sub-steps.

      See getMaxStepSize for more details.

      :param max_step_size: The maximum step size that advanceTo will use.



   .. py:method:: setUpdateStateDerivativesHopEnd(update_state_derivatives_hop_end: bool) -> None

      Set whether to update the derivatives at hop end or not.

      If true, then update the multibody state derivatives with the
      integrator states at the end of each hop.

      :param update_state_derivatives_hop_end: The setting for updating the
                                               derivatives at hop end.



   .. py:method:: stop() -> None

      Stop the simulation advancing to the last requested advanceTo time.

      If the advance-to time was already reached, then this is a no-op.



   .. py:method:: toDS() -> Karana.Dynamics.SOADyn_types.StatePropagatorDS

      Create a StatePropagatorDS from this StatePropagator model.

      :returns: * *StatePropagatorDS*
                * *A StatePropagatorDS instance with values set to match this model.*



   .. py:method:: unregisterTimedEvent(name: str, pre_hop: bool, okay_not_exists: bool) -> None

      Unregister a TimedEvent. See :ref:`timed_events_sec` section for more
      on using the TimedEvent class.
      :param name:
                   - The name of the timed event to remove.
      :param pre_hop:
                      - Whether the event to remove is a pre_hop or post_hop
                      timed event.
      :param okay_not_exists:
                              - If true, then do not error out if a timed event
                              by this name does not exist with the given
                              pre_hop setting, otherwise, error our if the
                              given event is not found.



.. py:class:: StatePropagatorCounters

   .. py:property:: derivs
      :type: int


      the number of deriv calls


   .. py:property:: hops
      :type: int


      the number of hops taken


   .. py:property:: integration_steps
      :type: int


      the number of integration steps taken


   .. py:property:: zero_crossings
      :type: int


      the number of zero crossings detected


.. py:class:: StatePropagatorVars

   Bases: :py:obj:`ModelManagerVars`


   The Vars for the StatePropagator class.


   .. py:property:: advance_to_time
      :type: Karana.Core.VarDouble


      the advance to time


   .. py:property:: counter_derivs
      :type: Karana.Core.VarInt


      number of derivative calls


   .. py:property:: counter_hops
      :type: Karana.Core.VarInt


      number of hops


   .. py:property:: counter_steps
      :type: Karana.Core.VarInt


      number of integration steps


   .. py:property:: counter_zero_crossings
      :type: Karana.Core.VarInt


      number of zero crossings


   .. py:property:: integrator_type
      :type: Karana.Core.VarString


      integrator type


.. py:class:: StickPartsConfig

   .. py:attribute:: body_to_constraint_node_color
      :type:  Karana.Scene.Color


   .. py:method:: __repr__() -> str


   .. py:property:: body_stick_radius
      :type: float


      Radius for the body stick part cylinder


   .. py:property:: body_to_onode_color
      :type: Karana.Scene.Color


      Body to pnode color


   .. py:property:: body_to_pnode_color
      :type: Karana.Scene.Color


      Body to pnode color


   .. py:property:: constraint_hinge_color
      :type: Karana.Scene.Color


      Constraint hinge color


   .. py:property:: constraint_node_color
      :type: Karana.Scene.Color


      Constraint node color


   .. py:property:: force_node_color
      :type: Karana.Scene.Color


      Force node color


   .. py:property:: hinge_axes_length
      :type: float


      Length of the pin subhinge axes


   .. py:property:: joint_color
      :type: Karana.Scene.Color


      Subhinge axis color


   .. py:property:: layers
      :type: int


      the scene layer type


   .. py:property:: node_radius
      :type: float


      Node sphere stick part radius


   .. py:property:: onode_color
      :type: Karana.Scene.Color


      onode color


   .. py:property:: pin_hinge_length
      :type: float


      Length of the pin subhinge axis cylinder


   .. py:property:: pin_hinge_radius
      :type: float


      Radius of the pin subhinge axis cylinder


   .. py:property:: sensor_node_color
      :type: Karana.Scene.Color


      Non-force node color


   .. py:property:: skip_body_frame
      :type: bool


      if true, do not include or use the body frame for the stick parts
      (work with nodes directly)


   .. py:property:: sphere_hinge_radius
      :type: float


      Radius of the spherical  subhinge axis cylinder


.. py:class:: SubGraph(name: str, parent_sg: SubGraph, new_root: BodyBase, use_branches: collections.abc.Sequence[BodyBase] = [], stop_at: collections.abc.Sequence[BodyBase] = [], inherit_constraints: bool = True)

   Bases: :py:obj:`SubTree`


   Represents a subtree of bodies with motion constraints

   This class is a container for a sub-tree of bodies with possible
   motion constraints on them.

   See the :ref:`physical_bodies_sec`, :ref:`treembody_sec`, and
   :ref:`subgraphs_sec` sections for more discussion related to the
   SubGraph class.


   .. py:method:: create(name: str, parent_sg: SubGraph, new_root: BodyBase, use_branches: collections.abc.Sequence[BodyBase] = [], stop_at: collections.abc.Sequence[BodyBase] = [], inherit_constraints: bool = True) -> SubGraph
      :staticmethod:


      Factory method to create a new SubGraph instance. See the SubTree
      documentation for more information on the bodies that are included in
      the sub-graph.

      If the inherit_constraints option is true then all relevant
      constraints from the parent SubGraph are added to this SubGraph in one
      swoop.

      :param name: The name for the new SubGraph
      :param parent_sg: The parent SubGraph for the new SubGraph
      :param new_root: The virtual root body for the new SubGraph
      :param use_branches: The list of bodies that define branches whose bodies
                           to include
      :param stop_at: The list of bodies whose descendants should not be
                      included
      :param inherit_constraints: if true, add relevant constraints from parent
                                  to this subgraph

      :returns: A new SubGraph instance



   .. py:method:: accelError() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

       Return the overall constraint spatial acceleration error for the
       enabled loop
      constraints

       @return the spatial acceleration error



   .. py:method:: aggregationSubGraph(arg0: str, arg1: collections.abc.Sequence[BilateralConstraintBase], arg2: bool) -> SubGraph

      Create and return an aggregation SubGraph for the list of constraints

      For a set of bilateral constraints, the aggregation sub-graph is the
      smallest sub-graph that contains their constrained bodies, and is
      "path-induced" for the underlying sub-graph. A path-induced sub-graph
      includes all the bodies from the parent sub-graph that are connected
      to each other via hinges and bilateral constraints (and form a sub-
      tree if the constraints are ignored). If with_velocity_constraints is
      true (usually recommended), the velocity level non-hinge convel
      constraints are also considered when identifying the aggregation
      SubGraph. Aggregation SubGraphs are used for multibody system
      constraint-embedding.

      :param name: The name for the new SubGraph
      :param constraints: The input list of constraints
      :param with_velocity_constraints: If true, also use the non-hinge convel
                                        constraints when identifying the
                                        aggregation SubGraph

      :returns: the aggregation SubGraph



   .. py:method:: articulateSubhinge(shg: SubhingeBase, subhinge_index: SupportsInt | SupportsIndex, disable_ik: bool = False, rangeQ: SupportsFloat | SupportsIndex = 0.5, dQ: SupportsFloat | SupportsIndex = 0.01, pause: SupportsFloat | SupportsIndex = 0.01) -> None

      Sequentially articulate a regular or loop constraint subhinge for a
      physical body.

      With graphics on, this step can be used to examine and debug issues
      with the model. If there are enabled loop constraints, this method
      will invoke the constraint kinematics solver each step to enforce the
      loop constraints.

      :param shg: subhinge to articulate
      :param subhinge_index: the index of the coordinate element to articulate
      :param disable_ik: if true, constraints solver is not invoked during
                         articulation
      :param range_q: is the excursion angle range (in radians)
      :param d_q: is the angle step size (in radians)
      :param pause: time in seconds to sleep between articulation steps



   .. py:method:: cks() -> ConstraintKinematicsSolver

      Return the constraint kinematics solver for the registered constraints

      See the :ref:`constraint_kinematics_sec` section for more on the
      ConstraintKinematicsSolver class.

      :returns: the ConstraintKinematicsSolver instance



   .. py:method:: clone(name: str) -> SubGraph

      This method returns a clone of the SubGraph as child subgraph.

      :param name: The name for the new SubGraph

      :returns: A new SubGraph instance



   .. py:method:: constraintErrorAt(arg0: SupportsInt | SupportsIndex) -> tuple[Karana.Core.LockingBase, int]

      Return the constraint obj and its local offset in the overall
      constraint error vector

      The constraint errors are organized as 6 elements for each cutjoint-
      loop constraint, followed by scalar entries for the non-cutjoint loop
      constraints, and then scalars for each of the coordinate constraints.
      Given an index value, this method returns the corresponding constraint
      and its local offset in this vector.

      Not that this is also the organization of the rows in the matrices
      returned by the Algorithms::evalVelocityConstraintMatrix(True) method
      and the vector returned by the SubGraph::velError() method.

      The related constraintResidualAt() method returns the constraint based
      on the packing order for constraint errors.

      :param row_offset: the overall row offset value @return The

      :returns: corresponding constraint instance and its local offset



   .. py:method:: constraintResidualAt(arg0: SupportsInt | SupportsIndex) -> tuple[Karana.Core.LockingBase, int]

      Return the constraint obj and its local offset in the overall
      constraint residuals vector

      The constraint residuals are organized as the residual elements for
      each cutjoint-loop constraint (6-constraint.hinge().nU() size),
      followed by scalar entries for the convel loop constraints, and then
      scalars for each of the coordinate constraints. Given an index value,
      this method returns the corresponding constraint and its local offset
      in this vector.

      This method returns the constraint and its local offset for the
      specified overall row offset value in the matrix returned by the
      Algorithms::evalVelocityConstraintMatrix(False) method.

      The related constraintErrorAt() method returns the constraint based on
      the packing order for constraint errors.

      :param row_offset: the input overall row offset value

      :returns: corresponding constraint instance and its local offset



   .. py:method:: constraintsGc() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]

      Compute the Gc overall constraint matrix  for the loop constraints
      (WIP)

      The Gc constraint matrix defines the overall velocity level
      constraints for the generalized velocity coordinates based on the loop
      closure constraints. Thus Gc*U=0 when the velocity constraints are
      satisfied. Gc itself is Q * Jacobian.

      The column space of Gc^* defines the squeeze forces, i.e (Gc^* x Y)
      generalized forces cause no motion for arbitrary Y.

      :returns: The velocity constraint Gc matrix



   .. py:method:: cutjointCoordData() -> CoordData

      Return the CoordData for the cut-joint loop constraint subhinges See
      :ref:`coord_data_sec` section for more on the CoordData class.
      :returns: the cut-joint constraints CoordData instance



   .. py:method:: disableConstraint(arg0: BilateralConstraintBase) -> None

      Disable a constraint for the SubGraph

      Remove this constraint from the enabled constraints list for this
      SubGraph. See :ref:`constraints_sec` section for more info on
      enabling/disabling constraints.

      :param constraint: the constraint



   .. py:method:: enableConstraint(arg0: BilateralConstraintBase) -> None

      Enable a constraint for the SubGraph

      If not already, add this loop constraint to the enabled list for use
      in constraint kinematics, and TA dynamics etc algorithms. See
      :ref:`constraints_sec` section for more info on enabling/disabling
      loop constraints.

      :param constraint: the new constraint



   .. py:method:: enabledConstraints(type: BilateralConstraintType = BilateralConstraintType.ALL) -> list[BilateralConstraintBase]

      Return the list of enabled  constraints for the SubGraph

      This returns the list of  constraints that are currently "active" for
      this SubGraph. See :ref:`constraints_sec` section for more info on
      enabling/disabling  constraints.

      :param type: the type of constraint to include in the returned list

      :returns: the list of enabled  constraints



   .. py:method:: flattenCompoundBodies() -> None

      Flatten all the compound bodies to remove nested ones



   .. py:method:: getBodyCoordinateConstraints(arg0: PhysicalBody) -> list[CoordinateConstraint]

      Return coordinate constraints connected to a body. See
      :ref:`constraints_sec` section for more info on constraints.

      :param body: the body instance

      :returns: the list of coordinate constraints involving the body



   .. py:method:: getBodyLoopConstraints(arg0: PhysicalBody) -> list[LoopConstraintBase]

      Return loop constraints connected to a body. See
      :ref:`constraints_sec` section for more info on constraints.

      :param body: the body instance

      :returns: the list of loop constraints involving the body



   .. py:method:: getEnabledConstraint(arg0: str) -> BilateralConstraintBase

      Look up an enabled constraint by name. See :ref:`constraints_sec`
      section for more info on loop constraints.
      :param name: the constraint's name

      :returns: the constraint instance, or null if there is no enabled constraint
                with the specified name



   .. py:method:: getLoopConstraintBodies(arg0: LoopConstraintBase) -> list[PhysicalBody]

      Return PhysicalBody instances involved in a loop for a loop constraint

      The Karana::Frame::Frame pair associated with a loop constraint define
      a pair of bodies whose relative motion is constrained. All
      PhysicalBody instances belonging to the minimal spanning tree
      containing this pair of bodies is effected by the loop constraint, and
      are included in the list of bodies returned by this method.  See the
      :ref:`constraints_sec` section for more info on loop constraints.

      :param c: the constraint instance

      :returns: the list of bodies in the loop



   .. py:method:: getVars() -> SubGraphVars


   .. py:method:: graphCoordData() -> CoordData

      Return the subhinge+body+constraints CoordData for the SubGraph

      This CoordData is a combination of the subhinge, body and constraint
      CoordDatas

      See :ref:`coord_data_sec` for more on the CoordData class.
      :returns: the CoordData for the SubGraph



   .. py:method:: nLoopConstraintResiduals() -> int

      Return the size of the residuals vector for loop constraints

      This returns the combined length of the residuals for the hinge and
      convel loop constraints. See :ref:`coordinate_constraints_sec` section
      for more info on enabling/disabling coordinate constraints.

      :returns: the size of the residuals vector



   .. py:method:: poseError() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the overall constraints pose error vector for the enabled
      constraints
      :returns: the pose error vector



   .. py:method:: setupConstraintEmbedding() -> None

      Create CECompoundBody instances for all enabled constraints

      Cycle through all of the enabled constraints, and create aggregation
      subgraphs for each and use it to create a CECompoundBody that embeds
      the constraint. On completion, the subgraph will be a pure tree, with
      all constraints having been embedded in a CECompound body. Depending
      on the topology, some of the compound bodies will be nested.



   .. py:method:: velError() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the overall constraint spatial velocity error for the enabled
      constraints

      :returns: the spatial velocity error



   .. py:method:: kinematicsAnalysis()

      Carry out kinematics analysis of the sub-graph with constraints.



   .. py:method:: showBodiesGraph(*, name_to_label_map: dict[str, str] | None = None, buttons: list[Karana.KUtils.visjs.Button] | None = None, extra_edges: dict[str, list[Karana.KUtils.visjs.Edge]] | list[Karana.KUtils.visjs.Edge] | None = None, port: int = 8765, title: str = 'Multibody System', launch_client=False) -> Karana.KUtils.visjs.MultibodyGraphServer

      Display the sub-graph bodies and constraints as a nodes graph.

      :param self: The sub-graph whose bodies to display
      :type self: SubGraph
      :param node_id_to_label_map: Dictionary defining the labels to use for each body in the graph
                                   display
      :type node_id_to_label_map: dict[str, str] | None
      :param buttons: Extra buttons to display with server-side callbacks on press
      :type buttons: list[Button] | None
      :param extra_edges: Extra edges to add to the graph. The key will be an identifier,
                          and the value will be a color, and a list of edges
      :type extra_edges: dict[str, dict[str, dict]] | None
      :param port: Port to bind to - defaults to 8765.
      :type port: int
      :param title: Title of the graph
      :type title: str
      :param launch_client: Automatically open the frontend in a local browser tab.
                            Defaults to False.
      :type launch_client: bool

      :returns: Handle to the server hosting the graph visualization
      :rtype: MultibodyGraphServer



.. py:class:: SubGraphVars

   Bases: :py:obj:`SubTreeVars`


   The Vars for the SubGraph class.


   .. py:property:: cutjoints_n_Q
      :type: Karana.Core.VarInt


      The cutjoints nQ


   .. py:property:: cutjoints_n_U
      :type: Karana.Core.VarInt


      The cutjoints nU


.. py:class:: SubTree(name: str, parent_subtree: SubTree, new_root: BodyBase, use_branches: collections.abc.Sequence[BodyBase] = [], stop_at: collections.abc.Sequence[BodyBase] = [])

   Bases: :py:obj:`Karana.Core.LockingBase`


   Represents a SubTree with connected bodies

   This class is for a sub-tree of connected bodies

   See the :ref:`physical_bodies_sec`, :ref:`treembody_sec`, and
   :ref:`subtrees_sec` sections for more discussion related to the
   SubTree class.


   .. py:attribute:: enable_dump_dynamics
      :type:  bool


   .. py:method:: create(name: str, parent_subtree: SubTree, new_root: BodyBase, use_branches: collections.abc.Sequence[BodyBase] = [], stop_at: collections.abc.Sequence[BodyBase] = []) -> SubTree
      :staticmethod:


      Factory method to create a new SubTree instance

      Create a new SubTree from the bodies in this SubTree starting at the
      new_root body, and with branches limited to the ones containing the
      bodies in the use_bodies list, and excluding bodies that are
      downstream of the bodies in the stop_at list. If use_branches is
      empty, all descendant branches are used. If the stop_at list is empty,
      then all bodies in the valid branches are included.

      :param parent_subtree: The parent SubTree for the new SubTree
      :param name: The name for the new SubTree
      :param new_root: The virtual root body for the new SubTree
      :param use_branches: The branches to get bodies from
      :param stop_at: list of last bodies on a branch

      :returns: A new SubTree instance



   .. py:method:: accumUniformGravAccel(g: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]], ref_frame: Karana.Frame.Frame = None) -> None

      Accumulate the uniform gravity accel value for all the physical bodies
      in the SubTree

      The input value is in the specified reference frame. If no reference
      frame is provided, then the newtonian root frame is assumed to be the
      reference frame.

      :param g: the gravity accel vector
      :param ref_frame: the reference frame



   .. py:method:: ancestorBody(bd: BodyBase, bd1: BodyBase) -> BodyBase

      Return the common ancestor body for the pair of BodyBase bodies in
      this SubTree

      :param bd: the first body
      :param bd1: the other body

      :returns: the common ancestor BodyBase body



   .. py:method:: articulateBodies(rangeQ: SupportsFloat | SupportsIndex = 0.5, dQ: SupportsFloat | SupportsIndex = 0.01, pause: SupportsFloat | SupportsIndex = 0.01) -> None

      Sequentially articulate all the 1 dof subhinges for the physical
      bodies.

      With graphics on, this step can be used to examine and debug any
      issues with the model.

      :param range_q: is the excursion angle range (in radians)
      :param d_q: is the angle step size (in radians)
      :param pause: time in seconds to sleep between articulation steps



   .. py:method:: articulateSubhinge(shg: SubhingeBase, subhinge_index: SupportsInt | SupportsIndex, rangeQ: SupportsFloat | SupportsIndex = 0.5, dQ: SupportsFloat | SupportsIndex = 0.01, pause: SupportsFloat | SupportsIndex = 0.01, cb: collections.abc.Callable[[], None] = None) -> None

      Sequentially articulate a subhinge for a physical body.

      With graphics on, this step can be used to examine and debug issues
      with the model.

      :param shg: subhinge to articulate
      :param subhinge_index: the index of the coordinate element to articulate
      :param range_q: is the excursion angle range (in radians)
      :param d_q: is the angle step size (in radians)
      :param pause: time in seconds to sleep between articulation steps
      :param cb: callback to invoke every time the Q coordinate is changed



   .. py:method:: baseBodies() -> list[BodyBase]

      Return the list of BodyBase base bodies for the SubTree

      Base bodies are the immediate children of the SubTree's virtual root
      body.

      :returns: the list of BodyBase base bodies



   .. py:method:: bodyCoordData() -> CoordData

      Return the CoordData for the body deformation coords See
      :ref:`coord_data_sec` for more on the CoordData class.

      :returns: the CoordData for the body deformation coords



   .. py:method:: childrenBodies(body: BodyBase) -> list[BodyBase]

      Return the list of BodyBase child bodies for a body for this subtree.

      The list may include physical and compound bodies.

      :param bd: the input body

      :returns: list of BodyBase children bodies



   .. py:method:: childrenSubTrees() -> list[SubTree]

      Return list of children subtrees

      :returns: the list of children subtrees



   .. py:method:: cmFrame() -> Karana.Frame.Frame

      Return the SubTree's center of mass (CM) Karana::Frame::Frame instance

      :returns: the CM frame Frame instance



   .. py:method:: containsBody(bd: BodyBase) -> bool

      Return true if the specified BodyBase body belongs to the SubTree or
      to any of its nested hierarchy of SubTrees

      :param bd: the input body

      :returns: true if the body belongs to the SubTree



   .. py:method:: coordAt(arg0: SupportsInt | SupportsIndex) -> tuple[CoordBase, int]
                  coordAt(arg0: SupportsInt | SupportsIndex) -> tuple[CoordBase, int]

      Returns coord obj and its coord offset corresponding to overall U
      offset

      A SubTree has multiple CoordData which are packed and unpacked the
      coordinate values for its set of CoordBase instances. This method
      returns the CoordBase and its local coordinate offset corresponding to
      the specified overall U offset value.  This method returns the
      CoordBase and its local offset for the specified overall column offset
      value in the matrix returned by the
      Algorithms::evalVelocityConstraintMatrix() method, or the
      vector returned by the SubTree::getU() method.

      :param u_offset: the input overall U offset value

      :returns: The CoordBase instance and its local U coord offset



   .. py:method:: coordOffsets(arg0: CoordBase) -> CoordDataCoordOffset

      Returns the packing offset for the specified CoordBase

      The SubTree has get/set methods to pack and unpack the coordinate
      values for its set of CoordBase and CoordData instances. This method
      returns the offsets for the Q and U values for the specified CoordBase
      in these combined arrays.

      :param c: The CoordBase to check for

      :returns: A CoordOffset struct with the Q and U offsets



   .. py:method:: createStickParts(stick_parts_config: Karana.Dynamics.StickPartsConfig = ...) -> None

      Create stick parts for the multibody.

      A Karana::Scene::ProxyScene scene must be registered with the
      Multibody first.

      :param c: Config that controls the look of the stick parts visualization.



   .. py:method:: disableAlgorithmicUse() -> None

      Disable the running of dynamics algorithms for the SubTree

      This methods unsets this SubTree from algorithmic use if it has not
      been unset already. See the :ref:`algorithms_sec` section for more on
      the available SubTree level computational algorithms.



   .. py:method:: displayModel(prefix: str = '') -> None

      Display information about the SubTree and its bodies

      :param prefix: the prefix for each line in the output



   .. py:method:: dumpDynamics(prefix: str = '') -> None

      Dump the details of the tree forward dynamics computations

      This is a debugging function that prints out the full state, the
      generalized forces, the external and constraint forces, and the
      gravity acceleration involved in the computation of the state
      derivative.  This method will be called with each call to
      Algorithms::evalForwardDynamics if the enable_dump_dynamics public
      member flag has been set to `true`. The flag can be set to `false` to
      disable the dump calls.

      :param prefix: the prefix for each line in the output



   .. py:method:: dumpTree(prefix: str = '', options: SubTreeDumpTreeOptions = ...) -> None

       Display the body tree. The contents of the options struct can be
      used to control the content and verbosity of the displayed output.
       @param prefix the prefix for each line in the output
      :param options: Options to tailor the output of dumpTree



   .. py:method:: enableAlgorithmicUse() -> None

      Enable the running of dynamics algorithms for the SubTree

      This methods sets up this SubTree for algorithmic use if it has not
      been setup as such already. Note, that algorithmic use is permissible
      only if this SubTree is disjoint from all other algorithmic SubTrees
      (i.e. the physical bodies are not shared).  See the
      :ref:`algorithms_sec` section for more on the available SubTree level
      computational algorithms.



   .. py:method:: filteredBodies(body: BodyBase = None, use_branches: collections.abc.Sequence[BodyBase] = [], stop_at: collections.abc.Sequence[BodyBase] = []) -> list[BodyBase]

      Return a list of BodyBase bodies for the SubTree based on the filter
      criteria

      Return a filtered list of bodies in a spanning tree anchored at the
      specified root body, and branches including the ones containing the
      bodies in the use_bodies list, and excluding bodies that are
      downstream of the bodies in the stop_at list. If no root is specified,
      then the SubTree's virtual root is used. If use_branches is empty, all
      descendant branches are used. If the stop_at list is empty, then all
      bodies in the valid branches are included. The returned list does not
      include the root body itself.

      :param root: The start body for the spanning tree
      :param use_branches: The branches to get bodies from
      :param stop_at: list of last bodies on a branch

      :returns: the filtered list of BodyBase bodies



   .. py:method:: getBodies(name: str) -> list[BodyBase]

      Look up BodyBase bodies directly in the SubTree with the specified
      name.

      :param name: the body name

      :returns: the list of BodyBase body instances



   .. py:method:: getBody(name: str) -> BodyBase

      Look up by name a BodyBase body directly in the SubTree.

      This method will throw an error if there are multiple bodies with the
      same specified name. This method will return a nullptr if there is no
      body with the matching name.

      :param name: the body's name

      :returns: the BodyBase body instance



   .. py:method:: getContainingCompoundBody(bd: BodyBase) -> CompoundBody

      Look up the containing compound body for a body contained by the
      subtree

      A body contained in a SubTree, may be a direct child, or be embedded
      at some level in a compound body in the subtree. This method will
      return the direct child compound body that contains the input body at
      some level in its nested hierarchy of embedded bodies. This method
      will return nullptr if the input body is not contained in the subtree.

      :param bd: the input body

      :returns: the CompoundBody instance containing the body



   .. py:method:: getQ() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the Q coordinates as an array

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :returns: Array of values



   .. py:method:: getT() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the T generalized forces as an array

      :returns: Array of values



   .. py:method:: getU() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the U velocity coordinates as an array

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :returns: Array of values



   .. py:method:: getUdot() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the Udot acceleration coordinates as an array

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :returns: Array of values



   .. py:method:: getVars() -> SubTreeVars


   .. py:method:: hasBody(bd: BodyBase) -> bool

      Return true if the specified BodyBase body directly belongs to the
      SubTree

      This method will return false if the input body is embedded within one
      its bodies.

      :param bd: the input body

      :returns: true if the body belongs to the SubTree



   .. py:method:: hasCompoundBodies() -> bool

      Return true if the SubTree contains any CompoundBody instances

      :returns: true if the SubTree has compound bodies



   .. py:method:: hasNestedCompoundBodies() -> bool

      Return true if the SubTree contains nested CompoundBodies

      :returns: true if the SubTree has nested compound bodies



   .. py:method:: isBaseBody(body: BodyBase) -> bool

      Return true if the BodyBase body is a base body for this sub-tree

      :param bd: the input body

      :returns: true, if the body is a base body in the SubTree



   .. py:method:: leafBodies() -> list[BodyBase]

      Return the list of BodyBase leaf bodies for the SubTree

      Leaf bodies are the bodies with children in the SubTree

      :returns: the list of leaf BodyBase bodies



   .. py:method:: multibody() -> Multibody

      Return the parent Multibody instance

      :returns: the Multibody instance



   .. py:method:: nQ() -> int

      The number of Q generalized coords for the CoordBase in the SubTree.

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :returns: the number of coordinates



   .. py:method:: nU() -> int

      The number of U velocity coords for the CoordBase.

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :returns: the number of velocity coordinates



   .. py:method:: numBodies() -> int

      Return the number of bodies in the tree

      :returns: the number of bodies



   .. py:method:: parentBody(body: BodyBase) -> BodyBase

      Return the specified body's BodyBase parent body in this SubTree

      Since a SubTree can have physical and compound bodies, the returned
      parent body can be a physical or a compound body.

      :param body: the specified body

      :returns: the parent body



   .. py:method:: parentSubTree() -> SubTree

      Return the parent SubTree for this subtree

      Return null if this subtree is the multibody instance

      :returns: the parent subtree



   .. py:method:: resetData() -> None

      Clear out the external spatial forces, gravity accel and gravity
      gradient values for all bodies, and all generalized coord, velocities,
      accels and forces. This is a helper method to initialize the SubTree
      to a zero state.

      This method should be used with caution. By initializing setting all
      coordinates etc to 0 values, it renders the isReady() method
      ineffective for detecting not ready state and other values.



   .. py:method:: scaleStickParts(arg0: SupportsFloat | SupportsIndex) -> None

      Scale stick parts for the subtree.

      :param scaling: the scaling to apply



   .. py:method:: setQ(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setQ(val: SupportsFloat | SupportsIndex) -> None

      Set the Q coordinates to a constant value

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :param fill_value: Fill value.



   .. py:method:: setT(arg0: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setT(arg0: SupportsFloat | SupportsIndex) -> None

      Set the U velocity coordinates to a constant value

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :param fill_value: Fill value.



   .. py:method:: setU(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setU(val: SupportsFloat | SupportsIndex) -> None

      Set the U velocity coordinates to a constant value

      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :param fill_value: Fill value.



   .. py:method:: setUdot(vals: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> None
                  setUdot(val: SupportsFloat | SupportsIndex) -> None

      Set the Udot acceleration coordinates to a constant value


      See :ref:`coords_sec` section for more on Q, U etc generalized
      coordinates.

      :param fill_value: Fill value.



   .. py:method:: setUniformGravAccel(g: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]], ref_frame: Karana.Frame.Frame = None) -> None

      Set the uniform gravity accel value for all the physical bodies in the
      SubTree

      The input value is in the specified reference frame. If no reference
      frame is provided, then the newtonian root frame is assumed to be the
      reference frame. This method can only be called on a SubTree that is
      healthy.

      :param g: the gravity accel vector
      :param ref_frame: the Frame reference frame



   .. py:method:: showState(arg0: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> None

      Display a breakdown of the elements of the state vector into its
      component elements.

      The state vector is typically associated with the StatePropagator
      state. See :ref:`system_state_sec` section for more on the state
      vector, and the :ref:`state_propagator_sec` for the StatePropagator
      class.

      :param x: The state vector



   .. py:method:: sortedBodiesList() -> list[BodyBase]

      Compute and return the sorted list of bodies in the tree. This will be
      a mix of PhysicalBody and CompoundBody instances.
      :returns: A vector containing the bodies of the SubTree.



   .. py:method:: sortedPhysicalBodiesList() -> list[PhysicalBody]

      Compute and return the topologically sorted list of PhysicalBody
      instances in the tree

      The list includes all physical bodies, even those embedded within
      CompoundBody bodies in the SubTree.

      :returns: the list of PhysicalBody instances



   .. py:method:: subhingeCoordData() -> CoordData

      Return the CoordData for the subhinges See :ref:`coord_data_sec` for
      more on the CoordData class.
      :returns: the CoordData for the subhinges



   .. py:method:: treeCoordData() -> CoordData

      Return the subhinge+body tree CoordData for the SubTree

      This CoordData is a combination of the subhinge and body CoordDatas

      See :ref:`coord_data_sec` for more on the CoordData class.
      :returns: the CoordData for the tree



   .. py:method:: virtualRoot() -> BodyBase

      Returns the virtual root BodyBase body for the tree.
      :returns: The virtual root body.



.. py:class:: SubTreeDumpTreeOptions(hinge_type: bool = True, lock_Status: bool = False, ref_count: bool = False, hinge_ref_count: bool = False, id: bool = False)

   .. py:attribute:: healthy_status
      :type:  bool


   .. py:attribute:: hinge_ref_count
      :type:  bool


   .. py:attribute:: hinge_type
      :type:  bool


   .. py:attribute:: id
      :type:  bool


   .. py:attribute:: ref_count
      :type:  bool


   .. py:method:: __repr__() -> str


.. py:class:: SubTreeVars

   Bases: :py:obj:`Karana.Core.LockingBaseVars`, :py:obj:`Karana.Core.BaseVars`


   The Vars for the SubTree class.


   .. py:property:: base_bodies
      :type: Karana.Core.VarVecString


      base bodies


   .. py:property:: children_subtrees
      :type: Karana.Core.VarInt


      number of children subtrees


   .. py:property:: coord_sanitization_subhinges
      :type: Karana.Core.VarVecString


      coord sanitization subhinges


   .. py:property:: enabled_algorithmically
      :type: Karana.Core.VarBool


      whether algorithmically enabled


   .. py:property:: has_compound_bodies
      :type: Karana.Core.VarBool


      whether has compound bodies


   .. py:property:: has_nested_compound_bodies
      :type: Karana.Core.VarBool


      whether has nested compound bodies


   .. py:property:: leaf_bodies
      :type: Karana.Core.VarVecString


      leaf bodies


   .. py:property:: nQ
      :type: Karana.Core.VarInt


      nQ


   .. py:property:: nU
      :type: Karana.Core.VarInt


      nU


   .. py:property:: n_bodies
      :type: Karana.Core.VarInt


      number of bodies


   .. py:property:: n_physical_bodies
      :type: Karana.Core.VarInt


      number of physical bodies


   .. py:property:: parent_subtree
      :type: Karana.Core.VarString


      The parent subtree


   .. py:property:: physical_virtual_root
      :type: Karana.Core.VarString


      The physical virtual root body name


   .. py:property:: virtual_root
      :type: Karana.Core.VarString


      The virtual root body name


.. py:class:: SubhingeBase

   Bases: :py:obj:`CoordBase`


   


   .. py:method:: getPrescribed() -> bool

      Return the prescribed flag for the subhinge
      :returns: the prescribed mode status



   .. py:method:: parentHinge() -> HingeBase

      Return the parent hinge for the subhinge
      :returns: the PhysicalHinge parent hinge



   .. py:method:: setPrescribed(flag: bool) -> None

      Set the prescribed flag for the subhinge
      :param flag: the enable/disable flag



   .. py:method:: subhingeType() -> SubhingeType

      Helper method to return the subhinge type

      :returns: the subhinge type



   .. py:method:: subhingeTypeString() -> str

      Helper method to return the string name for a SubhingeType subhinge
      type

      :param shtype: the subhinge type

      :returns: the subhinge type as a string



.. py:class:: SubhingeType(*args, **kwds)

   Bases: :py:obj:`enum.Enum`


   The available subhinge types


   .. py:attribute:: COMPOUND
      :type:  ClassVar[SubhingeType]


   .. py:attribute:: LINEAR
      :type:  ClassVar[SubhingeType]


   .. py:attribute:: LINEAR3
      :type:  ClassVar[SubhingeType]


   .. py:attribute:: LOCKED
      :type:  ClassVar[SubhingeType]


   .. py:attribute:: PIN
      :type:  ClassVar[SubhingeType]


   .. py:attribute:: SCREW
      :type:  ClassVar[SubhingeType]


   .. py:attribute:: SPHERICAL
      :type:  ClassVar[SubhingeType]


   .. py:attribute:: SPHERICAL_QUAT
      :type:  ClassVar[SubhingeType]


   .. py:method:: to_yaml(representer, node)
      :classmethod:


      Class method used to represent SubhingeType in a yaml file.



   .. py:method:: from_yaml(_, node) -> Self
      :classmethod:


      Construct a SubhingeType from yaml file data.



   .. py:method:: to_json(o: SubhingeType) -> dict[str, Any]
      :staticmethod:


      Class method used to represent SubhingeType in a json file.



   .. py:method:: from_json(d: dict[str, Any]) -> Self
      :classmethod:


      Construct a SubhingeType from json file data.



.. py:class:: TerminateCrossingCallbackRegistry

   .. py:attribute:: trace_callback_registry
      :type:  bool


   .. py:method:: __contains__(arg0: str) -> bool

      Check whether the given callback is contained within the registry.
      :param item: The name of the callback to check for.
      :type item: str

      :returns: True if the item is in the CallbackRegistry, False otherwise.
      :rtype: bool



   .. py:method:: __getitem__(key: str | SupportsInt | SupportsIndex) -> collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], bool]

      Get a function by name



   .. py:method:: __len__() -> int

      Get the number of callbacks registered to the CallbackRegistry.

      :returns: Number of callbacks registered in the CallbackRegistry.
      :rtype: int



   .. py:method:: __setitem__(key: str | SupportsInt | SupportsIndex, func: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], bool]) -> None

      Set a function with a string name or integer index



   .. py:method:: clear() -> None

      Clear out the entire CallbackRegistry. All callbacks will be removed.



   .. py:method:: dump(prefix: str = '') -> None

      Print out the string from `dumpString`. See `dumpString` for more details.



   .. py:method:: dumpString(prefix: str = '') -> str

      Create a string that lists all the functions by name.



   .. py:method:: erase(name: str, okay_not_exists: bool = False) -> None
                  erase(index: SupportsInt | SupportsIndex) -> None

      Erase the callback at the provided index.

      :param name: The index of the callback to erase.
      :type name: int



   .. py:method:: execute(arg0: SupportsFloat | SupportsIndex | numpy.timedelta64, arg1: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> list[bool]

      Execute all functions in the registry.



   .. py:method:: executeAndPopReverse(arg0: SupportsFloat | SupportsIndex | numpy.timedelta64, arg1: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> list[bool]

      Execute all functions in the registry in reverse and delete them as we go.



   .. py:method:: executeReverse(arg0: SupportsFloat | SupportsIndex | numpy.timedelta64, arg1: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> list[bool]

      Execute all functions in the registry in reverse.



   .. py:method:: insertAfter(item: str, name: str, fn: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], bool]) -> None

      Insert a function after another in the registry.
      :param item: The name of the item to insert this new one after.
      :type item: str
      :param name: The name of the new item.
      :type name: str
      :param fn: The callback associated with the new item.
      :type fn: Callable



   .. py:method:: insertBefore(item: str, name: str, fn: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], bool]) -> None

      Insert a function before another in the registry.
      :param item: The name of the item to insert this new one before.
      :type item: str
      :param name: The name of the new item.
      :type name: str
      :param fn: The callback associated with the new item.
      :type fn: Callable



   .. py:method:: pop(name: str) -> collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], bool]
                  pop(index: SupportsInt | SupportsIndex) -> collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64, Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]], bool]

      Pop the callback at the provided index.

      :param name: The index of the callback to pop.
      :type name: int



   .. py:method:: size() -> int

      Get the number of callbacks registered to the CallbackRegistry.

      :returns: Number of callbacks registered in the CallbackRegistry.
      :rtype: int



.. py:class:: TimeKeeper(fc: Karana.Frame.FrameContainer)

   Bases: :py:obj:`Karana.Core.Base`


   Keeps track of time.


   .. py:method:: create(fc: Karana.Frame.FrameContainer) -> TimeKeeper
      :staticmethod:


      Create a new instance of TimeKeeper.

      :param fc: FrameContainer. Used to update ephemeris in derived classes.
                 The _initial_ephemeris will also be set to the
                 FrameContainer's current ephemeris.

      :returns: A pointer to the newly created instance of TimeKeeper.



   .. py:method:: utcTimeToEphemeris(utc_time: str) -> float
      :staticmethod:


      Convert a time in UTC to an ephemeris.

      :param utc_time: The utc_time given as a string in the form "YYYY-MM-
                       DDThh:mm:ss.ss" where Y is the year, M is the month, D
                       is the day, h is the hour, m is the minute, and s is the
                       second. The seconds can have decimals.

      :returns: The utc_time as an ephemeris.



   .. py:method:: getTime() -> numpy.timedelta64

      Get the time from TimeKeeper.

      :returns: The current time.



   .. py:method:: getVars() -> TimeKeeperVars


   .. py:method:: isReady() -> bool

      Determine if the TimeKeeper is initialized.

      :returns: true if initialized, false otherwise.



   .. py:method:: setInitialEphemeris(initial_ephemeris: SupportsFloat | SupportsIndex) -> None
                  setInitialEphemeris(utc_time: str) -> None

      Set the initial ephemeris.

      :param utc_time: The UTC time as a string in the form "YYYY-MM-
                       DDThh:mm:ss.ss" where Y is the year, M is the month, D
                       is the day, h is the hour, m is the minute, and s is the
                       second. The seconds can have decimals.



   .. py:method:: setTime(time: SupportsFloat | SupportsIndex | numpy.timedelta64) -> None

      Set the TimeKeeper's time.

      :param time: The current time.



.. py:class:: TimeKeeperVars

   Bases: :py:obj:`Karana.Core.BaseVars`


   Vars for the TimeKeeper class.


   .. py:property:: time
      :type: Karana.Core.VarDouble


      The current time.


.. py:class:: TimedEvent(name: str, t: SupportsFloat | SupportsIndex | numpy.timedelta64, fn: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64], None], pre_hop: bool)

   Bases: :py:obj:`Karana.Core.Base`


   This class is used to execute events at a given time. The initial time
   and function to execute are constructor arguments. The callback
   function itself can be get/set afterwards as well using the `f` member
   variable. The `period` and `reschedule_fn` are member variables that
   are used for recurring callbacks. If the `period` is non-zero, then
   the `TimedEvent` will be rescheduled using that period. If the period
   is 0, and the `reschedule_fn` is set, then the result of the
   `reschedule_fn` will be used to determine the next reschedule time. If
   the `period` is 0 and the `reschedule_fn` is not set, then the
   callback will not be rescheduled.


   .. py:method:: create(name: str, t: SupportsFloat | SupportsIndex | numpy.timedelta64, fn: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64], None], pre_hop: bool) -> TimedEvent
      :staticmethod:


      Constructor for TimedEvent.
      :param name: The event's name.
      :param t: The time to execute the TimedEvent at.
      :param fn: The function to execute.
      :param pre_hop: This determines whether the timed event runs before or
                      after the hop.

      :returns: the TimedEvent instance



   .. py:method:: __gt__(other: TimedEvent) -> bool

      Comparison operator. Used mainly to order TimedEvents on a heap.

      First time is used to compare. If this is the same, then priority is
      used. If this is also the same, then the id is used.

      :param other:
                    - The TimedEvent to compare this one against.

      :returns: comparison status



   .. py:method:: dumpString(prefix: str = '', options: Karana.Core.DumpOptionsBase = None) -> str

      Dump the TimedEvent information to a string.

      :param prefix: A string to use as prefix for each output line.
      :param options: Struct with options to tailor the output.

      :returns: A string with the dump info for this TimedEvent.



   .. py:method:: isPreHop() -> bool

      Returns whether the TimedEvent is a pre-hop timed event or not.
      :returns: `true` if the TimedEvent is a pre-hop timed event. `false`
                otherwise.



   .. py:method:: nextEventTime() -> numpy.timedelta64

      Get the next time this TimedEvent will execute its event function at.

      :returns: The next time this TimedEvent will execute its event function at.



   .. py:method:: reschedule() -> bool

      Reschedules the callback if appropriate. This will update the internal
      time with the new time if it should be rescheduled.
      :returns: true if the `TimedEvent` is rescheduled and false otherwise.



   .. py:property:: fn
      :type: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64], None]


      The callback function that runs when this timed event is called


   .. py:property:: period
      :type: numpy.timedelta64


      The period to reschedule this callback at. If 0, then the
      reschedule_fn will be used.


   .. py:property:: priority
      :type: int


      The priority for this callback. This differentiates callbacks that are
      running at the same time. Lower is a higher priority.


   .. py:property:: reschedule_fn
      :type: collections.abc.Callable[[SupportsFloat | SupportsIndex | numpy.timedelta64], numpy.timedelta64 | None]


      The reschedule_fn is used if and only if the period is 0. If the
      period is 0 and the reschedule_fn is not defined, then this timed
      event will not be rescheduled. If the reschedule_fn returns
      std::nullopt, then this will not be rescheduled.


.. py:class:: ZeroCrossingCallbackRegistry

   .. py:attribute:: trace_callback_registry
      :type:  bool


   .. py:method:: __contains__(arg0: str) -> bool

      Check whether the given callback is contained within the registry.
      :param item: The name of the callback to check for.
      :type item: str

      :returns: True if the item is in the CallbackRegistry, False otherwise.
      :rtype: bool



   .. py:method:: __getitem__(key: str | SupportsInt | SupportsIndex) -> collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], bool], bool]

      Get a function by name



   .. py:method:: __len__() -> int

      Get the number of callbacks registered to the CallbackRegistry.

      :returns: Number of callbacks registered in the CallbackRegistry.
      :rtype: int



   .. py:method:: __setitem__(key: str | SupportsInt | SupportsIndex, func: collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], bool], bool]) -> None

      Set a function with a string name or integer index



   .. py:method:: clear() -> None

      Clear out the entire CallbackRegistry. All callbacks will be removed.



   .. py:method:: dump(prefix: str = '') -> None

      Print out the string from `dumpString`. See `dumpString` for more details.



   .. py:method:: dumpString(prefix: str = '') -> str

      Create a string that lists all the functions by name.



   .. py:method:: erase(name: str, okay_not_exists: bool = False) -> None
                  erase(index: SupportsInt | SupportsIndex) -> None

      Erase the callback at the provided index.

      :param name: The index of the callback to erase.
      :type name: int



   .. py:method:: execute(arg0: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], arg1: bool) -> list[bool]

      Execute all functions in the registry.



   .. py:method:: executeAndPopReverse(arg0: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], arg1: bool) -> list[bool]

      Execute all functions in the registry in reverse and delete them as we go.



   .. py:method:: executeReverse(arg0: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], arg1: bool) -> list[bool]

      Execute all functions in the registry in reverse.



   .. py:method:: insertAfter(item: str, name: str, fn: collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], bool], bool]) -> None

      Insert a function after another in the registry.
      :param item: The name of the item to insert this new one after.
      :type item: str
      :param name: The name of the new item.
      :type name: str
      :param fn: The callback associated with the new item.
      :type fn: Callable



   .. py:method:: insertBefore(item: str, name: str, fn: collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], bool], bool]) -> None

      Insert a function before another in the registry.
      :param item: The name of the item to insert this new one before.
      :type item: str
      :param name: The name of the new item.
      :type name: str
      :param fn: The callback associated with the new item.
      :type fn: Callable



   .. py:method:: pop(name: str) -> collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], bool], bool]
                  pop(index: SupportsInt | SupportsIndex) -> collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], bool], bool]

      Pop the callback at the provided index.

      :param name: The index of the callback to pop.
      :type name: int



   .. py:method:: size() -> int

      Get the number of callbacks registered to the CallbackRegistry.

      :returns: Number of callbacks registered in the CallbackRegistry.
      :rtype: int



.. py:class:: ModalNodeDeformationProvider

   Bases: :py:obj:`Karana.Dynamics.NodeDeformationProvider`


   Node deformation provider class for modeling small deformation via
   modal representation

   See :ref:`modal_flex_body_sec` section for more information of
   deformation provider classes.


   .. py:method:: deformedRotFrame() -> Karana.Frame.Frame

      Return the deformed rotational frame
      :returns: the deformed rotational Frame instance



   .. py:method:: deformedTransFrame() -> Karana.Frame.Frame

      Return the deformed translational frame
      :returns: the deformed translational Frame instance



   .. py:method:: getNodalMatrix() -> Annotated[numpy.typing.NDArray[numpy.float64], [6, n]]

      Return the nodal deformation matrix
      :returns: the nodal matrix



   .. py:method:: setNodalMatrix(matrix: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, n]]) -> None

      Set the nodal deformation matrix
      :param nodal_matrix: the nodal matrix



   .. py:method:: undeformedFrame() -> Karana.Frame.Frame

      Return the undeformed frame
      :returns: the undeformed Frame instance



.. py:class:: PhysicalModalBody

   Bases: :py:obj:`Karana.Dynamics.PhysicalBody`


   Flexible body class supporting assumed modes based small deformation

   See the :ref:`modal_flex_body_sec` section for more discussion on
   flexible bodies.


   .. py:method:: addSerialChain(name: str, nbodies: SupportsInt | SupportsIndex, root: Karana.Dynamics.PhysicalBody = None, htype: Karana.Dynamics.HingeType = ..., params: Karana.Dynamics.PhysicalBodyParams = None) -> list[Karana.Dynamics.PhysicalBody]
      :staticmethod:


      Add a serial chain of flexible physical bodies to the multibody system

      Add a serial chain of flexible bodies to the multibody system to the
      specified root body with the specified mass properties, hinge type and
      hinge connection properties. This method is mainly used for
      procedurally generating large test systems.

      :param name: prefix string to use for the new body names
      :param nbodies: number of bodies
      :param root: the parent body to attach the chain to
      :param htype: the hinge type
      :param params: the body params for each body

      :returns: the list of new flexible bodies



   .. py:method:: addTree(name: str, branch_length: SupportsInt | SupportsIndex, nbranches: SupportsInt | SupportsIndex, depth: SupportsInt | SupportsIndex, root: Karana.Dynamics.PhysicalBody = None, htype: Karana.Dynamics.HingeType = ..., param: Karana.Dynamics.PhysicalBodyParams = None) -> list[Karana.Dynamics.PhysicalBody]
      :staticmethod:


      Add a sub-tree of flexible physical bodies to the multibody system

      Add a sub-tree of flexible bodies to the multibody system to the
      specified root body with the specified mass properties, hinge type and
      hinge connection properties. This method is mainly used for
      procedurally generating large test systems.

      :param name: prefix string to use for the new body names
      :param branch_length: the number of bodies in a branch
      :param nbranches: the number of children branches
      :param depth: the number of branching levels to create
      :param root: the parent body to attach the chain to
      :param htype: the hinge type
      :param params: the body params for each body

      :returns: the list of new rigid bodies



   .. py:method:: create(name: str, mbs: Karana.Dynamics.Multibody, nmodes: SupportsInt | SupportsIndex) -> PhysicalModalBody
      :staticmethod:


      Factory method to create a PhysicalModalBody instance

      :param name: the body's name
      :param mbs: the Multibody instance
      :param nmodes: the number of deformation modes

      :returns: a new PhysicalModalBody instance



   .. py:method:: getDampingVector() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Get the damping vector for the body.
      :returns: The new damping vector for the body.



   .. py:method:: getStiffnessVector() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Get the stiffness vector for the body.
      :returns: The stiffness vector for the body.



   .. py:method:: getVars() -> PhysicalModalBodyVars


   .. py:method:: setDampingVector(damping: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> None

      Set the damping vector for the body.
      :param damping: The new damping vector for the body.



   .. py:method:: setStiffnessVector(stiffness: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]]) -> None

      Set the stiffness vector for the body.
      :param stiffness: The new stiffness vector for the body.



   .. py:method:: toDS() -> Karana.Dynamics.SOAFlexDyn_types.BodyDS

      Create a ModalBodyDS from this PhysicalModalBody model.

      :returns: * *ModalBodyDS*
                * *A ModalBodyDS instance with values set to match this model.*



   .. py:method:: toStateDS() -> Karana.Dynamics.SOAFlexDyn_types.BodyStateDS

      Create a ModalBodyStateDS from this PhysicalModalBody model.

      :returns: * *ModalBodyStateDS*
                * *A ModalBodyStateDS instance with values set to match this model.*



   .. py:method:: trimModes(keep_modes: collections.abc.Sequence[SupportsInt | SupportsIndex]) -> None

      Trim the modes to only keep the ones in the specified list of indices
      :param keep_modes: The indices of the modes to retain



.. py:class:: PhysicalModalBodyParams(spI: Karana.Math.SpatialInertia = ..., axes: collections.abc.Sequence[Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]]] = ..., body_to_joint_transform: Karana.Math.HomTran = ..., inb_to_joint_transform: Karana.Math.HomTran = ..., scene_parts: collections.abc.Sequence[Karana.Scene.ScenePartSpec] = [], nmodes: SupportsInt | SupportsIndex = 4, stiffness: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]] = ..., damping: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]] = ..., pnode_nodal_matrix: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, n]] = ..., onode_nodal_matrix: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, n]] = ...)

   Bases: :py:obj:`Karana.Dynamics.PhysicalBodyParams`


   .. py:property:: damping
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]



   .. py:property:: nmodes
      :type: int



   .. py:property:: onode_nodal_matrix
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]



   .. py:property:: pnode_nodal_matrix
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]



   .. py:property:: stiffness
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]



.. py:class:: PhysicalModalBodyVars

   Bases: :py:obj:`Karana.Dynamics.PhysicalBodyVars`, :py:obj:`Karana.Frame.FrameVars`, :py:obj:`Karana.Core.LockingBaseVars`, :py:obj:`Karana.Core.BaseVars`


   


   .. py:property:: Q
      :type: Karana.Core.VarVec


      Modal coordinates


   .. py:property:: U
      :type: Karana.Core.VarVec


      Modal velocities


   .. py:property:: Udot
      :type: Karana.Core.VarVec


      Modal accelerations


   .. py:property:: damping
      :type: Karana.Core.VarVec


      damping


   .. py:property:: n_modes
      :type: Karana.Core.VarInt


      The number of modes


   .. py:property:: stiffness
      :type: Karana.Core.VarVec


      stiffness


