Source code for Karana.Dynamics._modal_params

# Copyright (c) 2024-2026 Karana Dynamics Pty Ltd. All rights reserved.
#
# NOTICE TO USER:
#
# This source code and/or documentation (the "Licensed Materials") is
# the confidential and proprietary information of Karana Dynamics Inc.
# Use of these Licensed Materials is governed by the terms and conditions
# of a separate software license agreement between Karana Dynamics and the
# Licensee ("License Agreement"). Unless expressly permitted under that
# agreement, any reproduction, modification, distribution, or disclosure
# of the Licensed Materials, in whole or in part, to any third party
# without the prior written consent of Karana Dynamics is strictly prohibited.
#
# THE LICENSED MATERIALS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
# KARANA DYNAMICS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
# BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND
# FITNESS FOR A PARTICULAR PURPOSE.
#
# IN NO EVENT SHALL KARANA DYNAMICS BE LIABLE FOR ANY DAMAGES WHATSOEVER,
# INCLUDING BUT NOT LIMITED TO LOSS OF PROFITS, DATA, OR USE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, WHETHER IN CONTRACT, TORT,
# OR OTHERWISE ARISING OUT OF OR IN CONNECTION WITH THE LICENSED MATERIALS.
#
# U.S. Government End Users: The Licensed Materials are a "commercial item"
# as defined at 48 C.F.R. 2.101, and are provided to the U.S. Government
# only as a commercial end item under the terms of this license.
#
# Any use of the Licensed Materials in individual or commercial software must
# include, in the user documentation and internal source code comments,
# this Notice, Disclaimer, and U.S. Government Use Provision.

from typing import TYPE_CHECKING, Self
import numpy as np


import Karana.Math as km
from Karana.Math.Ktyping import (
    Mat3n,
    RotationalNodalMatrix,
    TranslationalNodalMatrix,
    Vec,
    ModalStiffness,
    ModalDamping,
)


if TYPE_CHECKING:
    from Karana.Dynamics import (
        PhysicalBodyParams,
        PhysicalHingeParams,
        PinSubhingeParams,
        HingeType,
        ParentPhysicalModalBodyAttachmentParams,
        ParentBodyAttachmentParams,
    )
    import Karana.Scene as ks
else:
    from ._params import PhysicalBodyParams, PhysicalHingeParams, PinSubhingeParams
    from ._SOADyn_Py import HingeType
    from ._SOAFlexDyn_Py import ParentPhysicalModalBodyAttachmentParams


def _stiffnessDefault():
    return np.linspace(1, 4, 4) * 0.1


def _dampingDefault():
    return np.linspace(1, 4, 4) * 0.01


def _rotDefault(val: float):
    dark = np.empty((3, 4))
    for i in range(3):
        for j in range(4):
            dark[i, j] = i + j + 1
    return val * dark


def _transDefault(val: float):
    dark = np.empty((3, 4))
    for i in range(3):
        for j in range(4):
            dark[i, j] = i + j + 4
    return val * dark


class PhysicalModalBodyParams(PhysicalBodyParams):
    """Parameters used to configure a PhysicalModalBody.

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

    nmodes: int
    stiffness: ModalStiffness[Vec]
    damping: ModalDamping[Vec]
    pnode_rotational_nodal_matrix: RotationalNodalMatrix[Mat3n]
    pnode_translational_nodal_matrix: TranslationalNodalMatrix[Mat3n]

    if TYPE_CHECKING:
        # Add type hint for init that includes coercion
        def __init__(
            self,
            spatial_inertia: km.SpatialInertia,
            body_to_joint_transform: km.HomTran,
            hinge_params: PhysicalHingeParams,
            parent_body_attachment_params: ParentBodyAttachmentParams,
            scene_part_specs: list[ks.ScenePartSpec],
            scene_file_object_specs: list[ks.SceneFileObjectSpec],
            nmodes: int,
            stiffness: ModalStiffness[Vec] | Vec,
            damping: ModalDamping[Vec] | Vec,
            pnode_rotational_nodal_matrix: RotationalNodalMatrix[Mat3n] | Mat3n,
            pnode_translational_nodal_matrix: TranslationalNodalMatrix[Mat3n] | Mat3n,
        ):
            """Parameters used to configure a PhysicalModalBody.

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

[docs] @classmethod def createDefault(cls) -> Self: """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 ------- Self An instance of PhysicalModalBodyParams with all values filled in. """ return cls( spatial_inertia=km.SpatialInertia( 2.0, np.array([0.3, 0.2, 0.1]), np.diag([3.0, 2.0, 1.0]) ), body_to_joint_transform=km.HomTran( km.UnitQuaternion(0.8, 0.6, 0.0, 0.0), np.array([0.2, 0.3, 0.4]) ), hinge_params=PhysicalHingeParams( hinge_type=HingeType.REVOLUTE, subhinge_params=[PinSubhingeParams(unit_axis=np.array([0.0, 1.0, 0.0]))], ), parent_body_attachment_params=ParentPhysicalModalBodyAttachmentParams( inb_to_joint_transform=km.HomTran( km.UnitQuaternion(0.5, 0.5, 0.5, 0.5), np.array([0.4, 0.2, 0.3]) ), onode_rotational_nodal_matrix=_rotDefault(0.2), onode_translational_nodal_matrix=_transDefault(0.2), ), scene_part_specs=[], scene_file_object_specs=[], nmodes=4, stiffness=_stiffnessDefault(), damping=_dampingDefault(), pnode_rotational_nodal_matrix=_rotDefault(0.1), pnode_translational_nodal_matrix=_transDefault(0.1), )
__all__ = ["PhysicalModalBodyParams"]