Program Listing for File FrameContainer.h

Program Listing for File FrameContainer.h#

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

#pragma once

#include <memory>
#include <string>

#include "Karana/Frame/OrientedChainedFrameToFrame.h"
#include "Karana/KCore/LockingBase.h"
#include "Karana/KCore/UsageTrackingMap.h"

#include "Karana/Frame/EdgeFrameToFrame.h"
#include "Karana/Frame/Frame.h"
#include "Karana/KCore/Tree.h"

namespace Karana::Frame {
    class Frame;
    class SpiceFrameToFrame;

    namespace kc = Karana::Core;

    /**
     * @class FrameContainer
     * @brief A container class for managing frames and their relationships.
     *
     * This class provides functionality to create, register, and manage frames,
     * as well as establish relationships between frames.
     *
     * See \sref{frames_layer_sec} for more discussion on
     * the frames layer.
     */
    class FrameContainer : public kc::LockingBase {

        // for access to _edgeOrientation
        friend class FrameToFrame;

        // For access to container elements for discard
        friend class Frame;
        friend class EdgeFrameToFrame;
        friend class ChainedFrameToFrame;
        friend class OrientedChainedFrameToFrame;

        // for access to _spce_f2fs_list
        friend class SpiceFrameToFrame;
        friend class SpiceFrame;

        // for access to trackUsage methods
        friend class PrescribedFrameToFrame;

      public:
        /**
         * @brief Constructs a FrameContainer with a root frame.
         */
        FrameContainer();

        /**
         * @brief FrameContainer destructor.
         */
        virtual ~FrameContainer();

        /**
         * @brief Create a FrameContainer.
         * @param root_frame_name Name for the root frame
         * @return The frame container.
         */
        static kc::ks_ptr<FrameContainer> create(std::string_view root_frame_name);

        /** options struct for dumpString */
        struct DumpOptions : LockingBase::DumpOptions {

            bool frames = false;   ///< frames usage map
            bool edges = false;    ///< edge usage map
            bool oriented = false; ///< oriented f2fs usage map
            bool chains = false;   ///< regular chains usage map

            /**
             * @brief Copy assignment operator.
             *
             * @param p DumpOptions to copy from.
             * @return A reference to the assigned DumpOptions.
             */
            DumpOptions &operator=(const DumpOptions &p) {
                if (this != &p) {
                    LockingBase::DumpOptions::operator=(p); // Call base class assignment operator
                    // Assign Derived-specific members here
                    frames = p.frames;
                    edges = p.edges;
                    oriented = p.oriented;
                    chains = p.chains;
                }

                return *this;
            }
        };

        /**
         * @brief Return a formatted string containing information about this object.
         *
         * @param prefix String prefix to use for formatting.
         * @param options Dump options (if null, defaults will be used).
         * @return A string representation of the object.
         */
        std::string dumpString(std::string_view prefix = "",
                               const Base::DumpOptions *options = nullptr) const override;

        /**
         * @brief Returns the root frame of the tree.
         * @return The root frame.
         */
        const kc::ks_ptr<Frame> &root() const;

        /**
         * @brief Return a vector of all Frames with the given name.
         * @param name name of the Frame instances to look up
         * @return A vector of all the Frames with the given name.
         */
        std::vector<kc::ks_ptr<Frame>> lookupFrame(std::string_view name);

        /**
         * @brief 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
         * @return True if oframe is an ancestor of pframe, false otherwise.
         */
        bool isAncestorOf(const Frame &oframe, const Frame &pframe, bool strict);

        /**
         * @brief Gets the common ancestor of two frames.
         * @param frame1 The first frame.
         * @param frame2 The second frame.
         * @return The common ancestor frame.
         */
        const kc::ks_ptr<Frame> &getAncestor(const Frame &frame1, const Frame &frame2);

      public:
        /* these are public for use by SOADyn */

        /**
         * @brief Method to track usage of a Frame instance.
         *
         * These methods need to be public to allow specialized classes
         * (e.g., multibody) ones to call them
         *
         * @param frame the new Frame to track
         */
        void trackUsageFrame(const kc::ks_ptr<Frame> &frame);

        /**
         * @brief Method to track usage of an EdgeFrameToFrame instance.
         *
         * These methods need to be public to allow specialized classes
         * (e.g., multibody) ones to call them
         *
         * @param f2f the new EdgeFrameToFrame to track
         */
        void trackUsageEdgeFrameToFrame(const kc::ks_ptr<EdgeFrameToFrame> &f2f);

        /**
         * @brief Method to track usage of an OrientedChainedFrameToFrame instance.
         *
         * These methods need to be public to allow specialized classes
         * (e.g., multibody) ones to call them
         *
         * @param of2f the new Frame to track
         */
        void
        trackUsageOrientedChainedFrameToFrame(const kc::ks_ptr<OrientedChainedFrameToFrame> &of2f);

