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/Algorithms/index
   /generated/python_api/Karana/Dynamics/SOADyn_types/index
   /generated/python_api/Karana/Dynamics/SOAFlexDyn_types/index
   /generated/python_api/Karana/Dynamics/fa2ta/index


Attributes
----------

.. autoapisummary::

   Karana.Dynamics.SubhingePyType


Classes
-------

.. autoapisummary::

   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.CELoopKinematicsPlanar4Bar
   Karana.Dynamics.CKFrozenCoordType
   Karana.Dynamics.CeresNonlinearSolver
   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.EigenNonlinearSolver
   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.IODataPool
   Karana.Dynamics.LevenbergMarquardtStatus
   Karana.Dynamics.Linear3Subhinge
   Karana.Dynamics.LinearSubhinge
   Karana.Dynamics.LockedOffsetSubhinge
   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.MMOptions
   Karana.Dynamics.MMSolverType
   Karana.Dynamics.ModelManager
   Karana.Dynamics.ModelManagerVars
   Karana.Dynamics.ModelPool
   Karana.Dynamics.MultiJacobianGenerator
   Karana.Dynamics.Multibody
   Karana.Dynamics.Node
   Karana.Dynamics.NodeDeformationProvider
   Karana.Dynamics.NodeVars
   Karana.Dynamics.NonlinearSolver
   Karana.Dynamics.NonlinearSolverStatus
   Karana.Dynamics.ParentBodyAttachmentParams
   Karana.Dynamics.ParentPhysicalBodyAttachmentParams
   Karana.Dynamics.Physical1DofSubhinge
   Karana.Dynamics.PhysicalBody
   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.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.SubTreeLayoutBodyData
   Karana.Dynamics.SubTreeVars
   Karana.Dynamics.SubhingeBase
   Karana.Dynamics.SubhingeMask
   Karana.Dynamics.SubhingeType
   Karana.Dynamics.TerminateCrossingCallbackRegistry
   Karana.Dynamics.TimedEvent
   Karana.Dynamics.ZeroCrossingCallbackRegistry
   Karana.Dynamics.PhysicalBodyParams
   Karana.Dynamics.PhysicalSubhingeParams
   Karana.Dynamics.PhysicalHingeParams
   Karana.Dynamics.PinSubhingeParams
   Karana.Dynamics.LinearSubhingeParams
   Karana.Dynamics.SphericalSubhingeParams
   Karana.Dynamics.SphericalQuatSubhingeParams
   Karana.Dynamics.Linear3SubhingeParams
   Karana.Dynamics.LockedPhysicalSubhingeParams
   Karana.Dynamics.LockedOffsetPhysicalSubhingeParams
   Karana.Dynamics.ScrewSubhingeParams
   Karana.Dynamics.VarPythonScriptContext
   Karana.Dynamics.ModalNodeDeformationProvider
   Karana.Dynamics.ParentPhysicalModalBodyAttachmentParams
   Karana.Dynamics.PhysicalModalBody
   Karana.Dynamics.PhysicalModalBodyVars
   Karana.Dynamics.PhysicalModalBodyParams


Functions
---------

.. autoapisummary::

   Karana.Dynamics.valuePrinter
   Karana.Dynamics.fullPrintOpts
   Karana.Dynamics.createIODataPool
   Karana.Dynamics.createModelPool
   Karana.Dynamics.treeForwardDynamicsPool
   Karana.Dynamics.valuePrinter
   Karana.Dynamics.fullPrintOpts


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

.. py:function:: valuePrinter(q) -> str

   Print values for Python scripts.

   :param q: The value to print
   :type q: Quantity | NDArray

   :returns: The string representation of the value.
   :rtype: str


.. py:function:: fullPrintOpts()

   Context to print numpy values with full precision.


.. 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.Var[Karana.Math.Ktyping.Vec]


      accel error


   .. py:property:: n_residuals
      :type: Karana.Core.Var[int]


      number of residuals


   .. py:property:: pose_error
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      pose error


   .. py:property:: type
      :type: Karana.Core.Var[str]


      The constraint type


   .. py:property:: vel_error
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      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: collections.abc.Sequence[tuple[CoordBase, SupportsInt | SupportsIndex]], indep_indices_Q: collections.abc.Sequence[tuple[CoordBase, SupportsInt | SupportsIndex]] = ..., 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:: createFromCoords(name: str, parent_subtree: SubGraph, subtree: SubGraph, indep_coords_U: collections.abc.Sequence[tuple[CoordBase, SupportsInt | SupportsIndex]], indep_coords_Q: collections.abc.Sequence[tuple[CoordBase, SupportsInt | SupportsIndex]] = ..., 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_cbs_U: the list of independent U coordinates
      :param indep_cbs_Q: the list of independent Q coordinates
      :param rank_threshold: threshold to use when computing error Jacobian
                             rank

      :returns: a CECompoundBody instance



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

       Return the X matrix that maps the min independent U to the
      full U (independent, dependent, constraint dofs) for the compound body

      :returns: the full constraint X matrix



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

       Return the Xdot*U product vector where Xdot is the time derivative
      of the X constraint matrix

      :returns: the Xdot*U product



   .. py:method:: getLoopSolver() -> CELoopKinematicsNumeric

      Return the CELoopKinematicsSolver for the compound body

      :returns: the CE loop solver



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


   .. py:method:: setLoopSolver(arg0: CELoopKinematicsBase) -> None

      Set the CELoopKinematicsSolver for the compound body

      The solver argument must have the same subgraph as the compound body.
      This requirement allows applications to ensure that the solver is
      compatible with the compound body. The independent coordinates may
      change when the loop solver is changed since these are set up and
      owned by the loop solver. The main use of this method is replace the
      general purpose solver with a specialized, perhaps analytical solver
      for the compound body.

      :param ls: 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:: getIndependentCoordsQ() -> list[tuple[CoordBase, int]]

      Get the independent Q coordinates

      :returns: the independent Q coordinate



   .. py:method:: getIndependentCoordsU() -> list[tuple[CoordBase, int]]

      Get the independent U coordinates

      :returns: the independent U coordinate



.. py:class:: CELoopKinematicsBaseVars

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


   The Vars for the  CELoopKinematicsBase class.


   .. py:property:: dep_indices_U
      :type: Karana.Core.Var[Karana.Math.Ktyping.VecInt]


      dependent U coord indices


   .. py:property:: indep_indices_Q
      :type: Karana.Core.Var[Karana.Math.Ktyping.VecInt]


      independent Q coord indices


   .. py:property:: indep_indices_U
      :type: Karana.Core.Var[Karana.Math.Ktyping.VecInt]


      independent U coord indices


   .. py:property:: inert_indices_U
      :type: Karana.Core.Var[Karana.Math.Ktyping.VecInt]


      inert U coord indices


.. py:class:: CELoopKinematicsNumeric

   Bases: :py:obj:`CELoopKinematicsBase`


   The numerical iterations based CE kinematics loop solver


   .. py:method:: cks() -> ConstraintKinematicsSolver

      Return the constraint kinematics solver instance

      :returns: the constraint kinematics solver



   .. py:method:: setIndependentCoords(indep_coords_U: collections.abc.Sequence[tuple[CoordBase, SupportsInt | SupportsIndex]], indep_coords_Q: collections.abc.Sequence[tuple[CoordBase, SupportsInt | SupportsIndex]] = []) -> None

      Set the independent Q and U coordinate indices.

      At least one of input lists is required to be non-empty. Empty lists
      are ignored. The indices consist of a subhinge and an offset in its
      coords list.

      :param indep_cbs_U: the independent U coordinates
      :param indep_cbs_Q: the independent Q coordinates



.. py:class:: CELoopKinematicsNumericVars

   Bases: :py:obj:`CELoopKinematicsBaseVars`


   The Vars for the  CELoopKinematicsNumeric class.


   .. py:property:: rows_Y
      :type: Karana.Core.Var[Karana.Math.Ktyping.VecInt]


      independent rows of the Y matrix


.. py:class:: CELoopKinematicsPlanar4Bar

   Bases: :py:obj:`CELoopKinematicsBase`


   The analytical kinematics solver for a planar 4-bar system

   This analytical solver for a planar 4-bar linkage requires that the
   subgraph's bodies be a serial chain of length 3. The cut-join loop
   constraint is between the third body and the first body's parent body.
   All the hinges involved should be REVOLUTE with parallel rotational
   axes.  The independent coordinate is the first body's coordinate.


   .. py:method:: create(name: str, bodies_sg: SubGraph) -> CELoopKinematicsPlanar4Bar
      :staticmethod:


      Constructs a CELoopKinematicsPlanar4Bar instance

      :param name: instance name
      :param bodies_sg: SubGraph with bodies being embedded

      :returns: a CELoopKinematicsPlanar4Bar instance



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

      Return the planar frame for the 4-bar

      :returns: the planar frame



   .. py:method:: setSolutionMode(arg0: bool) -> None

      Select the open of crossed solution mode

      :param mode: the solution mode



.. 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:: CeresNonlinearSolver(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], type: CeresNonlinearSolver = SolverType.LEVENBERG_MARQUARDT)

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


   CeresNonlinearSolver class manages a nonlinear problem and associated
   solver.


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

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


      Solver type to use internally, options are LEVENBERG_MARQUARDT or DOGLEG.


      .. py:attribute:: DOGLEG
         :type:  ClassVar[CeresNonlinearSolver]


      .. py:attribute:: LEVENBERG_MARQUARDT
         :type:  ClassVar[CeresNonlinearSolver]



   .. 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], type: CeresNonlinearSolver = SolverType.LEVENBERG_MARQUARDT) -> CeresNonlinearSolver
      :staticmethod:


      CeresNonlinearSolver constructor. This is a container that holds the
      information CeresNonlinearSolver needs to solve a nonlinear problem.

      :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 should take in a vector of inputs
                and output a matrix of outputs.
      :param type: The type of nonlinear solver to use.

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



   .. py:method:: getSolverType() -> CeresNonlinearSolver

      Get the non-linear solver type.

      :returns: The current non-linear solver type.



   .. py:method:: setSolverType(type: CeresNonlinearSolver) -> None

      Set the nonlinear solver type.

      :param type: New solver type to use.



.. 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:: parentHinge() -> CompoundHinge

      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:: 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.Var[Karana.Math.Ktyping.Vec]


      The Q coordinates


   .. py:property:: Qdot
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      The Qdot coordinates


   .. py:property:: T
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      The T coordinates


   .. py:property:: U
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      The U coordinates


   .. py:property:: Udot
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      The Udot coordinates


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

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


   


   .. 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(coord: tuple[CoordBase, 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 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(use_ceres: bool = False) -> float

      Solve for the Q generalized coordinates to satisfy constraints

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

      :param use_ceres: Whether to use a Ceres solver (more robust, obeys joint
                        stops, but slower) or Eigen (the default).

      :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(coord: tuple[CoordBase, SupportsInt | SupportsIndex], ctype: CKFrozenCoordType = CKFrozenCoordType.Q_U) -> None

      Method to unfreeze a coordinate component

      :param coord: The coordinate whose element is 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.Var[Karana.Math.Ktyping.VecInt]


      dependent  Q coord indices


   .. py:property:: frozen_indices_Q
      :type: Karana.Core.Var[Karana.Math.Ktyping.VecInt]


      frozen Q coord indices


   .. py:property:: frozen_indices_U
      :type: Karana.Core.Var[Karana.Math.Ktyping.VecInt]


      frozen U coord indices


.. 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: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]) -> bool
                  accumT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.QuantityOrValue[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: getQ() -> Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]

      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() -> Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]

      Return the Qdot rate coordinates

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

      :returns: Array of values.



   .. py:method:: getT() -> Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]

      Return the T generalized forces

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

      :returns: Array of values.



   .. py:method:: getU() -> Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]

      Return the U velocity coordinates

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

      :returns: Array of values.



   .. py:method:: getUdot() -> Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]

      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: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]) -> bool
                  setQ(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.QuantityOrValue[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setT(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]) -> bool
                  setT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.QuantityOrValue[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setU(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]) -> bool
                  setU(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.QuantityOrValue[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setUdot(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]) -> bool
                  setUdot(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.QuantityOrValue[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



.. 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]]) -> bool
                  accumT(fill_value: SupportsFloat | SupportsIndex) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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


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

      Get a vector of the CoordBase instances for this CoordData

      :returns: A vector of CoordBase instances.



   .. py:method:: coordOffset(arg0: tuple[CoordBase, SupportsInt | SupportsIndex], arg1: bool) -> int

      Returns the packing offset for the specified Coordinate

      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 Coordinate with CoordBase and index to check for
      :param for_U: If true, then U offset is returned, else Q offset

      :returns: The coordinate offset value



   .. 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]]) -> bool
                  setQ(val: SupportsFloat | SupportsIndex) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. 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.Var[int]


      nQ


   .. py:property:: nU
      :type: Karana.Core.Var[int]


      nU


   .. py:property:: n_coord_base
      :type: Karana.Core.Var[int]


      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.Var[float]


      The scale ratio for the CoordinateConstraint.


