Karana.Frame
============

.. py:module:: Karana.Frame

.. autoapi-nested-parse::

   Classes and modules related to the Frames layer.



Classes
-------

.. autoapisummary::

   Karana.Frame.ChainedFrameToFrame
   Karana.Frame.ChainedFrameToFrameVars
   Karana.Frame.EdgeFrameToFrame
   Karana.Frame.Frame
   Karana.Frame.FrameContainer
   Karana.Frame.FrameDumpOptions
   Karana.Frame.FrameToFrame
   Karana.Frame.FrameToFrameVars
   Karana.Frame.FrameVars
   Karana.Frame.OrientedChainedFrameToFrame
   Karana.Frame.OrientedChainedFrameToFrameVars
   Karana.Frame.PrescribedFrameToFrame
   Karana.Frame.SpiceFrame
   Karana.Frame.SpiceFrameToFrame


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

.. py:class:: ChainedFrameToFrame

   Bases: :py:obj:`FrameToFrame`


   FrameToFrame class connecting arbitrary oframe/pframe Frame pairs

   The oframe and pframe frames can be located anywhere in the frames
   tree.

   See :ref:`frames_layer_sec` for more discussion on the frames layer.


   .. py:method:: getPath() -> list[EdgeFrameToFrame]

      Return the sequence of edge names in this chain as vector
      :returns: path the sequence of f2f edges making up the chain



.. py:class:: ChainedFrameToFrameVars

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


   The Vars for the ChainedFrameToFrame class.


.. py:class:: EdgeFrameToFrame

   Bases: :py:obj:`FrameToFrame`


   Base class for an edge FrameToFrame in the frames tree

   See :ref:`frames_layer_sec` for more discussion on the frames layer.


.. py:class:: Frame(name: str, fc: FrameContainer)

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


   .. py:method:: create(name: str, fc: FrameContainer) -> Frame
      :staticmethod:


      Creates a new frame with the given name.
      :param name:
                   - The name of the frame to create.
      :param fc:
                 - The parent frames container

      :returns: The created frame.



   .. py:method:: childrenFrames() -> list[Frame]

      Return the list of frames attached to this frame

      :returns: list of children frames



   .. py:method:: container() -> FrameContainer

      Get the reference to the container of the frame.
      :returns: The reference to the container of the frame.



   .. py:method:: dumpFrameTree(prefix: str = '', options: FrameDumpOptions = ...) -> None

       Display the frame 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 output line @param options output
       content options



   .. py:method:: edge() -> EdgeFrameToFrame

      Get the edge associated with this frame.
      :returns: The edge f2f.



   .. py:method:: frameToFrame(frame: Frame) -> ChainedFrameToFrame

      Create a chained f2f between this frame and the target frame. This
      frame will be the o-frame and the target frame will become the
      p-frame.
      :param frame: The target frame. This will be the p-frame in the chained
                    frame to frame.

      :returns: The ChainedFrameToFrame connecting this frame (o-frame) and the
                target frame (p-frame).



   .. py:method:: getAncestor(other: Frame) -> Frame

      Get the ancestor of this frame and another frame.
      :param other: The other frame.

      :returns: The common ancestor.



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


   .. py:method:: isAncestorOf(arg0: Frame, arg1: bool) -> bool

      Check if this frame is an ancestor of another frame.
      :param other: The other frame to check against.
      :param strict: if false, a frame can be its own ancestor

      :returns: True if this frame is an ancestor of the other frame, false
                otherwise.



   .. py:method:: orientedFrameToFrame(frame: Frame) -> OrientedChainedFrameToFrame

      Create an oriented chained f2f between this frame and the target
      frame. This frame will be the o-frame and the target frame will become
      the p-frame.

      Note that it up to the user to ensure that the pframe is a true
       descendant of the oframe. If not, there will be errors when trying to
       use this oriented chain.

      :param frame: The target frame. This will be the p-frame in the chained
                    frame to frame.

      :returns: The OrientedChainedFrameToFrame connecting this frame (o-frame)
                and the target frame (p-frame).



   .. py:method:: parentFrame() -> Frame

      Get the parent frame.
      :returns: The parent frame.



