Program Listing for File CoordData.h

Program Listing for File CoordData.h#

Return to documentation for file (include/Karana/SOADyn/CoordData.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 CoordData class.
 */

#pragma once

#include "Karana/KCore/LockingBase.h"
#include "Karana/KCore/RegistryList.h"
#include "Karana/KCore/Tree.h"
#include "Karana/Math/Defs.h"
#include "Karana/SOADyn/CoordBase.h"

#include <map>
#include <vector>

namespace Karana::Dynamics {

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

    class BodyBase;
    class SubhingeBase;
    class HingePnode;
    class LoopConstraint;

    /**
     * @class CoordData
     * @brief Class for managing coordinates for managing a set of CoordBase coordinate provider
     * objects. See the \sref{coord_data_sec} section for more information on this class.
     */
    class CoordData : public kc::LockingBase {

        /* for access to _setupOrientationMap */

        /* for acced to _coord_obj_list */
        friend class FrameToFrameJacobianGenerator;
        friend class CompoundSubhinge;

        /* for access to _coord_objs_list */
        friend class ConstraintKinematicsSolver;

        /* for access to _coordOffsets() */
        friend class SubGraph;
        friend class SubTree;
        friend class Algorithms;

      public:
        /**
         * @brief CoordData creation static factory method.
         *
         * @param name instance name
         * @param coordobjs_list list of CoordBase objects to manage
         * @return a new CoordData instance
         */
        static kc::ks_ptr<CoordData>
        create(std::string_view name, const std::vector<kc::ks_ptr<CoordBase>> &coordobjs_list);

        /**
         * @brief Constructor. The constructor is not meant to be called
         *        directly.  Please use the create(...) method instead
         *        to create an instance.
         *
         * @param name instance name
         * @param coordobjs_list list of CoordBase objects to manage
         */
        CoordData(std::string_view name, const std::vector<kc::ks_ptr<CoordBase>> &coordobjs_list);

        /**
         * @brief Destructor
         */
        ~CoordData();

        /** @brief struct for tracking the offset for the generalized coordinates in
         the uber list for a collection of bodies and subhinges */
        struct CoordOffset {
            /// offset for the generalized coordinates
            size_t Q;

            /// offset for the generalized velocity coordinates
            size_t U;

            /// the CoordBase instance itself
            kc::ks_ptr<CoordBase> obj;
        };

        /**
         * @brief Return the Q coordinates as an array
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @return Array of values
         */
        km::Vec getQ() const;

        /**
         * @brief Return the U velocity coordinates as an array
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @return Array of values
         */
        km::Vec getU() const;

        /**
         * @brief Return the Udot acceleration coordinates as an array
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @return Array of values
         */
        km::Vec getUdot() const;

        /**
         * @brief Return the T generalized forces as an array
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @return Array of values
         */
        km::Vec getT() const;

        /**
         * @brief Return the Qdot rate coordinates as an array
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @return Array of values
         */
        km::Vec getQdot() const;

        /**
         * @brief Set the Q coordinates.
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @param vals Array of values.
         */
        void setQ(const Eigen::Ref<const km::Vec> &vals);

        /**
         * @brief Set the Q coordinates to a constant value
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @param fill_value Fill value.
         */
        void setQ(double fill_value);

        /**
         * @brief Set the U velocity coordinates.
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @param vals Array of values.
         */
        void setU(const Eigen::Ref<const km::Vec> &vals);

        /**
         * @brief Set the U velocity coordinates to a constant value
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @param fill_value Fill value.
         */
        void setU(double fill_value);

        /**
         * @brief Set the T generalized forces.
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @param vals Array of values.
         */
        void setT(const Eigen::Ref<const km::Vec> &vals);

        /**
         * @brief Set the T generalized forces to a constant value
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @param fill_value Fill value.
         */
        void setT(double fill_value);

        /**
         * @brief Set the Udot acceleration coordinates.
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @param vals Array of values.
         */
        void setUdot(const Eigen::Ref<const km::Vec> &vals);

        /**
         * @brief Set the Udot acceleration coordinates to a constant value
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @param fill_value Fill value.
         */
        void setUdot(double fill_value);

        /**
         * @brief The number of Q generalized coords for the CoordBase.
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @return the number of coordinates
         */
        size_t nQ() const;

        /**
         * @brief The number of U velocity coords for the CoordBase.
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @return the number of velocity coordinates
         */
        size_t nU() const;

        bool isReady() const override;

        /**
         * @brief 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.
         */
        void dumpState(std::string_view prefix, std::vector<std::string> filter = {"ALL"}) const;

        std::string
        dumpString(std::string_view prefix = "",
                   const Karana::Core::Base::DumpOptions *options = nullptr) const override;

        /**
         * @brief Check if a CoordBase instance belongs to this CoordData
         *
         * @param c The CoordBase to check for
         * @return True if the CoordBase instance belongs to the CoordData
         */
        bool contains(const CoordBase &c) const;

        /**
         * @brief Check if a obj with specified id instance belongs to this CoordData
         *
         * @param id The id to check for
         * @return True if the CoordBase instance belongs to the CoordData
         */
        bool contains(kc::id_t id) const;

        /**
         * @brief 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
         * @return A CoordOffset struct with the Q and U offsets
         */
        const CoordOffset &coordOffsets(const CoordBase &c) const;

        /**
         * @brief Returns coord obj and its coord offset corresponding to overall U offset
         *
         * The CoordData has get/set methods to pack and unpack 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.
         *
         * @param u_offset the input overall U offset value
         * @return The CoordBase instance and its local U coord offset
         */
        const std::pair<kc::ks_ptr<CoordBase>, size_t> coordAt(size_t u_offset) const;

        /**
         * @brief Get a vector of the CoordBase instances for this CoordData
         * @return A vector of CoordBase instances.
         */
        std::vector<kc::ks_ptr<CoordBase>> coordBases() { return _coord_objs_list.items(); };

        /**
         * @brief Return the CoordBase that is the closed parent to the specified one
         *
         * @param cb the CoordBase to check for
         * @return the CoordBase parent if it exists
         */
        kc::ks_ptr<CoordBase> parent(const CoordBase &cb) const;

        /**
         * @brief 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.
         * @returns A map representation of the CoordData object.
         */
        std::map<std::string, std::vector<km::Vec>> toMap();

      protected:
        /**
         * @brief Return the list of CoordBase children
         *
         * @param cb the CoordBase to check for
         * @return the list of children CoordBase
         */
        std::vector<kc::ks_ptr<CoordBase>> _children(const CoordBase &cb) const;

        /**
         * @brief Check whether a CoordBase is an ancestor of another
         *
         * @param anc the candidate CoordBase ancestor
         * @param desc the candidate CoordBase descendant
         * @param strict if true, a CoordBase cannot be its own ancestor
         * @return true if anc is an ancestor of desc
         */
        bool _isAncestorOf(const CoordBase &anc, const CoordBase &desc, bool strict) const;

        /**
         * @brief Return the common ancestor CoordBase
         *
         * @param first the first CoordBase
         * @param second the second CoordBase
         * @return the common ancestor CoordBase
         */
        kc::ks_ptr<CoordBase> _getAncestor(const CoordBase &first, const CoordBase &second) const;

        /**
         * @brief Method to combine CoordData instances
         *
         * Return a new CoordData containing the union of the CoordBase
         * elements from the input CoordData list
         *
         * @param cds List of CoordData to be combined
         * @param name the name for the merged CoordData
         * @return the merged CoordData
         */
        static kc::ks_ptr<CoordData> _mergeCoordData(const std::vector<kc::ks_ptr<CoordData>> &cds,
                                                     std::string_view name = "");

        /**
         * @brief Return a CoordOffset with the packing offsets for the CoordBase with the specified
         * id
         *
         * @param id the CoordBase id
         * @return the CoordOffset struct with the offset
         */
        const CoordOffset &_coordOffsets(kc::id_t id) const;

        /** Create the structure tree if it has not been created yet */
        void _makeTree() const;

        /**
         * @brief Set the local chart Q coordinates
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @param val Array of values.
         */
        void _localChartSetQ(const Eigen::Ref<const km::Vec> &val);

        /**
         * @brief Return the local chart Q coordinates  - without sanitizing coordinates
         *
         * See \sref{coords_sec} section for discussion on Q, U etc coordinates.
         *
         * @return Array of values.
         */
        km::Vec _localChartGetQ() const;

      protected:
        /** The total number of Q coordinates for this CoordData */
        size_t _nQ = 0;

        /** The total number of U coordinates for this CoordData */
        size_t _nU = 0;

        /// List of coord objs
        kc::RegistryList<CoordBase> _coord_objs_list;

        /// map of the coord offset for subhinges and body coordinates
        std::map<kc::id_t, CoordOffset> _coord_offsets;

        /// tree with the CoordBase hierarchy info
        mutable std::unique_ptr<const kc::Tree<kc::id_t>> _tree = nullptr;
    };

} // namespace Karana::Dynamics