        /**
         * @brief Method to track usage of an ChainedFrameToFrame instance.
         *
         * These methods need to be public to allow specialized classes
         * (e.g., multibody) ones to call them
         *
         * @param cf2f the new Frame to track
         */
        void trackUsageChainedFrameToFrame(const kc::ks_ptr<ChainedFrameToFrame> &cf2f);

        /** @brief Return a vector of all the ChainedFrameToFrames in the FrameContainer.
         *
         * @return List of all the chain elements.
         */
        std::vector<kc::ks_ptr<ChainedFrameToFrame>> chainedFrameToFrames();

      public:
        /** @brief Return a vector of all the frames in the FrameContainer.
         *
         * @return List of all the frame elements.
         */
        std::vector<kc::ks_ptr<Frame>> frames();

        /** @brief Return a vector of all the EdgeFrameToFrames in the FrameContainer.
         *
         * @return List of all the edge elements.
         */
        std::vector<kc::ks_ptr<EdgeFrameToFrame>> edgeFrameToFrames();

        /** @brief Freeze the OrientedChainedFrameToFrame that connects this frame to the root.
         *         This will effectively freeze all edges in the path.
         *
         * @param frame the downstream terminal frame
         */
        void freezeUpstream(const kc::ks_ptr<Frame> &frame);

        /** @brief Unfreeze the OrientedChainedFrameToFrame that connects this frame to the root.
         *         This will effectively unfreeze all edges in the path.
         *
         * @param frame the downstream terminal frame
         */
        void unfreezeUpstream(const kc::ks_ptr<Frame> &frame);

        /**
         * @brief Set the ephemeris time
         *
         * The ephemeris time is needed by Spice frames
         *
         * @param ephemeris_time the ephemeris time
         */
        void setEphemerisTime(double ephemeris_time);

        /**
         * @brief Return the current ephemeris time
         *
         * The ephemeris time is needed by Spice frames
         *
         * @return the current ephemeris time
         */
        double getEphemerisTime();

        /**
         * @brief Return true if this FrameContainer is using spice frames, false otherwise.
         *
         * @return true if this FrameContainer is using spice frames, false otherwise.
         */
        bool isUsingSpice();

        /**
         * @brief Display the frame tree hierarchy starting from a specific frame
         *
         * @param prefix the string prefix for each line of the displayed output
         * @param f the root Frame for the start of the tree display
         * @param callback the function to generate each frame's display string
         */
        void dumpFrameTree(std::string_view prefix,
                           const Frame &f,
                           const std::function<std::string(const Frame &)> &callback) const;

        /**
         * @brief Return the frame ids tracking their hierarchy
         *
         * @returns the ids tree
         */
        const std::unique_ptr<const kc::Tree<kc::id_t>> &tree() { return _tree; }

      protected:
        /**
         * @brief - Discard the FrameContainer.
         * @param base - Pointer to the FrameContainer.
         */
        void _discard(kc::ks_ptr<Base> &base) override;

        // void _ensureTree();
        void _makeNotHealthy() override;
        void _makeHealthy() override;

        /**
         * @brief Return true if the sub_f2f path is contained within the
         *        f2f's oframe/pframe path and oriented with the path, false
         *        if it has opposed orientation, and nullopt if it is not full
         *        contained on the path at all.
         *
         * @param f2f The frame to frame we want to check if sub_f2f is contained within.
         * @param sub_f2f The sub-frame this method checks is contained within f2f.
         * @returns true if the sub_f2f path is contained within the f2f's oframe/pframe path,
         *          false if it has opposed orientation, and nullopt if it is not contained
         *          in the path.
         */
        std::optional<bool> _subchainOrientation(const FrameToFrame &f2f,
                                                 const FrameToFrame &sub_f2f) const;

        /** List of all SpiceFrameToFrame instances */
        kc::RegistryList<FrameToFrame> _spice_f2fs_list;

      private:
        kc::UsageTrackingMap<kc::id_t, Frame> _frame_usage_map;
        kc::UsageTrackingMap<kc::id_t, EdgeFrameToFrame> _edge_usage_map;
        kc::UsageTrackingMap<std::pair<kc::id_t, kc::id_t>, ChainedFrameToFrame> _chain_usage_map;
        kc::UsageTrackingMap<std::pair<kc::id_t, kc::id_t>, OrientedChainedFrameToFrame>
            _oriented_chain_usage_map;
        mutable std::unique_ptr<const kc::Tree<kc::id_t>> _tree;

        kc::ks_ptr<Frame> _root_frame;
        double _ephemeris_time = km::notReadyNaN;
    };
} // namespace Karana::Frame