Source code for Karana.KUtils.MultibodyTUI.loopdb

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

"""Contains the LoopConstraintDatabase class, which is used to query body/loop constraint relationships."""

from Karana.Dynamics import Multibody, PhysicalBody, LoopConstraintBase
from collections import defaultdict
from collections.abc import Mapping, Generator


[docs] class LoopConstraintDatabase: """Helper to query body / loop constraint relationships.""" def __init__(self, multibody: Multibody): """Create an instance of LoopConstraintDatabase. Parameters ---------- multibody: Multibody The multibody to do queries within """ self.multibody = multibody # map with the list of all the bodies in a loop constraint's loop self._lc_related_bodies: Mapping[int, list[PhysicalBody]] = defaultdict(list) # map with the list of all the loop constraints that # the body in a part of self._body_related_lcs: Mapping[int, list[LoopConstraintBase]] = defaultdict(list) for lc in self.allLoopConstraints(): related_bodies = self._computeLoopBodyPath(lc) self._lc_related_bodies[lc.id()] = related_bodies for body in related_bodies: self._body_related_lcs[body.id()].append(lc)
[docs] def allLoopConstraints(self) -> Generator[LoopConstraintBase]: """Retrieve all the loop constraints. Returns ------- Generator[LoopConstraintBase] All the loop constraints as a generator. """ for constraint in self.multibody.enabledConstraints(): if isinstance(constraint, LoopConstraintBase): yield constraint
def _computeLoopBodyPath(self, lc: LoopConstraintBase) -> list[PhysicalBody]: """Compute the body path for the loop constraint. This is the alternate path through the body tree connecting the source and target nodes of the constraint. """ src_body = lc.sourceNode().parentBody() tgt_body = lc.targetNode().parentBody() common_ancestor = self.multibody.ancestorBody(src_body, tgt_body) src_leg = [] tgt_leg = [] while src_body != common_ancestor: src_leg.append(src_body) src_body = src_body.physicalParentBody() while tgt_body != common_ancestor: tgt_leg.append(tgt_body) tgt_body = tgt_body.physicalParentBody() path = src_leg + [common_ancestor] + list(reversed(tgt_leg)) return path
[docs] def emanatingLoopConstraints(self, body: PhysicalBody) -> list[LoopConstraintBase]: """Get all loop constraints directly attached to the body. Parameters ---------- body: PhysicalBody The given body Returns ------- list[LoopConstraintBase] The list of loop constraints """ return self.multibody.getBodyLoopConstraints(body)
[docs] def relatedLoopConstraints(self, body: PhysicalBody) -> list[LoopConstraintBase]: """Get all loop constraints having the body in their path. A loop constraint is included if the path through the body tree from their source to target node includes the given body. Parameters ---------- body: PhysicalBody The given body Returns ------- list[LoopConstraintBase] The list of loop constraints """ return self._body_related_lcs[body.id()][:]
[docs] def relatedBodies(self, loop_constraint: LoopConstraintBase) -> list[PhysicalBody]: """Get all bodies along the loop constraint's path. Lists the bodies along the path from the source to target node through the body tree. Parameters ---------- loop_constraint: LoopConstraintBase The given loop constraint Returns ------- list[PhysicalBody] The list of bodies """ return self._lc_related_bodies[loop_constraint.id()][:]