.. py:class:: EigenNonlinearSolver(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, type: EigenNonlinearSolver = SolverType.LEVENBERG_MARQUARDT)

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


   EigenNonlinearSolver class manages a nonlinear problem and associated
   solver.


   .. 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[EigenNonlinearSolver]


      .. py:attribute:: LEVENBERG_MARQUARDT
         :type:  ClassVar[EigenNonlinearSolver]



   .. 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, type: EigenNonlinearSolver = SolverType.LEVENBERG_MARQUARDT) -> EigenNonlinearSolver
      :staticmethod:


      Constructor for nonlinear solver using numerical methods shipped with
      Eigen.

      :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.
      :param type: The type of nonlinear solver to use.

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



   .. py:method:: getSolverType() -> EigenNonlinearSolver

      Get the non-linear solver type.

      :returns: The current non-linear solver type.



   .. py:method:: setSolverType(type: EigenNonlinearSolver) -> None

      Set the solver type.

      :param solver_type: The solver.



.. 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.Var[str]


      The hinge type


   .. py:property:: nQ
      :type: Karana.Core.Var[int]


      The number of Q coordinates


   .. py:property:: nU
      :type: Karana.Core.Var[int]


      The number of U coordinates


   .. py:property:: n_subhinges
      :type: Karana.Core.Var[int]


      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:: getDistance2DHingeParams(arg0: SupportsFloat | SupportsIndex, arg1: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]]) -> HingeParams
      :staticmethod:


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

      For a HingeType::DISTANCE_2D joint, the outboard pnode is positionally
      limited to the edge of a circle of a specified radius in a plane
      specified by its normal.  @param distance the sphere radius @param
      normal the unit normal to the circle's plane @return struct with the
      hinge onode, pnode and axis parameter values



   .. py:method:: getDistance3DHingeParams(arg0: SupportsFloat | SupportsIndex) -> HingeParams
      :staticmethod:


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

      For a HingeType::DISTANCE_3D joint, the outboard pnode is positionally
      limited to the surface of a sphere of a specified radius.

      :param distance: the sphere radius

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



   .. 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.SpatialAcceleration


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


.. 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:: subhinge_params
      :type: list[Karana.Dynamics.SOADyn_types.PhysicalSubhingeParams]


      list of subhinge parameters


.. 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

      :returns: 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:: DISTANCE_2D
      :type:  ClassVar[HingeType]


   .. py:attribute:: DISTANCE_3D
      :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:: LOCKED_OFFSET
      :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:: IODataPool

   .. py:property:: Q
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [200, 1]]


      the Q generalized coordinates


   .. py:property:: T
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [200, 1]]


      the T generalized force coordinates


   .. py:property:: U
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [200, 1]]


      the U generalized velocity coordinates


   .. py:property:: Udot
      :type: Annotated[numpy.typing.NDArray[numpy.float64], [200, 1]]


      the Udot generalized acceleration coordinates


   .. py:property:: external_force
      :type: Annotated[list[Karana.Math.SpatialForce], FixedSize(30)]


      the external spatial force values