.. py:class:: FrameContainer(name: str)

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


   


   .. py:method:: create(name: str) -> FrameContainer
      :staticmethod:


      Create a FrameContainer.
      :param root_frame_name: Name for the root frame

      :returns: The frame container.



   .. py:method:: edgeFrameToFrames() -> list[EdgeFrameToFrame]

      Return a vector of all the EdgeFrameToFrames in the FrameContainer.

      :returns: List of all the edge elements.



   .. py:method:: frames() -> list[Frame]

      Return a vector of all the frames in the FrameContainer.

      :returns: List of all the frame elements.



   .. py:method:: getAncestor(frame1: Frame, frame2: Frame) -> Frame

      Gets the common ancestor of two frames.
      :param frame1: The first frame.
      :param frame2: The second frame.

      :returns: The common ancestor frame.



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

      Return the current ephemeris time

      The ephemeris time is needed by Spice frames

      :returns: the current ephemeris time



   .. py:method:: isAncestorOf(arg0: Frame, arg1: Frame, arg2: bool) -> bool

      Checks if one frame is an ancestor of another.
      :param oframe: The potential ancestor frame.
      :param pframe: The potential descendant frame.
      :param strict: If false, a frame can be its own ancestor

      :returns: True if oframe is an ancestor of pframe, false otherwise.



   .. py:method:: lookupFrame(name: str) -> list[Frame]

      Return a vector of all Frames with the given name.
      :param name: name of the Frame instances to look up

      :returns: A vector of all the Frames with the given name.



   .. py:method:: root() -> Frame

      Returns the root frame of the tree.
      :returns: The root frame.



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

      Set the ephemeris time

      The ephemeris time is needed by Spice frames

      :param ephemeris_time: the ephemeris time



   .. py:method:: showFramesGraph(*, port: int = 29623, label_map: collections.abc.Mapping[str | int, str] | None = None, title: str = 'Frame layer', buttons: list[Button] | None = None, coloring: Literal['type', 'valency'] = 'type', chains: bool = False, launch_client: bool = False) -> GraphServer

      Visualize the frame tree as a graph.

          Parameters
          ----------
          self: FrameContainer
              The frame container whose frames to display
          port: int
              Port to bind to. Use 0 to pick an arbitrary open port. Defaults
              to 29623.
          label_map: Mapping[str | int, str] | None
              Map indicating labels to use for frames in the visualization.
              Keys may be either frame ids or names. Frames without a label
              will be assigned a unique number as their label.
          title: str
              Title of the graph. Defaults to "Frame layer".
          buttons: list[Button]
              Extra buttons to display, triggering callbacks on press.
          coloring: Literal["type", "valency"]
              How to color the nodes and edges in the visualization:
                  type: Color based on the type of the Frame or FrameToFrame
                  valency: Color nodes based on number of connecting edges
              Defaults to the "type" coloring.
          chains: bool
              Whether to also show edges for ChainedFrameToFrames.
              Defaults to False.
          launch_client: bool
              Automatically open the frontend in a local browser tab.
              Defaults to False.

          Returns
          -------
          GraphServer
              Handle to the web server hosting the graph visualization





.. py:class:: FrameDumpOptions(type_string: bool = True, edge_type: bool = False, healthy_status: bool = False, id: bool = False)

   .. py:attribute:: edge_ref_count
      :type:  bool


   .. py:attribute:: edge_type
      :type:  bool


   .. py:attribute:: healthy_status
      :type:  bool


   .. py:attribute:: id
      :type:  bool


   .. py:attribute:: ref_count
      :type:  bool


   .. py:attribute:: type_string
      :type:  bool


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


