Program Listing for File HingeBase.h

Program Listing for File HingeBase.h#

Return to documentation for file (include/Karana/SOADyn/HingeBase.h)

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

/**
 * @file
 * @brief Contains the declarations for the HingeBase class.
 */

#pragma once

#include "Karana/KCore/RegistryList.h"
#include "Karana/Math/UnitQuaternion.h"
#include "Karana/SOADyn/Defs.h"
#include "Karana/SOADyn/SubhingeBase.h"

namespace Karana::Dynamics {

    namespace kc = Karana::Core;
    namespace km = Karana::Math;

    class SubhingeBase;

    /**
     * @class HingeBase
     * @brief Represents the base class for articulation hinges
     *
     * This is the abstract base class for hinge containers for
     * PhysicalHinge and CompoundHinge classes that define articulation
     * for bodies. See \sref{body_hinge_sec} section for more discussion
     * on hinges.
     */
    class HingeBase {

        // for access to _subhinges_usage_map
        friend class HingeOnode;
        friend class SubTree;

        // for access to _subhinges_list
        friend class CompoundSubhinge;
        friend class CompoundBody;

        // for access to coord map matrices
        friend class Algorithms;

        // for access to coord map matrices
        friend class KaranaTest::Dynamics::SOADynTesting;

      public:
        /**
         * @brief Return the list of SubhingeBase::SubhingeType subhinge types for a known hinge
         * type
         *
         * A hinge is a container for a list of subhinges. This method
         * returns the list of subhinge types for a known hinge type.
         *
         * @param htype the hinge type
         * @return list of subhinge types
         */
        static std::vector<SubhingeType> getSubhingeTypes(HingeType htype);

        /**
         * @brief Constructs a HingeBase.

         * @param htype the hinge type
         */
        HingeBase(HingeType htype)
            : _hinge_type(htype) {}

        /**
         * @brief Returns the type string of the HingeBase.
         *
         * @param brief if true, return the short form of the class type name, else the full type
         *        name
         * @return The type string.
         */
        virtual std::string_view typeString(bool brief) const noexcept = 0;

        /**
         * @brief HingeBase destructor.
         */
        virtual ~HingeBase(){};

        /**
         * @brief Return the name of the hinge instance
         *
         * @return the hinge name
         */
        virtual std::string_view name() const = 0;

        /**
         * @brief Return the SubhingeBase subhinge instance at the specified index
         *
         * @param index the subhinge index
         * @return the subhinge object
         */
        kc::ks_ptr<SubhingeBase> subhinge(size_t index) const;

        /**
         * @brief Return the number of subhinges in the hinge
         * @return the number of subhinges
         */
        size_t nSubhinges() const { return _subhinges_list.size(); }

        /**
         * @brief Return the total nU dofs from all the subhinges
         *
         * @returns the total number of U coordinates across the subhinges
         */
        size_t nU() const;

        /** @brief Return the HingeType hinge type for this hinge.
         *  @returns The hinge type used by this body.
         */
        HingeType hingeType() const { return _hinge_type; }

        /**
         * @brief Helper method to return the string name for a HingeType hinge type
         * @param htype the hinge type
         * @return the hinge type as a string
         */
        static std::string hingeTypeString(HingeType htype);

      public:
        /**
         * @brief Return the CoordData for the hinge's list of subhinges
         *
         * @return the CoordData for the subhinges
         */
        const kc::ks_ptr<CoordData> &coordData() const { return _hinge_coord_data; }

        /**
         * @brief Return the list of SubhingeBase subhinges
         * @return the list of subhinges
         */
        const kc::RegistryList<SubhingeBase> &subhinges() const { return _subhinges_list; }

        /** @brief 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.
         */
        struct HingeParams {
            km::UnitQuaternion i_to_onode_q =
                km::UnitQuaternion(0, 0, 0, 1); //!< required onode orientation with respect to the
                                                //!< constraint frame on the inboard body
            km::UnitQuaternion j_to_pnode_q =
                km::UnitQuaternion(0, 0, 0, 1); //!< required pnode orientation with respect to the
                                                //!< constraint frame on the outboard body
            km::Mat axes; //!< 3xm matrix with columns defining the 1-dof subhinge axes
        };

        /**
         * @brief 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
         * @return struct with the hinge onode, pnode and axis parameter values
         */
        static HingeParams getHookeHingeParams(const km::UnitQuaternion &ij_q);

        /**
         * @brief 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
         *
         * @return struct with the hinge onode, pnode and axis parameter values
         */
        static HingeParams getInlineHingeParams();

        /**
         * @brief 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
         *
         * @return struct with the hinge onode, pnode and axis parameter values
         */
        static HingeParams getInplaneHingeParams();

        /**
         * @brief 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
         * @return struct with the hinge onode, pnode and axis parameter values
         */
        static HingeParams getPerpendicularHingeParams(const km::UnitQuaternion &ij_q);

        /**
         * @brief 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.
         *
         * @return struct with the hinge onode, pnode and axis parameter values
         */
        static HingeParams getParallelHingeParams();

      protected:
        /**
         * @brief The overall pframe coordinate map matrix for the hinge
         *
         * Return the overall 6xnU() coord map matrix for the hinge in the
         * pframe frame from all of its subhinges. Note that the matrix will
         * be configuration dependent when there are multiple subhinges. This
         * method is specialized by PhysicalHinge and CompoundHinge hinges.
         *
         * @return the coordinate map matrix
         */
        virtual km::Mat _pframeCoordMapMatrix() const = 0;

        /**
         * @brief Return the orthogonal complement for the pframeCoordMapMatrix() matrix
         *
         * Compute the orthogonal complement (OC) of the pframe coord
         * map matrix computed by pframeCoordMapMatrix(). The product of
         * this OC with the pframe coord map matrix is zero.
         *
         * @return the orthogonal complement matrix
         */
        km::Mat _pframeCoordMapMatrixOrthoComplement() const;

        /**
         * @brief Return the orthogonal complement for the oframe coordinate map matrix
         *
         * Compute the orthogonal complement (OC) of the pframe coord map
         * matrix. The product of the OC with the oframe coord map matrix
         * is zero.
         *
         * @return the orthogonal complement matrix
         */
        km::Mat _oframeCoordMapMatrixOrthoComplement() const;

        /**
         * @brief Return list of singular values for the hinge's pframe coord map matrix
         *
         * This method is handy for monitoring potential loss in rank for
         * hinges such as ujoint and gimbal hinges. For full rank, there
         * should be nu() singular values.
         *
         * @return Array of singular values.
         */
        km::Vec _pframeCoordMapSingularValues() const;

        /** @brief The coordinate map matrix across all subhinges in the onode frame
            @return the coordinate map matrix
        */
        virtual km::Mat _oframeCoordMapMatrix() const // NOLINT(readability-identifier-naming)
        {
            return km::Mat(0, 0);
        }

        /// ordered list of subhinges
        kc::RegistryList<SubhingeBase> _subhinges_list;

        /** the hinge type */
        HingeType _hinge_type;

        /** the list of subhinge types for the hinge */
        std::vector<SubhingeType> _subhinge_types;

        /** the CoordData for the hinge's subhinge coordinates */
        kc::ks_ptr<CoordData> _hinge_coord_data = nullptr;
    };

} // namespace Karana::Dynamics