.. 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:method:: accumT(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Force[Karana.Math.Ktyping.Vec]) -> bool
                  accumT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Force[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: getQ() -> Karana.Math.Ktyping.Length[Karana.Math.Ktyping.Vec]

      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() -> Karana.Math.Ktyping.Velocity[Karana.Math.Ktyping.Vec]

      Return the Qdot rate coordinates

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

      :returns: Array of values.



   .. py:method:: getRangeLimits() -> Karana.Math.Ktyping.Length[Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]]

      Return the range limits matrix for this subhinge

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :returns: the range limits matrix



   .. py:method:: getT() -> Karana.Math.Ktyping.Force[Karana.Math.Ktyping.Vec]

      Return the T generalized forces

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

      :returns: Array of values.



   .. py:method:: getU() -> Karana.Math.Ktyping.Velocity[Karana.Math.Ktyping.Vec]

      Return the U velocity coordinates

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

      :returns: Array of values.



   .. py:method:: getUdot() -> Karana.Math.Ktyping.Acceleration[Karana.Math.Ktyping.Vec]

      Return the Udot acceleration coordinates

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

      :returns: Array of values.



   .. py:method:: setQ(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Length[Karana.Math.Ktyping.Vec]) -> bool
                  setQ(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Length[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setRangeLimits(limits: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Length[Karana.Math.Ktyping.Vec], offset: SupportsInt | SupportsIndex) -> None

      Set the range limits matrix for a subhinge Q component

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :param limits: the lower/upper range limits
      :param offset: the offset of the Q coordinate that this applies to e.g.,
                     0 means these limits are for the first coordinate of the
                     subhinge



   .. py:method:: setT(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Force[Karana.Math.Ktyping.Vec]) -> bool
                  setT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Force[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setU(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Velocity[Karana.Math.Ktyping.Vec]) -> bool
                  setU(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Velocity[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setUdot(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Acceleration[Karana.Math.Ktyping.Vec]) -> bool
                  setUdot(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Acceleration[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



.. 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:method:: accumT(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Force[Karana.Math.Ktyping.Vec]) -> bool
                  accumT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Force[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: getJointLimits() -> Karana.Math.Ktyping.Length[Karana.Math.Ktyping.Vec]

      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:: getQ() -> Karana.Math.Ktyping.Length[Karana.Math.Ktyping.Vec]

      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() -> Karana.Math.Ktyping.Velocity[Karana.Math.Ktyping.Vec]

      Return the Qdot rate coordinates

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

      :returns: Array of values.



   .. py:method:: getRangeLimits() -> Karana.Math.Ktyping.Length[Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]]

      Return the range limits matrix for this subhinge

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :returns: the range limits matrix



   .. py:method:: getT() -> Karana.Math.Ktyping.Force[Karana.Math.Ktyping.Vec]

      Return the T generalized forces

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

      :returns: Array of values.



   .. py:method:: getU() -> Karana.Math.Ktyping.Velocity[Karana.Math.Ktyping.Vec]

      Return the U velocity coordinates

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

      :returns: Array of values.



   .. py:method:: getUdot() -> Karana.Math.Ktyping.Acceleration[Karana.Math.Ktyping.Vec]

      Return the Udot acceleration coordinates

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

      :returns: Array of values.



   .. py:method:: setJointLimits(limits: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Length[Karana.Math.Ktyping.Vec]) -> 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:: setQ(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Length[Karana.Math.Ktyping.Vec]) -> bool
                  setQ(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Length[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setRangeLimits(limits: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Length[Karana.Math.Ktyping.Vec], offset: SupportsInt | SupportsIndex) -> None

      Set the range limits matrix for a subhinge Q component

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :param limits: the lower/upper range limits
      :param offset: the offset of the Q coordinate that this applies to e.g.,
                     0 means these limits are for the first coordinate of the
                     subhinge



   .. py:method:: setT(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Force[Karana.Math.Ktyping.Vec]) -> bool
                  setT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Force[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setU(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Velocity[Karana.Math.Ktyping.Vec]) -> bool
                  setU(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Velocity[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setUdot(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Acceleration[Karana.Math.Ktyping.Vec]) -> bool
                  setUdot(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Acceleration[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



.. py:class:: LockedOffsetSubhinge

   Bases: :py:obj:`LockedSubhinge`


   Represents a locked subhinge with transform offset

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


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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. 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:: setOffset(arg0: Karana.Math.HomTran) -> None

      Set the subhinge offset transform.

      :param offset: the offset param.



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



.. 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:method:: accumT(val: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> bool
                  accumT(fill_value: SupportsFloat | SupportsIndex) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. 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:: setQ(val: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> bool
                  setQ(fill_value: SupportsFloat | SupportsIndex) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



.. 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.Var[bool]


      has source node


   .. py:property:: has_target_node
      :type: Karana.Core.Var[bool]


      has target node


   .. py:property:: rel_Q
      :type: Karana.Core.Var[Karana.Math.Ktyping.Mat]


      The rel_Q matrix


   .. py:property:: source_Q
      :type: Karana.Core.Var[Karana.Math.Ktyping.Mat]


      The source_Q matrix


   .. py:property:: target_Q
      :type: Karana.Core.Var[Karana.Math.Ktyping.Mat]


      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.Var[Karana.Math.Ktyping.Vec3]


      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:: freezeNodes(name: str, mb: Multibody, nodes_f_to_f: Karana.Frame.FrameToFrame) -> LoopConstraintCutJoint
      :staticmethod:


      Factory method for creating a LoopConstraintCutJoint instance with
      locked_offset hinge for freezing one or a pair of nodes

      For an input f2f - with at least one of the oframe/pframe being a body
      node, this method creates a cutjoint constraint with a LOCKED_OFFSET
      hinge that constrains the f2f relative transforms from changing any
      further.

      :param name: the name for the loop constraint instance
      :param mb: The Multibody instance
      :param nodes_f_to_f: the Karana::Frame::FrameToFrame defining the node(s)
                           to freeze

      :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:: MMOptions

   Options for the model manager


   .. py:method:: create() -> MMOptions
      :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:: FORWARD_DYNAMICS
      :type:  ClassVar[MMSolverType]


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


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


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


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


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


      Class method used to represent MMSolverType in a json file.



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


      Construct a MMSolverType from json file data.



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


      Construct a MMSolverType from yaml file data.



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


      Class method used to represent MMSolverType in a yaml file.



.. py:class:: ModelManager(st: SubTree, sp_opts: MMOptions | 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: MMOptions | 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]) -> bool
                  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

      :returns: true if the all went well, and false if the input state was not
                valid



   .. 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:: getMaskedSubhinges() -> dict[SubhingeBase, SubhingeMask]

      Get the currently masked subhinges.

      :returns: A map of masked subhinges, where the keys are the subhinges and
                the values are the mask type.



   .. py:method:: getRegisteredModel(name: str) -> Karana.Models.BaseKModel | None

      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() -> Karana.Frame.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:: maskSubhinge(sh: SubhingeBase, mask: SubhingeMask) -> None

      Mask a subhinge.

      This can be used to remove a subhinge's coordinates, velocities, or
      both from the integrator. When this is the case, another event
      (KModel, callback function, etc.) should update the masked values
      manually.

      The mask parameter below controls which coordinates are masked. A
      value of NONE can be used to remove a mask if set.

      :param sh: The subhinge to mask.
      :param mask: The masking enum.



   .. 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:: runKModelsInParallel(models: collections.abc.Sequence[Karana.Models.BaseKModel], method_type: Karana.Models.OutputUpdateType) -> None
                  runKModelsInParallel(model_names: collections.abc.Sequence[str], method_type: Karana.Models.OutputUpdateType) -> None

      Run the given models in parallel.

      If multiple method types need to be run in parallel, then call this
      multiple times.

      :param models: The models to run in parallel.
      :param method_type: The method type to run in parallel.



   .. 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.

      :param x: the new state value

      .. seealso:: assembleState



   .. 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:: setTAConstraintErrorThreshold(arg0: SupportsFloat | SupportsIndex) -> None

      Set the constraint error threshold used in TA dynamics to check for
      bad state in the deriv function

      :param threshold: the



   .. 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:: setTimeKeeper(time_keeper: Karana.Frame.TimeKeeper) -> None

      Set the TimeKeeper used by this ModelManager.

      :param time_keeper: The new TimeKeeper to be used by this ModelManager.



   .. 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.Var[int]


      number of SubTree states


   .. py:property:: nstates
      :type: Karana.Core.Var[int]


      number of states


   .. py:property:: solver_type
      :type: Karana.Core.Var[str]


      solver type


   .. py:property:: time
      :type: Karana.Core.Var[float]


      current time


.. py:class:: ModelPool

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

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


   


   .. 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

      :returns: the ancestor Node for the Frame.



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

      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:: 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', print_connection_info: bool = True) -> tuple[Callable[[], None], Karana.Scene.WebScene]

      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"
      :param print_connection_info: If True, then print the connection info. Otherwise, do not print it.
      :type print_connection_info: bool

      :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', '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
                              "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:: __deepcopy__(arg0: Any) -> Node


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

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

      Accumulate the external spatial force at the node represented in the
      specified frame. This method adds 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. 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
      this has been done.

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



   .. 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:method:: transferNode(arg0: PhysicalBody) -> None

      Method to transfer a body node to a different body

      The inertial pose of the node is preserved after reattachment. This
      method is used by the pruning process which merges bodies and
      reattaches merged body nodes with to the parent body.

      This method is for moving regular, force and constraint nodes from one
      rigid body to another, and not for cases where either of the bodies is
      deformable. Transfer of additional data associated with nodes on
      deformable bodies is not handled by this method and must be done
      separately. Transfer of contact nodes is not supported by this method.

      :param new_parent: the new PhysicalBody to attach the node to.



.. 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.Var[Karana.Math.SpatialForce]


      external force on the node


   .. py:property:: force_node
      :type: Karana.Core.Var[bool]


      True if this is a force node


   .. py:property:: parent_body
      :type: Karana.Core.Var[str]


      parent body


.. py:class:: NonlinearSolver

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


   NonlinearSolver class manages a nonlinear problem and associated
   solver.


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

      Get the cost function.

      :returns: The cost function.



   .. py:method:: getJac() -> 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]

      Get the jacobian function.

      :returns: The jacobian function.



   .. py:method:: getStatus() -> NonlinearSolverStatus

      Get the status of the last solve() call.

      :returns: Status The outcome of the most recent solve() call.



   .. 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:: setFTol(ftol: SupportsFloat | SupportsIndex) -> None

      Set stopping tolerance for reduction in residual norm

      :param ftol: New tolerance value



   .. py:method:: setGTol(gtol: SupportsFloat | SupportsIndex) -> None

      Set stopping tolerance for jacobian norm

      :param gtol: New tolerance value



   .. 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:: setXTol(xtol: SupportsFloat | SupportsIndex) -> None

      Set stopping tolerance for changes in parameter value

      :param xtol: New tolerance value



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

      Solve the nonlinear system.

      Some solvers may support upper and lower bounds; pass an empty vector
      for no bounds, or a NaN entry for no bounds on a given variable.

      :param x: The initial guess.
      :param lb: Lower bounds on parameters.
      :param ub: Upper bounds on parameters.

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



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

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


   Status of the latest nonlinear solver


   .. py:attribute:: CONVERGED
      :type:  ClassVar[NonlinearSolverStatus]


   .. py:attribute:: DID_NOT_CONVERGE
      :type:  ClassVar[NonlinearSolverStatus]


   .. py:attribute:: FAILED
      :type:  ClassVar[NonlinearSolverStatus]


   .. py:attribute:: NOT_RUN_YET
      :type:  ClassVar[NonlinearSolverStatus]


.. py:class:: ParentBodyAttachmentParams

   Base class for attachment between a parent and child body.

   One of these classes will be used on every *BodyParams to indicate how
   it should be connected to its parent.


.. py:class:: ParentPhysicalBodyAttachmentParams(inb_to_joint_transform: Karana.Math.HomTran)

   Bases: :py:obj:`ParentBodyAttachmentParams`


   ParentBodyAttachement for a PhysicalBody.


   .. py:attribute:: __hash__
      :type:  ClassVar[None]
      :value: None



   .. py:method:: create(inb_to_joint_transform: Karana.Math.HomTran) -> ParentPhysicalBodyAttachmentParams
      :staticmethod:


      Create a new instance of ParentPhysicalBodyAttachmentParams.

      :param inb_to_joint_transform: The inboard body to joint transform for
                                     the body.

      :returns: The new instance of ParentPhysicalBodyAttachmentParams.



   .. py:method:: __eq__(other: ParentBodyAttachmentParams) -> bool

      Equality operator.

      :param other: The other parameter to compare against.

      :returns: true if the two ParentPhysicalBodyAttachmentParams have the same
                parameters; false otherwise.



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


   .. py:method:: __repr__()


   .. py:method:: __setstate__(arg0: Karana.Math.HomTran) -> None


   .. py:property:: inb_to_joint_transform
      :type: Karana.Math.HomTran


      The inboard body to joint transform


.. 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() -> Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]

      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: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec]) -> 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, params: Karana.Dynamics._params.PhysicalBodyParams) -> 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 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, params: Karana.Dynamics._params.PhysicalBodyParams) -> 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 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: Karana.Math.Ktyping.Vec3 | Karana.Math.Ktyping.Acceleration[Karana.Math.Ktyping.Vec3], 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:: addSceneFileObjectSpec(new_obj_spec: Karana.Scene.SceneFileObjectSpec) -> None

      Add a SceneFileObject description to the body to be realized whenever
      a ProxyScene is available.

      The new scene file object spec's name must not conflict with the name
      of an existing scene file object spec of scene file object for the
      body.

      :param scene_file_spec: The SceneFileObject description



   .. 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:: attachTo(new_parent: PhysicalBody, hinge_type: HingeType = HingeType.FULL6DOF) -> PhysicalHinge

      Reattach the body to the specified parent PhysicalBody

      Attach this PhysicalBody to the new parent PhysicalBody body via a
      hinge of the specified type.

      If this body is already attached to a body then it is detached from
      the current parent before attaching to the new parent.  If the new
      hinge type is a 6-dof hinge, then the inertial pose, spatial velocity
      and spatial acceleration of the body are fully preserved after
      reattachment by appropriately initializing the coordinates for the new
      hinge. For a new 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

      :returns: the new hinge between the bodies



   .. 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:: convexifyBody(threshold: float = 0.05, mcts_iterations: int = 50) -> None

      Convexify and replace all the non-convex scene part specs for the body.

          Parameters
          ----------
          threshold : float
              Convexification threshold parameter
          mcts_iterations : int
              Convexification iterations parameter




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

      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 and return the new hinge. No changes are made if the body
      already has a 6 dof hinge.

      See :ref:`mbody_config_changes_sec` section for information.

      :returns: the new 6 dof hinge for the detached body



   .. 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() -> Karana.Math.Ktyping.Acceleration[Karana.Math.Ktyping.Vec3]

      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:: getParams() -> Karana.Dynamics._params.PhysicalBodyParams

      Get the PhysicalBody parameters

      :returns: The parameters for this PhysicalBody.



   .. py:method:: getSceneFileObject(arg0: str) -> Karana.Scene.ProxySceneFileObject

      Return the SceneFileObject with the specified name

      See :ref:`proxyscene_sec` section for proxy scene related discussion.

      :param nm: the name of the scene file object

      :returns: The scene file object with given name, or nullptr if none found



   .. py:method:: getSceneFileObjectSpecs() -> list[Karana.Scene.SceneFileObjectSpec]

      Return a list of copies of SceneFileObjectSpecs. Do not modify these
      directly; use replaceSceneFileObjectSpec instead.

      See :ref:`proxyscene_sec` section for proxy scene related discussion.

      :returns: The list of scene file object specs



   .. py:method:: getSceneFileObjects() -> list[Karana.Scene.ProxySceneFileObject]

      Return a list of SceneFileObjects created from
      Karana::Scene::SceneFileObjectSpec values

      See :ref:`proxyscene_sec` section for proxy scene related discussion.

      :returns: The list of scene file objects



   .. 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:: makeIntoBaseBody() -> 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:: 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:: pruneChildren(skip_deformed: bool = True) -> int

      Merge each immediate rigid child attached by a locked hinge into a
      parent body.

      For every immediate child whose parent hinge has
      Karana::Dynamics::HingeType::LOCKED, this function:

      1. expresses the child's spatial inertia about the parent frame and
         adds it to the
      parent;
      2. transfers the child's body nodes to the parent without changing
         their identity or
      poses; and
      3. reparents the child's immediate children to the parent, preserving
         their hinge type, hinge parameters, generalized state, and hinge
         attachment locations.

      Only children that are immediate children when the function begins are
      considered. Therefore, a locked grandchild promoted during this call
      is not also merged during the same call.

      :param skip_deformable: If true, skip pruning any children bodies that
                              are deformable

      :returns: Number of immediate locked child bodies merged into ``parent.``

      :raises std::invalid_argument: If ``parent`` is the multibody virtual root
          or if an immediate child is not a rigid
          PhysicalBody.

      .. note::

         Because merged child bodies are discarded, callers must release
         owning pointers to those body objects before calling this
         function. References to transferred nodes may be kept.



   .. py:method:: relocateBodyFrame(arg0: Karana.Math.HomTran) -> None

      Change the location of the body frame for the body

      This method moves the body frame to a new location and updates all
      other transforms to be consistent with the new location. The mass
      properties are updates as well for the new location.

      :param body_to_joint_transform: The body to joint transform for the new
                                      body frame location



   .. 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:: removeSceneFileObjectSpec(spec_name: str) -> None

      Remove a scene file object description from the body *and* all
      associated scene file objects in the ProxyScene, if one is available.

      Note that this will also remove the scene file object 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:: 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:: replaceSceneFileObjectSpec(new_obj_spec: Karana.Scene.SceneFileObjectSpec) -> None

      Replace a scene file object spec by name

      This allows you to edit scene file object specs before any scenes have
      been constructed

      :param new_obj_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 file object already exists with
          that name, or if no matching spec exists.



   .. 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: Karana.Math.Ktyping.Vec3 | Karana.Math.Ktyping.Acceleration[Karana.Math.Ktyping.Vec3], 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(params: Karana.Dynamics._params.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 spatial_inertia: the input spatial inertia
      :param ref_frame: the reference frame for the input spatial inertia



   .. 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:: PhysicalBodyVars

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


   


   .. py:property:: local_gravity_accel
      :type: Karana.Core.Var[Karana.Math.Ktyping.Acceleration[Karana.Math.Ktyping.Vec3]]


      The local frame gravitational acceleration


   .. py:property:: mass
      :type: Karana.Core.Var[Karana.Math.Ktyping.Mass[float]]


      The mass of the PhysicalBody.


   .. py:property:: physical_parent
      :type: Karana.Core.Var[str]


      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:: getParams() -> Karana.Dynamics.SOADyn_types.PhysicalHingeParams

      Get the PhysicalHinge parameters

      :returns: The parameters for this PhysicalHinge.



   .. 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`


   


   .. 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:: getParams() -> Karana.Dynamics.SOADyn_types.PhysicalSubhingeParams

      Get the parameters for this subhinge.

      :returns: The parameters to set for this subhinge.



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


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

      Return the parent hinge for the subhinge

      :returns: the PhysicalHinge parent hinge



   .. py:method:: setParams(arg0: Karana.Dynamics.SOADyn_types.PhysicalSubhingeParams) -> None

      Set the parameters for this subhinge.

      :param params: The parameters to set for this subhinge.



.. py:class:: PhysicalSubhingeVars

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


   The Vars for the PhysicalSubhinge class.


   .. py:property:: Q
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      The Q coordinates


   .. py:property:: Qdot
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      The Qdot coordinates


   .. py:property:: T
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      The T coordinates


   .. py:property:: U
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      The U coordinates


   .. py:property:: Udot
      :type: Karana.Core.Var[Karana.Math.Ktyping.Vec]


      The Udot coordinates


.. py:class:: PhysicalSubhinge_T_0_0

   Bases: :py:obj:`PhysicalSubhinge`


   


.. py:class:: PhysicalSubhinge_T_1_1

   Bases: :py:obj:`PhysicalSubhinge`


   


.. py:class:: PhysicalSubhinge_T_3_3

   Bases: :py:obj:`PhysicalSubhinge`


   


.. py:class:: PhysicalSubhinge_T_4_3

   Bases: :py:obj:`PhysicalSubhinge`


   


.. py:class:: PinSubhinge

   Bases: :py:obj:`Physical1DofSubhinge`


   


   .. py:method:: accumT(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]) -> bool
                  accumT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Torque[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: getJointLimits() -> Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec]

      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:: getQ() -> Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec]

      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() -> Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]

      Return the Qdot rate coordinates

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

      :returns: Array of values.



   .. py:method:: getRangeLimits() -> Karana.Math.Ktyping.Angle[Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]]

      Return the range limits matrix for this subhinge

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :returns: the range limits matrix



   .. py:method:: getT() -> Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]

      Return the T generalized forces

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

      :returns: Array of values.



   .. py:method:: getU() -> Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]

      Return the U velocity coordinates

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

      :returns: Array of values.



   .. py:method:: getUdot() -> Karana.Math.Ktyping.AngularAcceleration[Karana.Math.Ktyping.Vec]

      Return the Udot acceleration coordinates

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

      :returns: Array of values.



   .. py:method:: setJointLimits(limits: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec]) -> 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:: setQ(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec]) -> bool
                  setQ(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Angle[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setRangeLimits(limits: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec], offset: SupportsInt | SupportsIndex) -> None

      Set the range limits matrix for a subhinge Q component

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :param limits: the lower/upper range limits
      :param offset: the offset of the Q coordinate that this applies to e.g.,
                     0 means these limits are for the first coordinate of the
                     subhinge



   .. py:method:: setT(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]) -> bool
                  setT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Torque[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setU(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]) -> bool
                  setU(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.AngularVelocity[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setUdot(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.AngularAcceleration[Karana.Math.Ktyping.Vec]) -> bool
                  setUdot(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.AngularAcceleration[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



.. 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:: addDependency(parent: str, child: str) -> None
                  addDependency(parent: SupportsInt | SupportsIndex, child: SupportsInt | SupportsIndex) -> None

      Add a dependency to the the execution graph.
      :param parent: The index of the callback that must finish first.
      :type parent: int
      :param child: The index of the callback that waits for the parent.
      :type child: int



   .. 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:: getDependencies(index: SupportsInt | SupportsIndex) -> list[int]
                  getDependencies(name: str) -> list[int]

      Remove all dependencies from the given callback.

      The dependencies are the parent edges in the DAG that this callback depends on before it can execute.

      :param name: The name of the callback to get dependencies for.
      :type name: str



   .. py:method:: getDependents(index: SupportsInt | SupportsIndex) -> list[int]
                  getDependents(name: str) -> list[int]

      Remove all dependents from the given callback.

      The dependents are the children in the DAG that depend on this callback completing before they can run.

      :param name: The name of the callback to get dependents for.
      :type name: str



   .. 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
                  insertAfter(index: SupportsInt | SupportsIndex, 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 index: The index to insert this item after.
      :type index: int
      :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
                  insertBefore(index: SupportsInt | SupportsIndex, 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 index: The index to insert this item before.
      :type index: int
      :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:: removeAllDependencies() -> None
                  removeAllDependencies(index: SupportsInt | SupportsIndex) -> None
                  removeAllDependencies(name: str) -> None

      Remove all dependencies from the given callback.

      The dependencies are the parent edges in the DAG that this callback depends on before it can execute.

      :param name: The index of the callback to remove all dependencies from.
      :type name: str



   .. py:method:: removeAllDependents(index: SupportsInt | SupportsIndex) -> None
                  removeAllDependents(name: str) -> None

      Remove all dependents from the given callback.

      The dependents are the children edges in the DAG that depend on this callback executing before they can execute.

      :param name: The index of the callback to remove all dependents from.
      :type name: str



   .. py:method:: removeDependency(parent: str, child: str) -> None
                  removeDependency(parent: SupportsInt | SupportsIndex, child: SupportsInt | SupportsIndex) -> None

      Remove a dependency from the the execution graph.
      :param parent: The index of the callback that must finish first.
      :type parent: int
      :param child: The index of the callback that waits for the parent.
      :type child: int



   .. py:method:: runInParallel(indices: collections.abc.Sequence[SupportsInt | SupportsIndex]) -> None
                  runInParallel(names: collections.abc.Sequence[str]) -> None

      This runs the given callbacks in parallel.

      This modifies the DAG as follows:
      1. A "base" callback is found. This is the callback with the shallowest depth in the DAG. If more than one callback has the same depth, then the callback with
         the lowest index is used.
      2. All the callbacks associated with the given indices are modified to have the same parents/children as the base.
      3. The callbacks whose edges were modified have their previous parents tied to their previous children.

      :param names: The names of the callbacks to run in parallel.
      :type names: list[str]



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

      Get the number of callbacks registered to the CallbackRegistry.

      :returns: Number of callbacks registered in the CallbackRegistry.
      :rtype: int



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

      Perform transitive reduction on the callbacks DAG.
      This preserves the reachability between all callbacks in the DAG while removing all redundant, transitive edges



.. 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; throws an error if none exists.

      :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:: accumT(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]) -> bool
                  accumT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Torque[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: getJointLimits() -> Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec]

      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:: getPitch() -> Karana.Math.Ktyping.Length[float]

      Return the pitch value for the subhinge

      The pitch is defined as meters of translation/radian.

      :returns: the pitch value



   .. py:method:: getQ() -> Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec]

      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() -> Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]

      Return the Qdot rate coordinates

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

      :returns: Array of values.



   .. py:method:: getRangeLimits() -> Karana.Math.Ktyping.Angle[Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]]

      Return the range limits matrix for this subhinge

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :returns: the range limits matrix



   .. py:method:: getT() -> Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]

      Return the T generalized forces

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

      :returns: Array of values.



   .. py:method:: getU() -> Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]

      Return the U velocity coordinates

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

      :returns: Array of values.



   .. py:method:: getUdot() -> Karana.Math.Ktyping.AngularAcceleration[Karana.Math.Ktyping.Vec]

      Return the Udot acceleration coordinates

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

      :returns: Array of values.



   .. py:method:: setJointLimits(limits: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec]) -> 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:: setPitch(pitch: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Length[float]) -> None

      Set the pitch value for the subhinge

      The pitch is defined as meters of translation/radian.

      :param pitch: the pitch value



   .. py:method:: setQ(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec]) -> bool
                  setQ(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Angle[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setRangeLimits(limits: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Angle[Karana.Math.Ktyping.Vec], offset: SupportsInt | SupportsIndex) -> None

      Set the range limits matrix for a subhinge Q component

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :param limits: the lower/upper range limits
      :param offset: the offset of the Q coordinate that this applies to e.g.,
                     0 means these limits are for the first coordinate of the
                     subhinge



   .. py:method:: setT(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]) -> bool
                  setT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Torque[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setU(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]) -> bool
                  setU(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.AngularVelocity[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setUdot(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.AngularAcceleration[Karana.Math.Ktyping.Vec]) -> bool
                  setUdot(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.AngularAcceleration[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



.. py:class:: SpOptions

   Bases: :py:obj:`MMOptions`


   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:method:: accumT(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]) -> bool
                  accumT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Torque[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. 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:: getQdot() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the Qdot rate coordinates as an array

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

      :returns: Array of values



   .. py:method:: getT() -> Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]

      Return the T generalized forces

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

      :returns: Array of values.



   .. py:method:: getU() -> Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]

      Return the U velocity coordinates

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

      :returns: Array of values.



   .. py:method:: getUdot() -> Karana.Math.Ktyping.AngularAcceleration[Karana.Math.Ktyping.Vec]

      Return the Udot acceleration coordinates

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

      :returns: Array of values.



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setT(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]) -> bool
                  setT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Torque[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setU(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]) -> bool
                  setU(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.AngularVelocity[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setUdot(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.AngularAcceleration[Karana.Math.Ktyping.Vec]) -> bool
                  setUdot(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.AngularAcceleration[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



.. 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:: accumT(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]) -> bool
                  accumT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Torque[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. 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:: 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:: getQdot() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the Qdot rate coordinates as an array

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

      :returns: Array of values



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

      Return the range limits matrix for this subhinge

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :returns: the range limits matrix



   .. py:method:: getT() -> Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]

      Return the T generalized forces

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

      :returns: Array of values.



   .. py:method:: getU() -> Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]

      Return the U velocity coordinates

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

      :returns: Array of values.



   .. py:method:: getUdot() -> Karana.Math.Ktyping.AngularAcceleration[Karana.Math.Ktyping.Vec]

      Return the Udot acceleration coordinates

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

      :returns: Array of values.



   .. 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:method:: setQ(val: Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]) -> bool
                  setQ(fill_value: SupportsFloat | SupportsIndex) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setRangeLimits(limits: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], offset: SupportsInt | SupportsIndex) -> None
                  setRangeLimits(limits: Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], offset: SupportsInt | SupportsIndex) -> None

      Set the range limits matrix for a subhinge Q component

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :param limits: the lower/upper range limits
      :param offset: the offset of the Q coordinate that this applies to e.g.,
                     0 means these limits are for the first coordinate of the
                     subhinge



   .. py:method:: setT(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.Torque[Karana.Math.Ktyping.Vec]) -> bool
                  setT(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.Torque[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setU(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.AngularVelocity[Karana.Math.Ktyping.Vec]) -> bool
                  setU(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.AngularVelocity[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setUdot(val: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.AngularAcceleration[Karana.Math.Ktyping.Vec]) -> bool
                  setUdot(fill_value: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.AngularAcceleration[float]) -> bool

      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.

      :returns: true if the new value was legal and accepted, false otherwise



.. 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:: setMaxHopSize(max_hop_size: SupportsFloat | SupportsIndex | numpy.timedelta64) -> None

      Register a no-op TimedEvent whose period is the max_hop_size.

      This effectively sets the max_hop_size by ensuring there is a boundary
      in the timeline at an interval of max_hop_size.

      :param max_hop_size: The period to use for the TimedEvent.



   .. 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:: invalid_derivatives
      :type: int



   .. 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.Var[float]


      the advance to time


   .. py:property:: counter_derivs
      :type: Karana.Core.Var[int]


      number of derivative calls


   .. py:property:: counter_hops
      :type: Karana.Core.Var[int]


      number of hops


   .. py:property:: counter_steps
      :type: Karana.Core.Var[int]


      number of integration steps


   .. py:property:: counter_zero_crossings
      :type: Karana.Core.Var[int]


      number of zero crossings


   .. py:property:: integrator_type
      :type: Karana.Core.Var[str]


      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 onode 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`


   


   .. 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

      :returns: the spatial acceleration error



   .. py:method:: articulateCoordinate(coord: tuple[CoordBase, SupportsInt | SupportsIndex], disable_ik: bool = False, rangeQ: tuple[SupportsFloat | SupportsIndex, SupportsFloat | SupportsIndex] = (-0.5, 0.5), dQ: SupportsFloat | SupportsIndex = 0.01, pause: SupportsFloat | SupportsIndex = 0.01) -> None

      Sequentially articulate a coordinate 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 coord: Coordinate to articulate
      :param disable_ik: if true, constraints solver is not invoked during
                         articulation
      :param range_q: is the min/max coordinate excursion range
      :param d_q: is the coordinate step size
      :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:: cloneSubGraph(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:: constraintAggregationSubGraph(arg0: str, arg1: BilateralConstraintBase, arg2: bool) -> SubGraph

      Create and return an aggregation SubGraph for a bilateral constraint

      For a bilateral constraint, 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 constraint: The constraint to compute the aggregation subgraph for
      :param with_velocity_constraints: If true, also use the non-hinge convel
                                        constraints when identifying the
                                        aggregation SubGraph

      :returns: the aggregation SubGraph



   .. 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:: getBaumgarteDamping() -> float

      Get damping parameter for Baumgarte stabilization.

      :returns: Damping parameter



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

      Check if Baumgarte stabilization is enabled for this SubGraph.

      :returns: Whether Baumgarte stabilization is enabled



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

      Get stiffness parameter for Baumgarte stabilization.

      :returns: Stiffness parameter



   .. 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.

      This method will error out if there are multiple bilateral constraints
      enabled with the specified name. It is meant to be used when there are
      no name conflicts among the enabled 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:: hingeAggregationSubGraph(arg0: str, arg1, arg2: bool) -> SubGraph

      Create and return an aggregation SubGraph for a hinge

      For a hinge, the aggregation sub-graph is the smallest sub-graph that
      contains the constrained bodies in any loops containing the hinge, and
      the subgraph 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 hge: The hinge to compute the aggregation subgraph for
      :param with_velocity_constraints: If true, also use the non-hinge convel
                                        constraints when identifying the
                                        aggregation SubGraph

      :returns: the aggregation SubGraph



   .. py:method:: isEnabledConstraint(arg0: BilateralConstraintBase) -> bool

      Check whether a constraint is enabled in this subgraph

      :param bcb: the constraint

      :returns: true if the constraint is enabled in this 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:: setBaumgarteDamping(damping: SupportsFloat | SupportsIndex) -> None

      Set damping parameter for Baumgarte stabilization.

      Note that you will also need to call setBaumgarteEnabled before this
      has any effect.

      :param damping: Damping parameter



   .. py:method:: setBaumgarteEnabled(enabled: bool) -> None

      Set whether Baumgarte stabilization is enabled on this SubGraph.

      Note that you will also need to call
      setBaumgarteStiffness/setBaumgarteDamping before this can be used.

      :param enabled: Whether to use Baumgarte stabilization during forward
                      dynamics



   .. py:method:: setBaumgarteStiffness(stiffness: SupportsFloat | SupportsIndex) -> None

      Set stiffness parameter for Baumgarte stabilization.

      Note that you will also need to call setBaumgarteEnabled before this
      has any effect.

      :param stiffness: Stiffness parameter



   .. py:method:: setupConstraintEmbedding(indep_coords_U: collections.abc.Sequence[tuple[CoordBase, SupportsInt | SupportsIndex]] = [], indep_coords_Q: collections.abc.Sequence[tuple[CoordBase, SupportsInt | SupportsIndex]] = []) -> 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.

      :param indep_coords_U: list of Coordinates to use as independent U coords
      :param indep_coords_Q: list of Coordinates to use as independent Q coords



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

      Create a SubGraphDS from this SubGraph model.

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



   .. 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 | int, 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 | int, 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.Var[int]


      The cutjoints nQ


   .. py:property:: cutjoints_n_U
      :type: Karana.Core.Var[int]


      The cutjoints nU


   .. py:property:: pose_error_norm
      :type: Karana.Core.Var[float]


      pose error


   .. py:property:: pose_gradient_rank
      :type: Karana.Core.Var[int]


      pose gradient matrix rank


   .. py:property:: pose_gradient_size
      :type: Karana.Core.Var[Karana.Math.Ktyping.VecInt]


      pose gradient matrix size


   .. py:property:: vel_error_norm
      :type: Karana.Core.Var[float]


      vel error


   .. py:property:: vel_jacobian_rank
      :type: Karana.Core.Var[int]


      velocity Jacobian matrix rank


   .. py:property:: vel_jacobian_size
      :type: Karana.Core.Var[Karana.Math.Ktyping.VecInt]


      velocity Jacobian matrix size


.. 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`


   


   .. 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.3

      :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: tuple[SupportsFloat | SupportsIndex, SupportsFloat | SupportsIndex] = (-0.5, 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 min/max coordinate excursion range
      :param d_q: is the coordinate step size
      :param pause: time in seconds to sleep between articulation steps



   .. py:method:: articulateCoordinate(coord: tuple[CoordBase, SupportsInt | SupportsIndex], rangeQ: tuple[SupportsFloat | SupportsIndex, SupportsFloat | SupportsIndex] = (-0.5, 0.5), dQ: SupportsFloat | SupportsIndex = 0.01, pause: SupportsFloat | SupportsIndex = 0.01, callback: collections.abc.Callable[[], None] = None) -> None

      Sequentially articulate a coordinate for a CoordBase.

      This method can be used to articulate coordinates for physical
      subhinges, compound subhinges as well as modal coordinates for a flex
      body. With graphics on, this step can be used to examine and debug
      issues with the model.

      :param coord: the Coordinate to articulate
      :param range_q: is the min/max coordinate excursion range
      :param d_q: is the coordinate step size
      :param pause: time in seconds to sleep between articulation steps
      :param callback: 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:: cloneSubTree(name: str) -> SubTree

      This method returns a clone of the SubTree as a child subtree

      :param name: The name for the new SubTree

      :returns: A new SubTree instance



   .. 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 Coordinate with 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 subtree.

      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:: evalForwardDynamicsNoCaches() -> None

      Evaluate tree forward dynamics without using ATBI data caches

      This method is work in progress. This is an alternative ATBI forward
      dynamics method that reduces the use of data caches during forward
      dynamics to improve performance.



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

      Evaluate tree forward dynamics without using ATBI data caches

      This method is work in progress. This is an alternative ATBI forward
      dynamics method that reduces the use of data caches during forward
      dynamics to improve performance.



   .. 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:: getLayoutBodyData() -> dict[int, SubTreeLayoutBodyData]

      Return the body layout data map

      :returns: the body layout data map



   .. 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:: getQdot() -> Annotated[numpy.typing.NDArray[numpy.float64], [m, 1]]

      Return the Qdot rate coordinates as an array

      :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:: pruneBodies() -> int

      Prune locked rigid bodies throughout a subtree, working from tips to
      bases.

      The traversal is post-order: descendants are processed before their
      parents. This ensures that a locked body can first absorb its own
      locked children before it is itself absorbed by its parent. Each
      subtree base body is processed, but is not merged into a parent
      outside the supplied subtree. The pruning is skipped if either the
      parent or the child body is deformable.

      :returns: Total number of locked child bodies merged throughout ``subtree.``

      :raises std::invalid_argument: If the subtree contains a non-PhysicalBody
          body.

      .. note::

         As with prune(), callers must release owning pointers to bodies
         that will be discarded. References to transferred nodes may remain
         live.



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

      Remove all stick parts for the subtree.

      A Karana::Scene::ProxyScene scene must be registered with the
      Multibody first.



   .. 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:: setLayoutBodyData(arg0: collections.abc.Mapping[SupportsInt | SupportsIndex, SubTreeLayoutBodyData]) -> None

      Set the body layout data map

      :param data: the body layout data map



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



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

      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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. 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:: toDS() -> Karana.Dynamics.SOADyn_types.SubTreeDS

      Create a SubTreeDS from this SubTree model.

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



   .. 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:method:: fromLayoutJSON(layout_json: pathlib.Path)

      Load the visjs graph layout data for the subtree from a JSON layout file.

      :param layout_json: The JSON layout file
      :type layout_json: Path



.. 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:: SubTreeLayoutBodyData(x: SupportsFloat | SupportsIndex = ..., y: SupportsFloat | SupportsIndex = ..., label: str = '', color: str = '')

   .. py:attribute:: color
      :type:  str


   .. py:attribute:: label
      :type:  str


   .. py:method:: __getstate__() -> dict


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


   .. py:method:: __setstate__(arg0: dict) -> None


   .. py:property:: x
      :type: float



   .. py:property:: y
      :type: float



.. 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.Var[list[str]]


      base bodies


   .. py:property:: children_subtrees
      :type: Karana.Core.Var[int]


      number of children subtrees


   .. py:property:: coord_sanitization_subhinges
      :type: Karana.Core.Var[list[str]]


      coord sanitization subhinges


   .. py:property:: enabled_algorithmically
      :type: Karana.Core.Var[bool]


      whether algorithmically enabled


   .. py:property:: has_compound_bodies
      :type: Karana.Core.Var[bool]


      whether has compound bodies


   .. py:property:: has_nested_compound_bodies
      :type: Karana.Core.Var[bool]


      whether has nested compound bodies


   .. py:property:: leaf_bodies
      :type: Karana.Core.Var[list[str]]


      leaf bodies


   .. py:property:: nQ
      :type: Karana.Core.Var[int]


      nQ


   .. py:property:: nU
      :type: Karana.Core.Var[int]


      nU


   .. py:property:: n_bodies
      :type: Karana.Core.Var[int]


      number of bodies


   .. py:property:: n_physical_bodies
      :type: Karana.Core.Var[int]


      number of physical bodies


   .. py:property:: parent_subtree
      :type: Karana.Core.Var[str]


      The parent subtree


   .. py:property:: physical_virtual_root
      :type: Karana.Core.Var[str]


      The physical virtual root body name


   .. py:property:: virtual_root
      :type: Karana.Core.Var[str]


      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:: getRangeLimits() -> Karana.Math.Ktyping.QuantityOrValue[Annotated[numpy.typing.NDArray[numpy.float64], [m, n]]]

      Return the range limits matrix for this subhinge

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :returns: the range limits matrix



   .. 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:: setRangeLimits(limits: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.QuantityOrValue[Karana.Math.Ktyping.Vec], offset: SupportsInt | SupportsIndex) -> None

      Set the range limits matrix for a subhinge Q component

      A NaN value indicates an undetermined limit, while infinite value
      implies that the limit is unbounded.

      :param limits: the lower/upper range limits
      :param offset: the offset of the Q coordinate that this applies to e.g.,
                     0 means these limits are for the first coordinate of the
                     subhinge



   .. 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:: SubhingeMask(*args, **kwds)

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


   Enum with values to classify the type of coordinate to mask


   .. py:attribute:: NONE
      :type:  ClassVar[SubhingeMask]


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


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


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


.. 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:: LOCKED_OFFSET
      :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:: addDependency(parent: str, child: str) -> None
                  addDependency(parent: SupportsInt | SupportsIndex, child: SupportsInt | SupportsIndex) -> None

      Add a dependency to the the execution graph.
      :param parent: The index of the callback that must finish first.
      :type parent: int
      :param child: The index of the callback that waits for the parent.
      :type child: int



   .. 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:: getDependencies(index: SupportsInt | SupportsIndex) -> list[int]
                  getDependencies(name: str) -> list[int]

      Remove all dependencies from the given callback.

      The dependencies are the parent edges in the DAG that this callback depends on before it can execute.

      :param name: The name of the callback to get dependencies for.
      :type name: str



   .. py:method:: getDependents(index: SupportsInt | SupportsIndex) -> list[int]
                  getDependents(name: str) -> list[int]

      Remove all dependents from the given callback.

      The dependents are the children in the DAG that depend on this callback completing before they can run.

      :param name: The name of the callback to get dependents for.
      :type name: str



   .. 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
                  insertAfter(index: SupportsInt | SupportsIndex, 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 index: The index to insert this item after.
      :type index: int
      :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
                  insertBefore(index: SupportsInt | SupportsIndex, 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 index: The index to insert this item before.
      :type index: int
      :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:: removeAllDependencies() -> None
                  removeAllDependencies(index: SupportsInt | SupportsIndex) -> None
                  removeAllDependencies(name: str) -> None

      Remove all dependencies from the given callback.

      The dependencies are the parent edges in the DAG that this callback depends on before it can execute.

      :param name: The index of the callback to remove all dependencies from.
      :type name: str



   .. py:method:: removeAllDependents(index: SupportsInt | SupportsIndex) -> None
                  removeAllDependents(name: str) -> None

      Remove all dependents from the given callback.

      The dependents are the children edges in the DAG that depend on this callback executing before they can execute.

      :param name: The index of the callback to remove all dependents from.
      :type name: str



   .. py:method:: removeDependency(parent: str, child: str) -> None
                  removeDependency(parent: SupportsInt | SupportsIndex, child: SupportsInt | SupportsIndex) -> None

      Remove a dependency from the the execution graph.
      :param parent: The index of the callback that must finish first.
      :type parent: int
      :param child: The index of the callback that waits for the parent.
      :type child: int



   .. py:method:: runInParallel(indices: collections.abc.Sequence[SupportsInt | SupportsIndex]) -> None
                  runInParallel(names: collections.abc.Sequence[str]) -> None

      This runs the given callbacks in parallel.

      This modifies the DAG as follows:
      1. A "base" callback is found. This is the callback with the shallowest depth in the DAG. If more than one callback has the same depth, then the callback with
         the lowest index is used.
      2. All the callbacks associated with the given indices are modified to have the same parents/children as the base.
      3. The callbacks whose edges were modified have their previous parents tied to their previous children.

      :param names: The names of the callbacks to run in parallel.
      :type names: list[str]



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

      Get the number of callbacks registered to the CallbackRegistry.

      :returns: Number of callbacks registered in the CallbackRegistry.
      :rtype: int



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

      Perform transitive reduction on the callbacks DAG.
      This preserves the reachability between all callbacks in the DAG while removing all redundant, transitive edges



.. 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:: addDependency(parent: str, child: str) -> None
                  addDependency(parent: SupportsInt | SupportsIndex, child: SupportsInt | SupportsIndex) -> None

      Add a dependency to the the execution graph.
      :param parent: The index of the callback that must finish first.
      :type parent: int
      :param child: The index of the callback that waits for the parent.
      :type child: int



   .. 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:: getDependencies(index: SupportsInt | SupportsIndex) -> list[int]
                  getDependencies(name: str) -> list[int]

      Remove all dependencies from the given callback.

      The dependencies are the parent edges in the DAG that this callback depends on before it can execute.

      :param name: The name of the callback to get dependencies for.
      :type name: str



   .. py:method:: getDependents(index: SupportsInt | SupportsIndex) -> list[int]
                  getDependents(name: str) -> list[int]

      Remove all dependents from the given callback.

      The dependents are the children in the DAG that depend on this callback completing before they can run.

      :param name: The name of the callback to get dependents for.
      :type name: str



   .. py:method:: insertAfter(item: str, name: str, fn: collections.abc.Callable[[Annotated[numpy.typing.ArrayLike, numpy.float64, [m, 1]], bool], bool]) -> None
                  insertAfter(index: SupportsInt | SupportsIndex, 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 index: The index to insert this item after.
      :type index: int
      :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
                  insertBefore(index: SupportsInt | SupportsIndex, 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 index: The index to insert this item before.
      :type index: int
      :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:: removeAllDependencies() -> None
                  removeAllDependencies(index: SupportsInt | SupportsIndex) -> None
                  removeAllDependencies(name: str) -> None

      Remove all dependencies from the given callback.

      The dependencies are the parent edges in the DAG that this callback depends on before it can execute.

      :param name: The index of the callback to remove all dependencies from.
      :type name: str



   .. py:method:: removeAllDependents(index: SupportsInt | SupportsIndex) -> None
                  removeAllDependents(name: str) -> None

      Remove all dependents from the given callback.

      The dependents are the children edges in the DAG that depend on this callback executing before they can execute.

      :param name: The index of the callback to remove all dependents from.
      :type name: str



   .. py:method:: removeDependency(parent: str, child: str) -> None
                  removeDependency(parent: SupportsInt | SupportsIndex, child: SupportsInt | SupportsIndex) -> None

      Remove a dependency from the the execution graph.
      :param parent: The index of the callback that must finish first.
      :type parent: int
      :param child: The index of the callback that waits for the parent.
      :type child: int



   .. py:method:: runInParallel(indices: collections.abc.Sequence[SupportsInt | SupportsIndex]) -> None
                  runInParallel(names: collections.abc.Sequence[str]) -> None

      This runs the given callbacks in parallel.

      This modifies the DAG as follows:
      1. A "base" callback is found. This is the callback with the shallowest depth in the DAG. If more than one callback has the same depth, then the callback with
         the lowest index is used.
      2. All the callbacks associated with the given indices are modified to have the same parents/children as the base.
      3. The callbacks whose edges were modified have their previous parents tied to their previous children.

      :param names: The names of the callbacks to run in parallel.
      :type names: list[str]



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

      Get the number of callbacks registered to the CallbackRegistry.

      :returns: Number of callbacks registered in the CallbackRegistry.
      :rtype: int



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

      Perform transitive reduction on the callbacks DAG.
      This preserves the reachability between all callbacks in the DAG while removing all redundant, transitive edges



.. py:function:: createIODataPool(arg0: SubTree) -> IODataPool

   Create a IODataPool instance for a subgraph

   :param sg: The SubGraph to create a IODataPool for.

   :returns: The newly created IODataPool instance.


.. py:function:: createModelPool(arg0: SubTree) -> ModelPool

   Create a ModelPool instance for a subgraph

   :param sg: The SubGraph to create a ModelPool for.

   :returns: The newly created ModelPool instance.


.. py:function:: treeForwardDynamicsPool(arg0: ModelPool, arg1: IODataPool) -> None

   Evaluate ModelPool based forward dynamics

   :param mpool: The ModelPool to evaluate.
   :param inputs: The inputs to evaluate the forward dynamics at.


.. py:class:: PhysicalBodyParams(/, **data: Any)

   Bases: :py:obj:`Karana.KUtils.DataStruct.DataStruct`, :py:obj:`Karana.KUtils.DataStruct.NestedBaseMixin`


   Parameters used to configure a PhysicalBody.

   :param spatial_inertia: Spatial inertia assigned to the body.
   :type spatial_inertia: Karana.Math.SpatialInertia
   :param body_to_joint_transform: Transform from the body frame to its hinge joint frame.
   :type body_to_joint_transform: Karana.Math.HomTran
   :param hinge_params: Parameters for the body's physical hinge.
   :type hinge_params: PhysicalHingeParams
   :param parent_body_attachment_params: Parameters for attaching this body to its parent.
   :type parent_body_attachment_params: ParentBodyAttachmentParams
   :param scene_part_specs: Scene-part specifications attached to the body.
   :type scene_part_specs: list[ScenePartSpec]
   :param scene_file_object_specs: Scene-file-object specifications attached to the body.
   :type scene_file_object_specs: list[SceneFileObjectSpec]


   .. py:attribute:: spatial_inertia
      :type:  Karana.Math.SpatialInertia


   .. py:attribute:: body_to_joint_transform
      :type:  Karana.Math.HomTran


   .. py:attribute:: hinge_params
      :type:  PhysicalHingeParams


   .. py:attribute:: parent_body_attachment_params
      :type:  Karana.Dynamics.ParentBodyAttachmentParams


   .. py:attribute:: scene_part_specs
      :type:  list[Karana.Scene.ScenePartSpec]


   .. py:attribute:: scene_file_object_specs
      :type:  list[Karana.Scene.SceneFileObjectSpec]


   .. py:method:: createDefault() -> Self
      :classmethod:


      Create a version of PhysicalBodyParams with all values filled in.

      This is useful for testing or when you just need a body for a simple demo.

      :returns: An instance of PhysicalBodyParams with all values filled in.
      :rtype: Self



.. py:class:: PhysicalSubhingeParams(/, **data: Any)

   Bases: :py:obj:`Karana.KUtils.DataStruct.DataStruct`, :py:obj:`Karana.KUtils.DataStruct.NestedBaseMixin`, :py:obj:`Karana.KUtils.DataStruct.IdMixin`\ [\ :py:obj:`Karana.Dynamics.PhysicalSubhinge`\ ]


   Base class for all subhinges.

   :param subhinge_type: The subhinge type associated with the subhinge.
   :type subhinge_type: SubhingeType


   .. py:attribute:: subhinge_type
      :type:  Karana.Dynamics.SubhingeType


   .. py:method:: fromSubhinge(sh: SubhingePyType) -> PhysicalSubhingeParams
      :classmethod:


      Create an instance of PhysicalSubhingeParams from the provided Subhinge.

      :param sh: The Subhinge used to create the PhysicalSubhingeParams.
      :type sh: SubhingeType

      :returns: A PhysicalSubhingeParams that represents the provided Subhinge.
      :rtype: Self



   .. py:method:: setSubhingeValues(sh: SubhingePyType) -> None
      :abstractmethod:


      Set the subhinge values for the provided subhinge.



.. py:class:: PhysicalHingeParams(/, **data: Any)

   Bases: :py:obj:`Karana.KUtils.DataStruct.DataStruct`


   Base class for all hinge types.

   Hinges that have 0 axes associated with them, e.g., BALL,
   use this DataStruct. Classes with more axes (or information) will use derived classes.

   :param hinge_type: The hinge type associated with the hinge.
   :type hinge_type: HingeType
   :param subhinge_params: A list of subhinge params that make up this hinge.
   :type subhinge_params: list[PhysicalSubhingeParams]


   .. py:attribute:: hinge_type
      :type:  Karana.Dynamics.HingeType


   .. py:attribute:: subhinge_params
      :type:  list[pydantic.SerializeAsAny[PhysicalSubhingeParams]]


   .. py:method:: toHinge(parent_bd: Karana.Dynamics.PhysicalBody, child_bd: Karana.Dynamics.PhysicalBody) -> Karana.Dynamics.PhysicalHinge

      Create a Hinge between the provided bodies.

      :param parent_bd: The parent body for the hinge.
      :type parent_bd: PhysicalBody
      :param child_bd: The child body for the hinge.
      :type child_bd: PhysicalBody

      :returns: The hinge that was created between the two provided bodies.
      :rtype: PhysicalHinge



   .. py:method:: fromHinge(hge: Karana.Dynamics.FramePairHinge, htype: Karana.Dynamics.HingeType) -> Self
      :classmethod:


      Create a PhysicalHingeParams from the provided hinge.

      :param hge: The FramePairHinge used to create the PhysicalHingeParams.
      :type hge: FramePairHinge
      :param htype: The hinge type associated with the FramePairHinge.
      :type htype: HingeType

      :returns: A PhysicalHingeParams that represents the provided FramePairHinge.
      :rtype: Self



.. py:class:: PinSubhingeParams(*, unit_axis: Karana.Math.Ktyping.Vec3, joint_limits: Karana.Math.Ktyping.Angle[Annotated[Karana.Math.Ktyping.Vec, npSizeCheck((2, ))]] | Annotated[Karana.Math.Ktyping.Vec, npSizeCheck((2, ))] = np.array([km.notReadyNaN, km.notReadyNaN]) * ureg.rad, prescribed: bool = False, range_limits: Karana.Math.Ktyping.Angle[Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((1, 2))]] | Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((1, 2))] = np.full((1, 2), km.notReadyNaN) * ureg.rad)

   Bases: :py:obj:`PhysicalSubhingeParams`


   PinSubhinge DataStruct.

   :param unit_axis: Unit axis for the pin subhinge.
   :type unit_axis: Vec3
   :param joint_limits: The lower and upper bound for the joint limit.
   :type joint_limits: Annotated[Vec, npSizeCheck((2,))]
   :param prescribed: Determines if the subhinge is prescribed or not.
   :type prescribed: bool
   :param range_limits: The lower and upper bound for the Q coordinate range limits.
   :type range_limits: Annotated[Vec, npSizeCheck((1,2))]


   .. py:attribute:: subhinge_type
      :type:  Karana.Dynamics.SubhingeType


   .. py:attribute:: unit_axis
      :type:  Annotated[Karana.Math.Ktyping.Vec3, normCheck(1.0)]


   .. py:attribute:: joint_limits
      :type:  Karana.Math.Ktyping.Angle[Annotated[Karana.Math.Ktyping.Vec, npSizeCheck((2, ))]]


   .. py:attribute:: prescribed
      :type:  bool
      :value: False



   .. py:attribute:: range_limits
      :type:  Karana.Math.Ktyping.Angle[Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((1, 2))]]


   .. py:method:: fromSubhinge(sh: Karana.Dynamics.PinSubhinge) -> Self
      :classmethod:


      Create a PinSubhingeParams from a PinSubhinge.



   .. py:method:: setSubhingeValues(sh: Karana.Dynamics.PinSubhinge) -> None

      Set the values of a PinSubhinge.



.. py:class:: LinearSubhingeParams(*, unit_axis: Karana.Math.Ktyping.Vec3, joint_limits: Karana.Math.Ktyping.Length[Annotated[Karana.Math.Ktyping.Vec, npSizeCheck((2, ))]] | Annotated[Karana.Math.Ktyping.Vec, npSizeCheck((2, ))] = np.array([km.notReadyNaN, km.notReadyNaN]) * ureg.m, prescribed: bool = False, range_limits: Karana.Math.Ktyping.Length[Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((1, 2))]] | Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((1, 2))] = np.full((1, 2), km.notReadyNaN) * ureg.m)

   Bases: :py:obj:`PhysicalSubhingeParams`


   LinearSubhinge DataStruct.

   :param unit_axis: Unit axis for the pin subhinge.
   :type unit_axis: Vec3
   :param joint_limits: The lower and upper bound for the joint limit.
   :type joint_limits: Annotated[Vec, npSizeCheck((2,))]
   :param prescribed: Determines if the subhinge is prescribed or not.
   :type prescribed: bool
   :param range_limits: The lower and upper bound for the Q coordinate range limits.
   :type range_limits: Annotated[Vec, npSizeCheck((1,2))]


   .. py:attribute:: subhinge_type
      :type:  Karana.Dynamics.SubhingeType


   .. py:attribute:: unit_axis
      :type:  Annotated[Karana.Math.Ktyping.Vec3, normCheck(1.0)]


   .. py:attribute:: joint_limits
      :type:  Karana.Math.Ktyping.Length[Annotated[Karana.Math.Ktyping.Vec, npSizeCheck((2, ))]]


   .. py:attribute:: prescribed
      :type:  bool
      :value: False



   .. py:attribute:: range_limits
      :type:  Karana.Math.Ktyping.Length[Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((1, 2))]]


   .. py:method:: fromSubhinge(sh: Karana.Dynamics.LinearSubhinge) -> Self
      :classmethod:


      Create a LinearSubhingeParams from a LinearSubhinge.



   .. py:method:: setSubhingeValues(sh: Karana.Dynamics.LinearSubhinge) -> None

      Set the values of a LinearSubhinge.



.. py:class:: SphericalSubhingeParams(/, **data: Any)

   Bases: :py:obj:`PhysicalSubhingeParams`


   SphericalSubhinge DataStruct.

   prescribed : bool
       Determines if the subhinge is prescribed or not.
   range_limits:  Annotated[Vec, npSizeCheck((3,2))]
       The lower and upper bound for the Q coordinate range limits.


   .. py:attribute:: subhinge_type
      :type:  Karana.Dynamics.SubhingeType


   .. py:attribute:: prescribed
      :type:  bool
      :value: False



   .. py:attribute:: range_limits
      :type:  Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((3, 2))]


   .. py:method:: fromSubhinge(sh: Karana.Dynamics.SphericalSubhinge) -> Self
      :classmethod:


      Create a SphericalSubhingeParams from a SphericalSubhinge.



   .. py:method:: setSubhingeValues(sh: Karana.Dynamics.SphericalSubhinge) -> None

      Set the values of a SphericalSubhinge.



.. py:class:: SphericalQuatSubhingeParams(/, **data: Any)

   Bases: :py:obj:`PhysicalSubhingeParams`


   SphericalQuatSubhinge DataStruct.

   prescribed : bool
       Determines if the subhinge is prescribed or not.
   range_limits:  Annotated[Vec, npSizeCheck((3,2))]
       The lower and upper bound for the Q coordinate range limits.


   .. py:attribute:: subhinge_type
      :type:  Karana.Dynamics.SubhingeType


   .. py:attribute:: prescribed
      :type:  bool
      :value: False



   .. py:attribute:: range_limits
      :type:  Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((4, 2))]


   .. py:method:: fromSubhinge(sh: Karana.Dynamics.SphericalQuatSubhinge) -> Self
      :classmethod:


      Create a SphericalQuatSubhingeParams from a SphericalQuatSubhinge.



   .. py:method:: setSubhingeValues(sh: Karana.Dynamics.SphericalQuatSubhinge) -> None

      Set the values of a SphericalQuatSubhinge.



.. py:class:: Linear3SubhingeParams(*, subhinge_type: Karana.Dynamics.SubhingeType = SubhingeType.LINEAR3, prescribed: bool = False, range_limits: Karana.Math.Ktyping.Length[Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((3, 2))]] | Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((3, 2))] = np.full((3, 2), km.notReadyNaN) * ureg.m)

   Bases: :py:obj:`PhysicalSubhingeParams`


   Linear3Subhinge DataStruct.

   :param prescribed: Determines if the subhinge is prescribed or not.
   :type prescribed: bool
   :param range_limits: The lower and upper bound for the Q coordinate range limits.
   :type range_limits: Annotated[Vec, npSizeCheck((3,2))]


   .. py:attribute:: subhinge_type
      :type:  Karana.Dynamics.SubhingeType


   .. py:attribute:: prescribed
      :type:  bool
      :value: False



   .. py:attribute:: range_limits
      :type:  Karana.Math.Ktyping.Length[Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((3, 2))]]


   .. py:method:: fromSubhinge(sh: Karana.Dynamics.Linear3Subhinge) -> Self
      :classmethod:


      Create a Linear3SubhingeParams from a Linear3Subhinge.



   .. py:method:: setSubhingeValues(sh: Karana.Dynamics.Linear3Subhinge) -> None

      Set the values of a Linear3Subhinge.



.. py:class:: LockedPhysicalSubhingeParams(/, **data: Any)

   Bases: :py:obj:`PhysicalSubhingeParams`


   LockedSubhinge DataStruct.


   .. py:attribute:: subhinge_type
      :type:  Karana.Dynamics.SubhingeType


   .. py:method:: fromSubhinge(sh: Karana.Dynamics.LockedSubhinge) -> Self
      :classmethod:


      Create a LockedPhysicalSubhingeParams from a LockedSubhinge.



   .. py:method:: setSubhingeValues(_: Karana.Dynamics.LockedSubhinge) -> None

      Set the values of a LockedSubhinge.



.. py:class:: LockedOffsetPhysicalSubhingeParams(*, offset: Karana.Math.HomTran)

   Bases: :py:obj:`PhysicalSubhingeParams`


   LockedOffsetSubhinge DataStruct.

   :param offset: The offset transform
   :type offset: HomTran


   .. py:attribute:: subhinge_type
      :type:  Karana.Dynamics.SubhingeType


   .. py:attribute:: offset
      :type:  Karana.Math.HomTran


   .. py:method:: fromSubhinge(sh: Karana.Dynamics.LockedOffsetSubhinge) -> Self
      :classmethod:


      Create a LockedOffsetPhysicalSubhingeParams from a LockedOffsetSubhinge.



   .. py:method:: setSubhingeValues(sh: Karana.Dynamics.LockedOffsetSubhinge) -> None

      Set the values of a LockedOffsetSubhinge.



.. py:class:: ScrewSubhingeParams(*, unit_axis: Karana.Math.Ktyping.Vec3, prescribed: bool = False, pitch: Karana.Math.Ktyping.Length[float] | float, joint_limits: Karana.Math.Ktyping.Angle[Annotated[Karana.Math.Ktyping.Vec, npSizeCheck((2, ))]] | Annotated[Karana.Math.Ktyping.Vec, npSizeCheck((2, ))] = np.array([km.notReadyNaN, km.notReadyNaN]) * ureg.rad, range_limits: Karana.Math.Ktyping.Angle[Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((1, 2))]] | Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((1, 2))] = np.full((1, 2), km.notReadyNaN) * ureg.rad)

   Bases: :py:obj:`PhysicalSubhingeParams`


   ScrewSubhinge DataStruct.

   :param prescribed: Determines if the subhinge is prescribed or not.
   :type prescribed: bool
   :param unit_axis: Unit axis for the pin subhinge.
   :type unit_axis: Vec3
   :param pitch: The pitch of the screw subhinge.
   :type pitch: Length[float]
   :param joint_limits: The lower and upper bound for the joint limit.
   :type joint_limits: Annotated[Vec, npSizeCheck((2,))]
   :param range_limits: The lower and upper bound for the Q coordinate range limits.
   :type range_limits: Annotated[Vec, npSizeCheck((1,2))]


   .. py:attribute:: subhinge_type
      :type:  Karana.Dynamics.SubhingeType


   .. py:attribute:: prescribed
      :type:  bool
      :value: False



   .. py:attribute:: unit_axis
      :type:  Annotated[Karana.Math.Ktyping.Vec3, normCheck(1.0)]


   .. py:attribute:: pitch
      :type:  Karana.Math.Ktyping.Length[float]


   .. py:attribute:: joint_limits
      :type:  Karana.Math.Ktyping.Angle[Annotated[Karana.Math.Ktyping.Vec, npSizeCheck((2, ))]]


   .. py:attribute:: range_limits
      :type:  Karana.Math.Ktyping.Angle[Annotated[Karana.Math.Ktyping.Mat, npSizeCheck((1, 2))]]


   .. py:method:: fromSubhinge(sh: Karana.Dynamics.ScrewSubhinge) -> Self
      :classmethod:


      Create a ScrewSubhingeParams from a ScrewSubhinge.



   .. py:method:: setSubhingeValues(sh: Karana.Dynamics.ScrewSubhinge) -> None

      Set the values of a ScrewSubhinge.



.. py:data:: SubhingePyType

.. py:function:: valuePrinter(q) -> str

   Print values for Python scripts.

   :param q: The value to print
   :type q: Quantity | NDArray

   :returns: The string representation of the value.
   :rtype: str


.. py:function:: fullPrintOpts()

   Context to print numpy values with full precision.


.. py:class:: VarPythonScriptContext

   .. py:method:: getVarNameIfExists(ds: Karana.KUtils.DataStruct.DataStruct) -> str | None
                  getVarNameIfExists(obj: object) -> str | None


   .. py:method:: getVarName(ds: Karana.KUtils.DataStruct.DataStruct, base_name: str = 'var') -> str
                  getVarName(obj: object, base_name: str = 'var') -> str


.. 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:: getRotationalNodalMatrix() -> Karana.Math.Ktyping.RotationalNodalMatrix[Karana.Math.Ktyping.Mat3n]

      Return the rotational portion of the nodal deformation matrix

      :returns: the rotational nodal matrix



   .. py:method:: getTranslationalNodalMatrix() -> Karana.Math.Ktyping.TranslationalNodalMatrix[Karana.Math.Ktyping.Mat3n]

      Return the translational portion of the nodal deformation matrix

      :returns: the translational nodal matrix



   .. py:method:: setRotationalNodalMatrix(rotational_nodal_matrix: Karana.Math.Ktyping.Mat3n | Karana.Math.Ktyping.RotationalNodalMatrix[Karana.Math.Ktyping.Mat3n]) -> None

      Set the rotational portion of the nodal deformation matrix

      :param rotational_nodal_matrix: the rotational nodal matrix



   .. py:method:: setTranslationalNodalMatrix(translational_nodal_matrix: Karana.Math.Ktyping.Mat3n | Karana.Math.Ktyping.TranslationalNodalMatrix[Karana.Math.Ktyping.Mat3n]) -> None

      Set the translational portion of the nodal deformation matrix

      :param translational_nodal_matrix: the translational nodal matrix



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

      Return the undeformed frame

      :returns: the undeformed Frame instance



.. py:class:: ParentPhysicalModalBodyAttachmentParams(inb_to_joint_transform: Karana.Math.HomTran, onode_rotational_nodal_matrix: Karana.Math.Ktyping.Mat3n | Karana.Math.Ktyping.RotationalNodalMatrix[Karana.Math.Ktyping.Mat3n], onode_translational_nodal_matrix: Karana.Math.Ktyping.Mat3n | Karana.Math.Ktyping.TranslationalNodalMatrix[Karana.Math.Ktyping.Mat3n])

   Bases: :py:obj:`Karana.Dynamics.ParentPhysicalBodyAttachmentParams`


   Defines an attachment to a PhysicalModalBody.


   .. py:method:: create(inb_to_joint_transform: Karana.Math.HomTran, onode_rotational_nodal_matrix: Karana.Math.Ktyping.Mat3n | Karana.Math.Ktyping.RotationalNodalMatrix[Karana.Math.Ktyping.Mat3n], onode_translational_nodal_matrix: Karana.Math.Ktyping.Mat3n | Karana.Math.Ktyping.TranslationalNodalMatrix[Karana.Math.Ktyping.Mat3n]) -> ParentPhysicalModalBodyAttachmentParams
      :staticmethod:


      Create a new instance of ParentPhysicalModalBodyAttachmentParams.

      :param inb_to_joint_transform: The inboard body to joint transform for
                                     the body.
      :param onode_rotational_nodal_matrix: The translational nodal matrix for
                                            the onode
      :param onode_translational_nodal_matrix: The translational nodal matrix
                                               for the onode

      :returns: The new instance of ParentPhysicalModalBodyAttachmentParams.



   .. py:method:: __getstate__() -> dict


   .. py:method:: __repr__()


   .. py:method:: __setstate__(arg0: dict) -> None


   .. py:property:: onode_rotational_nodal_matrix
      :type: Karana.Math.Ktyping.RotationalNodalMatrix[Karana.Math.Ktyping.Mat3n]


      The rotational nodal matrix for the onode


   .. py:property:: onode_translational_nodal_matrix
      :type: Karana.Math.Ktyping.TranslationalNodalMatrix[Karana.Math.Ktyping.Mat3n]


      The translational nodal matrix for the onode


.. py:class:: PhysicalModalBody(name: str, mbs: Karana.Dynamics._SOADyn_pybind11_Py.Multibody, nmodes: SupportsInt | SupportsIndex)

   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._SOADyn_pybind11_Py.PhysicalBody, params: Karana.Dynamics._modal_params.PhysicalModalBodyParams) -> list[PhysicalModalBody]
      :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 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._SOADyn_pybind11_Py.PhysicalBody, params: Karana.Dynamics._modal_params.PhysicalModalBodyParams) -> list[PhysicalModalBody]
      :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 params: the body params for each body

      :returns: the list of new rigid bodies



   .. py:method:: create(name: str, mbs: Karana.Dynamics._SOADyn_pybind11_Py.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:: accumT(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.ModalForce[Karana.Math.Ktyping.Vec]) -> None
                  accumT(val: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.ModalForce[float]) -> 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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: getDampingVector() -> Karana.Math.Ktyping.ModalDamping[Karana.Math.Ktyping.Vec]

      Get the damping vector for the body.

      :returns: The new damping vector for the body.



   .. py:method:: getParams() -> Karana.Dynamics._modal_params.PhysicalModalBodyParams

      Get the PhysicalModalBody parameters

      :returns: The parameters for this PhysicalModalBody.



   .. py:method:: getQ() -> Karana.Math.Ktyping.ModalCoordinate[Karana.Math.Ktyping.Vec]

      Return the global (chart) Q coordinates

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

      :returns: Array of values.



   .. py:method:: getStiffnessVector() -> Karana.Math.Ktyping.ModalStiffness[Karana.Math.Ktyping.Vec]

      Get the stiffness vector for the body.

      :returns: The stiffness vector for the body.



   .. py:method:: getT() -> Karana.Math.Ktyping.ModalForce[Karana.Math.Ktyping.Vec]

      Return the T generalized forces

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

      :returns: Array of values.



   .. py:method:: getU() -> Karana.Math.Ktyping.ModalVelocity[Karana.Math.Ktyping.Vec]

      Return the U velocity coordinates

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

      :returns: Array of values.



   .. py:method:: getUdot() -> Karana.Math.Ktyping.ModalAcceleration[Karana.Math.Ktyping.Vec]

      Return the Udot acceleration coordinates

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

      :returns: Array of values.



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


   .. py:method:: setDampingVector(damping: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.ModalDamping[Karana.Math.Ktyping.Vec]) -> None

      Set the damping vector for the body.

      :param damping: The new damping vector for the body.



   .. py:method:: setParams(params: Karana.Dynamics._modal_params.PhysicalModalBodyParams) -> None


   .. py:method:: setQ(Q: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.ModalCoordinate[Karana.Math.Ktyping.Vec]) -> None
                  setQ(Q: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.ModalCoordinate[float]) -> 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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setStiffnessVector(stiffness: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.ModalStiffness[Karana.Math.Ktyping.Vec]) -> None

      Set the stiffness vector for the body.

      :param stiffness: The new stiffness vector for the body.



   .. py:method:: setT(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.ModalForce[Karana.Math.Ktyping.Vec]) -> None
                  setT(val: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.ModalForce[float]) -> 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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setU(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.ModalVelocity[Karana.Math.Ktyping.Vec]) -> None
                  setU(val: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.ModalVelocity[float]) -> 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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: setUdot(vals: Karana.Math.Ktyping.Vec | Karana.Math.Ktyping.ModalAcceleration[Karana.Math.Ktyping.Vec]) -> None
                  setUdot(val: SupportsFloat | SupportsIndex | Karana.Math.Ktyping.ModalAcceleration[float]) -> 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.

      :returns: true if the new value was legal and accepted, false otherwise



   .. py:method:: toDS() -> Karana.Dynamics.SOAFlexDyn_types.ModalBodyDS

      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.ModalBodyStateDS

      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:: 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.Var[Karana.Math.Ktyping.ModalCoordinate[Karana.Math.Ktyping.Vec]]


      Modal coordinates


   .. py:property:: U
      :type: Karana.Core.Var[Karana.Math.Ktyping.ModalVelocity[Karana.Math.Ktyping.Vec]]


      Modal velocities


   .. py:property:: Udot
      :type: Karana.Core.Var[Karana.Math.Ktyping.ModalAcceleration[Karana.Math.Ktyping.Vec]]


      Modal accelerations


   .. py:property:: damping
      :type: Karana.Core.Var[Karana.Math.Ktyping.ModalDamping[Karana.Math.Ktyping.Vec]]


      damping


   .. py:property:: n_modes
      :type: Karana.Core.Var[int]


      The number of modes


   .. py:property:: stiffness
      :type: Karana.Core.Var[Karana.Math.Ktyping.ModalStiffness[Karana.Math.Ktyping.Vec]]


      stiffness


.. py:class:: PhysicalModalBodyParams(spatial_inertia: Karana.Math.SpatialInertia, body_to_joint_transform: Karana.Math.HomTran, hinge_params: Karana.Dynamics.PhysicalHingeParams, parent_body_attachment_params: Karana.Dynamics.ParentBodyAttachmentParams, scene_part_specs: list[Karana.Scene.ScenePartSpec], scene_file_object_specs: list[Karana.Scene.SceneFileObjectSpec], nmodes: int, stiffness: Karana.Math.Ktyping.ModalStiffness[Karana.Math.Ktyping.Vec] | Karana.Math.Ktyping.Vec, damping: Karana.Math.Ktyping.ModalDamping[Karana.Math.Ktyping.Vec] | Karana.Math.Ktyping.Vec, pnode_rotational_nodal_matrix: Karana.Math.Ktyping.RotationalNodalMatrix[Karana.Math.Ktyping.Mat3n] | Karana.Math.Ktyping.Mat3n, pnode_translational_nodal_matrix: Karana.Math.Ktyping.TranslationalNodalMatrix[Karana.Math.Ktyping.Mat3n] | Karana.Math.Ktyping.Mat3n)

   Bases: :py:obj:`Karana.Dynamics.PhysicalBodyParams`


   Parameters used to configure a PhysicalModalBody.

   :param spatial_inertia: Spatial inertia assigned to the body.
   :type spatial_inertia: Karana.Math.SpatialInertia
   :param body_to_joint_transform: Transform from the body frame to its hinge joint frame.
   :type body_to_joint_transform: Karana.Math.HomTran
   :param hinge_params: Parameters for the body's physical hinge.
   :type hinge_params: PhysicalHingeParams
   :param parent_body_attachment_params: Parameters for attaching this body to its parent.
   :type parent_body_attachment_params: ParentBodyAttachmentParams
   :param scene_part_specs: Scene-part specifications attached to the body.
   :type scene_part_specs: list[ScenePartSpec]
   :param scene_file_object_specs: Scene-file-object specifications attached to the body.
   :type scene_file_object_specs: list[SceneFileObjectSpec]
   :param nmodes: The number of deformation modes
   :type nmodes: int
   :param stiffness: The stiffness vector (based on modal frequencies)
   :type stiffness: ModalStiffness[Vec]
   :param damping: The damping coefficients
   :type damping: ModalDamping[Vec]
   :param pnode_rotational_nodal_matrix: The rotational nodal matrix for the pnode
   :type pnode_rotational_nodal_matrix: Mat3n
   :param pnode_translational_nodal_matrix: The translational nodal matrix for the pnode
   :type pnode_translational_nodal_matrix: Mat3n


   .. py:attribute:: nmodes
      :type:  int


   .. py:attribute:: stiffness
      :type:  Karana.Math.Ktyping.ModalStiffness[Karana.Math.Ktyping.Vec]


   .. py:attribute:: damping
      :type:  Karana.Math.Ktyping.ModalDamping[Karana.Math.Ktyping.Vec]


   .. py:attribute:: pnode_rotational_nodal_matrix
      :type:  Karana.Math.Ktyping.RotationalNodalMatrix[Karana.Math.Ktyping.Mat3n]


   .. py:attribute:: pnode_translational_nodal_matrix
      :type:  Karana.Math.Ktyping.TranslationalNodalMatrix[Karana.Math.Ktyping.Mat3n]


   .. py:method:: createDefault() -> Self
      :classmethod:


      Create a version of PhysicalModalBodyParams with all values filled in.

      This is useful for testing or when you just need a body for a simple demo.

      :returns: An instance of PhysicalModalBodyParams with all values filled in.
      :rtype: Self