.. py:class:: FrameToFrame

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


   Represents a connection between two frames.

   This class handles the transformation, velocity, and acceleration
   between two frames.

   See :ref:`frames_layer_sec` for more discussion on the frames layer.


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

      Get flag whether this f2f supports accelerations.

      Most f2fs support accelerations, but there are exceptions such as
      SpiceFrameToFrame and CM frame edges that do not.

      :returns: true if the f2f supports acceleration values.



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


   .. py:method:: oframe() -> Frame

      Get the oframe of the FrameToFrame.
      :returns: oframe.



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

      Return the transform rates for the oframe to pframe relative velocity

      This method converts the spatial velocity of the pframe with respect
      to the oframe, into the minimal coordinate rates 6-vector for the
      relative transform. The minimal coordinates are the
      Karana::Math::RotationVector representation of the attitude part, and
             the
      relative position of the linear part.

      :returns: The coordinate rates as a 6-vector



   .. py:method:: pframe() -> Frame

      Get the pframe of the FrameToFrame.
      :returns: pframe.



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

      Return the pframe observed relative spatial acceleration between the
      oframe and pframe.

      This is the spatial acceleration of the pframe with respect to the
      oframe, as observed from the pframe, and represented in pframe.

      The resulting linear accel, p_a(o,p) is the derivative of p_R_o *
      o_v(o,p) vector, i.e. the time derivative of the pframe coordinate
      representation of the o_v(o,p) oframe/pframe translational velocity.

           p_a(o,p) = p_R_o * [ o_a(o,p) + o_v(o,p) x w(o,p) ]

      Note that the returned value is *NOT* p_a(p,o), which corresponds to
      f_to_f(pframe, oframe).relSpAccel(). To get p_a(p,o) you need to
      switch the roles of oframe and pframe and simply call
      pframe.relSpAccel(oframe).

      :returns: The pframe observed spatial acceleration vector.



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

      Return the pframe observed relative spatial velocity between the
      oframe and pframe.

      This is the spatial velocity of the pframe with respect to the oframe,
      as observed from the pframe, and represented in the pframe.

      The resulting linear velocity, p_v(o,p) is the derivative of p_l(o,p)
      = p_R_o * o_l(o,p) vector, i.e. the time derivative of the pframe
      coordinate representation of the oframe/pframe translational vector.
      Thus

           p_v(o,p) = p_R_o * [ o_v(o,p) + o_l(o,p) x w(o,p) ]

      Note that the returned value is *NOT* p_v(p,o) that corresponds to
      f_to_f(pframe, oframe).relSpVel() where the roles of oframe and pframe
      are switched, and the value would be the velocity of oframe with
      respect to pframe.

      :returns: The pframe observed spatial velocity vector.



   .. py:method:: relSpAccel() -> Karana.Math.SpatialAcceleration

      Get the relative acceleration between the oframe and pframe.

      This is the spatial acceleration of the pframe with respect to the
      oframe, as observed from the oframe, and represented in the oframe.

      The resulting linear accel, o_a(o,p) is the derivative of o_v(o,p)
      velocity, i.e. the time derivative of the oframe coordinate
      representation of the o_v(o,p) oframe/pframe translational velocity.
      The actual work is done by the accel cache callback, and this is a
      simple public wrapper for it.

      :returns: The spatial acceleration vector.



   .. py:method:: relSpVel() -> Karana.Math.SpatialVelocity

      Get the relative velocity between the oframe and pframe.

      This is the spatial velocity of the pframe with respect to the oframe,
      as observed from the oframe, and represented in the oframe.

      The resulting linear velocity, o_v(o,p) is the derivative of o_l(o,p)
      vector, i.e. the time derivative of the oframe coordinate
      representation of the oframe/pframe translational vector.  The actual
      work is done by the velocity cache callback, and this is a simple
      public wrapper for it.

      :returns: The spatial velocity vector.



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

      Get the relative homogeneous transformation between the oframe and
      pframe.

      The actual work is done by the transform cache callback, and this is a
      simple public wrapper for it.

      :returns: The homogeneous transformation.



   .. py:method:: solveSpAccel(arg0: FrameToFrame, arg1: FrameToFrame, arg2: Karana.Math.SpatialAcceleration) -> Karana.Math.SpatialAcceleration

      Solve for sub f_to_f's relative spatial acceleration needed to achieve
      desired relative spatial acceleration

      Denoting this as the A/C f_to_f, and the desired relative spatial
      acceleration as A, this method solves for the relative spatial
      acceleration required of the sub_f_to_f (which is assumed to be in the
      A/C path). It is required that sub_f_to_f be at one end or the other
      of the A/C f_to_f, i.e. it's oframe is A, or that its pframe is C. The
      sub_f_to_f thus splits the A/C f_to_f path in two parts. The
      other_f_to_f is the f_to_f for the remaining half.

      We pass in extra f_to_f's to avoid the cost of lookups within this
      method.

      :param sub_f_to_f: the sub f_to_f whose required spatial acceleration is
                         to be computed
      :param other_f_to_f: the f_to_f for the segment of oframe/pframe not
                           covered by sub_f_to_f
      :param A: the desired relative spatial acceleration for this f_to_f

      :returns: the relative spatial acceleration required for the sub f_to_f



   .. py:method:: solveSpVel(arg0: FrameToFrame, arg1: FrameToFrame, arg2: Karana.Math.SpatialVelocity) -> Karana.Math.SpatialVelocity

      Solve for sub f_to_f's relative spatial velocity needed to achieve
      desired relative spatial velocity

      Denoting this as the A/C f_to_f, and the desired relative spatial
      velocity as V, this method solves for the relative spatial velocity
      required of the sub_f_to_f (which is assumed to be in the A/C path).
      It is required that sub_f_to_f be at one end or the other of the A/C
      f_to_f, i.e. it's oframe is A, or that its pframe is C. The sub_f_to_f
      thus splits the A/C f_to_f path in two parts. The other_f_to_f is the
      f_to_f for the remaining half.

      We pass in extra f_to_f's to avoid the cost of lookups within this
      method.

      :param sub_f_to_f: the sub f_to_f whose required spatial velocity is to
                         be computed
      :param other_f_to_f: the f_to_f for the segment of oframe/pframe not
                           covered by sub_f_to_f
      :param V: the desired relative spatial velocity for this f_to_f

      :returns: the relative spatial velocity required for the sub f_to_f



   .. py:method:: solveTransform(arg0: FrameToFrame, arg1: Karana.Math.HomTran) -> Karana.Math.HomTran

      Solve for sub f_to_f's transform needed to achieve desired relative
      transform

      Denoting this as the A/C f_to_f, and the desired relative transform as
      desired_T, this method solves for the relative transform required of
      the sub_f_to_f (which is assumed to be in the A/C path). It is
      required that sub_f_to_f be at one end or the other of the A/C f_to_f,
      i.e. it's oframe is A, or that its pframe is C.

      :param sub_f_to_f: the sub f_to_f whose required transform is to be
                         computed
      :param T: the desired relative transform for this f_to_f

      :returns: the relative transform required for the sub f_to_f



   .. py:method:: subchainOrientation(arg0: FrameToFrame) -> bool | None

      Check the relationship of a sub-chain FrameToFrame's path with respect
      to the overall FrameToFrame path.

      Return true if the sub-chain FrameToFrame's path is contained in the
      FrameToFrame's oframe/pframe path and oriented with the path, false if
      it has opposed orientation, and nullopt if it is not fully contained
      in the path.

      :param sub_f_to_f: the sub-path FrameToFrame's orientation to check

      :returns: null if not on path, and true if on the path and oriented



   .. py:method:: toOframeObserved(arg0: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]], arg1: Annotated[numpy.typing.ArrayLike, numpy.float64, [3, 1]]) -> Annotated[numpy.typing.NDArray[numpy.float64], [3, 1]]

      Transform the 3-vector pframe observed derivative to oframe observed
      derivative

      This method converts the pframe observed time derivative of a 3-vector
      into the oframe observed time derivative.

      Usage: This method is used to change the observing frame for
      a 3-vector derivative to a new one. To do this, create a f_to_f
      FrameToFrame from the new observing frame to the original observing
      frame for the vector derivative, and pass in the vector, x, and its
      time derivative, xdot, as arguments to f_to_f.toOframeObserved(x,
      xdot). The returned value will be the time derivative vector in the
      new observing frame.

      :param pframe_x: the pframe representation of the 3-vector whose time
                       derivative is being taken
      :param pframe_x_dot: the (original) pframe observed time derivative of
                           pframe_x

      :returns: the (new) oframe observed time derivative of pframe_x



   .. py:method:: toPframeRelativeSpAccel(arg0: Karana.Math.SpatialAcceleration) -> Karana.Math.SpatialAcceleration

      Transform the provided oframe relative spatial accel into pframe
      relative value

      For this f_to_f, convert the hypothetical oframe relative spatial
      accel for the f_to_f into the corresponding pframe relative spatial
      accel as if we are taking the derivative of the pframe to the oframe
      vector quantities as observed from the pframe, and represented in the
      pframe. This method assumes that the relative transform and spatial
      velocity for the f_to_f are valid and uses them.

      Note that when the hypothetical input spatial accel is the true value
      we will have the following equivalence:

         toPframeRelativeSpAccel(relSpAccel()) ==
      pframe()->frameToFrame(oframe())->relSpAccel()


      Note that this method changes the acceleration vector from being
      oframe/pframe to being pframe/oframe, and thus is doing more than just
      changing the observing frame./

      This method is handy for multibody state initialization, where we are
      trying to initialize the multibody acceleration coordinates based on
      some physical requirements on body/node spatial acceleration. This
      method can be use to convert these requirements into requirements on
      the relative spatial acceleration on hinges, and at which point the
      hinge fitUdot() method can be used to compute the Udot acceleration
      coordinates for the hinge that meet the requirements.

      :param oframe_a: the hypothetical oframe relative spatial accel

      :returns: the corresponding pframe relative spatial accel



   .. py:method:: toPframeRelativeSpVel(arg0: Karana.Math.SpatialVelocity) -> Karana.Math.SpatialVelocity

      Transform the hypothetical oframe deriv relative spatial velocity into
      pframe relative value

      For this f_to_f, convert the hypothetical oframe derivative relative
      spatial velocity for the f_to_f into the corresponding pframe relative
      spatial velocity, i.e the derivative of the reversed pframe to the
      oframe vector quantities as observed from the pframe, and representing
      in the pframe. Thus this is computing B_alpha(B,A) from A_alpha(A, B).
      This method assumes that the relative transform for the f_to_f is
      valid and uses it.

      Note that when the hypothetical input oframe relative spatial velocity
      is the true value we will have the following
      equivalence:

         toPframeRelativeSpVel(relSpVel()) ==
         pframe()->frameToFrame(oframe())->relSpVel()

      Note that this method changes the velocity vector from being
      oframe/pframe to being pframe/oframe, and thus is doing more than just
      changing the observing frame./

      This method is handy for state initialization, where we are trying to
      initialize the multibody velocity coordinates based on some physical
      requirements on body/node spatial velocities. This method can be use
      to convert these requirements into requirements on the relative
      spatial velocities for the hinge, and at which point the hinge fitU()
      method can be used to compute the U velocity coordinates for the hinge
      that meet the requirements.

      :param oframe_v: the hypothetical oframe relative spatial velocity

      :returns: the corresponding pframe relative spatial velocity



.. py:class:: FrameToFrameVars

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


   


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


      The oframe name


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


      The pframe name


   .. py:property:: rel_sp_accel
      :type: Karana.Core.VarSpatialAcceleration


      The relative spatial acceleration


   .. py:property:: rel_sp_vel
      :type: Karana.Core.VarSpatialVelocity


      The relative spatial velocity


   .. py:property:: rel_transform
      :type: Karana.Core.VarHomTran


      The relative pose


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


      whether accels are supported


.. py:class:: FrameVars

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


   The Vars for the Frame class.


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


      The name of the frame's parent frame


.. py:class:: OrientedChainedFrameToFrame

   Bases: :py:obj:`FrameToFrame`


   


   .. py:method:: getPath() -> list[EdgeFrameToFrame]

      Return the sequence of edge names in this chain as a string
      :returns: path the sequence of f2f edges making up the chain



.. py:class:: OrientedChainedFrameToFrameVars

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


   The Vars for the OrientedChainedFrameToFrame class.


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


      the  number of f2f edges in the chain


   .. py:property:: oriented_f2f_edges
      :type: Karana.Core.VarVecString


      the oframe to pframe path


.. py:class:: PrescribedFrameToFrame(oframe: Frame, pframe: Frame, name: str = '', supports_accels: bool = True)

   Bases: :py:obj:`EdgeFrameToFrame`


   Base class for an edge FrameToFrame in the frames tree

   See :ref:`frames_layer_sec` for more discussion on the frames layer.


   .. py:method:: create(oframe: Frame, pframe: Frame, name: str = '', supports_accels: bool = True) -> PrescribedFrameToFrame
      :staticmethod:


      Constructor for PrescribedFrameToFrame.
      :param oframe:
                     - oframe of the PrescribedFrameToFrame.
      :param pframe:
                     - pframe of the PrescribedFrameToFrame.
      :param name: the name for the edge.
      :param supports_accels: flag indicating whether the edge supports accels

      :returns: The PrescribedFrameToFrame object.



   .. py:method:: setRelSpAccel(arg0: Karana.Math.SpatialAcceleration) -> None

      Set the relative acceleration between the oframe and pframe.



   .. py:method:: setRelSpVel(arg0: Karana.Math.SpatialVelocity) -> None

      Set the relative velocity between the oframe and pframe.



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

      Set the relative homogeneous transformation between the oframe and
      pframe.



.. py:class:: SpiceFrame(fc: FrameContainer, naif_body_id: SupportsInt | SupportsIndex, naif_frame_id: SupportsInt | SupportsIndex = 999999)

   Bases: :py:obj:`Frame`


   .. py:method:: loadNaifKernel(path: os.PathLike | str | bytes) -> None
      :staticmethod:


      Method to load a NAIF kernel.
      :param path: path to the kernel



   .. py:method:: lookupOrCreate(fc: FrameContainer, naif_body_id: SupportsInt | SupportsIndex, naif_frame_id: SupportsInt | SupportsIndex = 999999) -> SpiceFrame
      :staticmethod:


      Factory method to look up, or create a SpiceFrame

      If the NAIF frame id is unspecified, then the default frame for the
      NAIF body is used.

      :param fc: the FrameContainer
      :param naif_body_id: the NAIF body id
      :param naif_frame_id: the NAIF frame id

      :returns: a new SpiceFrame instance



.. py:class:: SpiceFrameToFrame(arg0: SpiceFrame, arg1: SpiceFrame)

   Bases: :py:obj:`EdgeFrameToFrame`


   Base class for an edge FrameToFrame in the frames tree

   See :ref:`frames_layer_sec` for more discussion on the frames layer.


   .. py:method:: lookupOrCreate(arg0: SpiceFrame, arg1: SpiceFrame) -> SpiceFrameToFrame
      :staticmethod:


      Factory method to look up or create a SpiceFrameToFrame

      :param oframe: the SpiceFrame oframe
      :param pframe: the SpiceFrame pframe

      :returns: a SpiceFrameToFrame instance



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


