HC_API.h Source File

[[PREPROC_HEADER_GUARD_BEGIN]]
 
 
#include <condition_variable>
#include <deque>
#include <iostream>
#include <math.h>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>
#include <functional>
 
 
[[PREPROC_NOPROC_START]]
#ifdef _WIN32    // Windows platform
#ifdef HC_EXPORTS// Define this when building the DLL
#define HC_API __declspec(dllexport)
#else
#define HC_API __declspec(dllimport)
#endif
#else            // Non-Windows platforms (Linux, macOS, etc.)
#ifdef HC_EXPORTS// Define this when building the shared library
#define HC_API __attribute__((visibility("default")))
#else
#define HC_API
#endif
#endif
[[PREPROC_NOPROC_END]]
 
 
#define HC_LOG_DEVICE_NAME_LEN (20)
 
#define HC_SWIG_SHAREDPTR(CLASSNAME)
 
#define HC_CLASS_META(CLASSNAME)                                     \
    HC_SWIG_SHAREDPTR(CLASSNAME)                                     \
    static std::string staticClassName() { return #CLASSNAME "\0"; } \
    virtual std::string className() override { return #CLASSNAME "\0"; } \
 
#define HC_CLASS_META_BASE(CLASSNAME)                                     \
    HC_SWIG_SHAREDPTR(CLASSNAME)                                     \
    static std::string staticClassName() { return #CLASSNAME "\0"; } \
    virtual std::string className() { return #CLASSNAME "\0"; } \
 
#define HC_CLASS_META_BASIC_FACTORY_BASE(CLASSNAME)                                     \
    virtual std::shared_ptr<CLASSNAME> createSharedPtr() { return std::make_shared<CLASSNAME>(); }
 
#define HC_CLASS_META_BASIC_FACTORY(CLASSNAME, BASECLASSNAME)                                     \
    virtual std::shared_ptr<BASECLASSNAME> createSharedPtr() override { return std::make_shared<CLASSNAME>(); }
 
#define HC_CLASS_DEVICECOMMANDPACKAGE_META(CLASSNAME) \
    HC_CLASS_META_BASIC_FACTORY(CLASSNAME, DeviceCommandPackage) \
    HC_CLASS_META(CLASSNAME) \
 
#define HC_CLASS_DEVICEINFO_META(CLASSNAME, COMMANDSTATUSNAME) COMMANDSTATUSNAME* addCommand(DeviceCommandPackage* package) { auto cs = api->addDeviceCommandDevId(this->apiDeviceId, package); return dynamic_cast<COMMANDSTATUSNAME*>(cs); }
 
#define HC_CLASS_META_NO_BINDINGS(CLASSNAME)//ignore class in python generation.
 
 
 
namespace spdlog {
    class logger;
}
 
 
namespace ControlAPI {
 
    int HC_API throwTestException();
 
    int HC_API raiseTestSIGSEG();
 
    void HC_API printTestMessage();
 
    void HC_API printTestErrorMessage();
 
    void HC_API printTestErrorThrowMessage();
 
#ifdef HC_API_MACRO_EXCLUDE_DOCS
    void HC_API signalHandler(int signum);
#endif
 
    std::string HC_API logLocation(int index);
 
    void HC_API addLogPath(std::string logFilePath);
 
 
    //full path to HC_API_Library at runtime.
    std::string HC_API getRuntimeLibraryPath();
 
    //full path to main runtime dependancies.
    std::string HC_API getRuntimeDependancyPath();
 
#ifdef HC_API_MACRO_EXCLUDE_DOCS
    void HC_API basicPointerTest(int* number_in_out);
 
    class HC_API ICTestObj { public: virtual ~ICTestObj() = default; int n = 0; };
    class HC_API ICDerivedTestObj : public ICTestObj {public: virtual ~ICDerivedTestObj() = default; int m = 0;};
    void HC_API basicObjectTest(ICTestObj* obj);
#endif
 
#if defined(HC_API_FEATURE_NETWORKING)
    void HC_API networkMQTTConnect(std::string brokerHostName, int port = 1883);
 
    void HC_API networkMQTTDisconnect();
#endif
 
 
#ifdef HC_API_MACRO_EXCLUDE_DOCS
#ifdef HC_API_MATLAB_BUILD
 
        //int HC_API matlabArrayTest(std::vector<ICTestObj> objArray);
        int HC_API matlabArrayTest2(ICTestObj objArray[], int len);
#endif
#endif
 
 
    //base class for any type of hardware
    struct HC_API HardwareInfo {
        HC_SWIG_SHAREDPTR(HardwareInfo)
        int apiDeviceId = -1;
        std::string alias;
    };
 
    struct HC_API PhysicalAxisControlInfo {
        HC_SWIG_SHAREDPTR(PhysicalAxisControlInfo)
        float minPosLimit = 0;
        float maxPosLimit = 0;
 
        float minVelLimit = 1.0f;
        float maxVelLimit = 50.0f;
 
        float minAccLimit = 1.0f;
        float maxAccLimit = 10.0f;
 
        bool isRadial = false;
 
        bool submittedToApi = false;
    };
 
    class CommandStatus;
    class HC_API CommandStateInfo {
    public:
        HC_CLASS_META_BASE(CommandStateInfo)
        HC_SWIG_SHAREDPTR(CommandStateInfo)
        virtual ~CommandStateInfo() = default;
 
#ifdef HC_API_FEATURE_NETWORKING
        virtual void cacheOnNetwork(CommandStatus* commandStatus);
#endif
 
        float percentFinished = 0.0f;
    };
 
 
 
 
 
    class HC_API ApiCommandPackage {
    public:
        HC_CLASS_META_BASE(ApiCommandPackage)
        HC_SWIG_SHAREDPTR(ApiCommandPackage)
        friend class ControlSystem;
 
        virtual ~ApiCommandPackage() = default;
 
 
#ifdef HC_API_MACRO_EXCLUDE_DOCS
        virtual std::shared_ptr<CommandStateInfo> createCommandStateInfo();//TODO - PIMPL
        virtual std::shared_ptr<CommandStatus> createCommandStatus();//TODO - PIMPL
#endif
 
 
        std::string alias;
 
 
    private:
        bool submitted = false;
    };
 
 
    class HC_API DeviceCommandPackage : public ApiCommandPackage {
    public:
        HC_CLASS_META(DeviceCommandPackage)
        HC_SWIG_SHAREDPTR(DeviceCommandPackage)
        HC_CLASS_META_BASIC_FACTORY_BASE(DeviceCommandPackage)
        virtual ~DeviceCommandPackage() = default;
 
        friend class CommandStatus_Internals;
 
        virtual void cloneFrom(DeviceCommandPackage* other);//TODO - PIMPL
 
#ifdef HC_API_MACRO_EXCLUDE_DOCS
#ifdef HC_API_FEATURE_NETWORKING
        virtual void syncFromNetwork(CommandStatus* command);//TODO - PIMPL
#endif
        virtual void copyFromStateInfo(CommandStateInfo* other);//TODO - PIMPL
#endif
 
 
        virtual DeviceCommandPackage* prepareUpdatePackage();
 
 
        void markUpdatePackageReady();
 
        bool continuous = false;
 
 
        
    private:
        #ifdef HC_API_MACRO_EXCLUDE_DOCS
            bool updatePackageReady = false;//TODO - PIMPL
            std::shared_ptr<DeviceCommandPackage> updatePackage = nullptr;//TODO - PIMPL
            void copyFromUpdatePackage();//TODO - PIMPL
        #endif
    };
 
 
    class HC_API MovementCommandPackage : public DeviceCommandPackage {
    public:
        HC_CLASS_DEVICECOMMANDPACKAGE_META(MovementCommandPackage)
        MovementCommandPackage();
        virtual ~MovementCommandPackage() = default;
 
 
        virtual void cloneFrom(DeviceCommandPackage* other) override;//TODO - PIMPL
#ifdef HC_API_MACRO_EXCLUDE_DOCS
#ifdef HC_API_FEATURE_NETWORKING
        virtual void syncFromNetwork(CommandStatus* command) override;//TODO - PIMPL
#endif
        virtual std::shared_ptr<CommandStateInfo> createCommandStateInfo() override;//TODO - PIMPL
        //virtual std::shared_ptr<CommandStatus> createCommandStatus();
 
 
#endif
 
 
        enum Units {
            Units_Millimeters, 
            Units_Degrees
        };
 
 
        float disp_target = 0.0f;
 
        float vel_target = 0.0f;
 
        float acc_target = 0.0f;
 
        bool disp_absolute = true;
 
        bool trackDisp = true;
 
        bool trackVel = true;
 
        bool trackAcc = true;
 
        Units units;
 
    };
 
 
    class HC_API MonitorCommandPackage : public DeviceCommandPackage {
    public:
        HC_CLASS_DEVICECOMMANDPACKAGE_META(MonitorCommandPackage)
        virtual ~MonitorCommandPackage() = default;
    };
 
    class HC_API TimeDelayDeviceCommand : public DeviceCommandPackage {
    public:
        HC_CLASS_META(TimeDelayDeviceCommand)
        HC_SWIG_SHAREDPTR(TimeDelayDeviceCommand)
        virtual ~TimeDelayDeviceCommand() = default;
 
 
 
        float time_s = 5.0f;
    };
 
    class HC_API SynchronizeDeviceCommand : public DeviceCommandPackage {
    public:
        HC_CLASS_META(SynchronizeDeviceCommand)
        HC_SWIG_SHAREDPTR(SynchronizeDeviceCommand)
        friend class DeviceController;
        friend class ControlSystem;
        //friend class SynchronizeDeviceCommand_Serializer;
 
        SynchronizeDeviceCommand();
        
 
        virtual ~SynchronizeDeviceCommand() = default;
 
 
    protected:
#ifdef HC_API_MACRO_EXCLUDE_DOCS
        int numDevices = 0;
        int deviceWaitCounter = 0;
 
        std::shared_ptr<std::condition_variable> synchronizationNotification;//TODO - PIMPL
        std::shared_ptr<std::mutex> synchronizationMutex;//TODO - PIMPL
#endif
    };
 
 
 
 
    
 
 
 
 
    class HC_API MovementStateInfo : public CommandStateInfo {
    public:
        HC_CLASS_META(MovementStateInfo)
        HC_SWIG_SHAREDPTR(MovementStateInfo)
        virtual ~MovementStateInfo() = default;
 
#ifdef HC_API_MACRO_EXCLUDE_DOCS
#ifdef HC_API_FEATURE_NETWORKING
        virtual void cacheOnNetwork(CommandStatus* commandStatus) override;
#endif
#endif
        //starting position
        float referencePos = 0.0f;
 
        //target position
        float currentTargetPos = 0.0f;
 
        //current position
        float currentPos = 0.0f;
 
        //target velocity 
        float currentTargetVel = 0.0f;
 
        //current velocity
        float currentVel = 0.0f;
 
        //target velocity 
        float currentTargetAcc = 0.0f;
 
        //current acceleration
        float currentAcc = 0.0f;
 
        //direction -1 or 1 indicator
        int signedDir = 0;
        
        //true if in the process of homing.
        bool homing = false;
 
        //true if the device is at homed state.
        bool isHomed = false;
    };
    class HC_API CommandStatusControlMethods {
        public:
        HC_CLASS_META_BASE(CommandStatusControlMethods)
 
        
        virtual bool runFull() = 0;
 
 
        virtual bool runASync() = 0;
 
        virtual bool initialize() = 0;
 
 
        virtual bool update(bool stepped = false) = 0;
 
        
 
        virtual bool waitUpdateReady() = 0;
 
 
        virtual bool waitUpdateReadyOrFinished() = 0;
 
 
 
        virtual void waitFinished() = 0;
 
 
        virtual void stop() = 0;
 
        virtual bool isBusy() const = 0;
 
        // @brief returns true if the command is waiting to start its next update step.
        virtual bool isUpdateStepReady() const = 0;
 
        virtual bool isFinished() const = 0;
 
        virtual bool isCancelled() const = 0;
 
        // @brief  returns true if the command was successfull. (finished and no failure and not cancelled)
        virtual bool isSuccessful() const = 0;
    };
 
 
 
 
    class CommandStatus_Internals;
    class ControlSystem;
    class DeviceInfo;
    class DeviceController;
    class HC_API CommandStatus : public  CommandStatusControlMethods {
    public:
        HC_CLASS_META(CommandStatus)
        HC_SWIG_SHAREDPTR(CommandStatus)
 
        friend class ControlSystem;
        friend class ControlSystem_Internals;
        friend class CommandStatus_Internals;
        friend class DeviceController;
        friend class DeviceInfo;
 
        CommandStatus();
        virtual ~CommandStatus();
 
 
 
        virtual bool runFull() override;
        virtual bool runASync() override;
        virtual bool initialize() override;
        virtual bool update(bool stepped = false) override;
        virtual bool waitUpdateReady() override;
        virtual bool waitUpdateReadyOrFinished() override;
        virtual void waitFinished() override;
        virtual void stop() override;
        virtual bool isBusy() const override;
        virtual bool isUpdateStepReady() const override;
        virtual bool isFinished() const override;
        virtual bool isCancelled() const override;
        virtual bool isSuccessful() const override;
 
 
        int apiId() const;
        int deviceApiId() const;
 
        CommandStateInfo *stateInfo();
 
 
        DeviceCommandPackage *commandPackage();
 
 
        ControlSystem *controlSystem();
 
 
        DeviceInfo *deviceInfo();
 
 
        DeviceController *deviceController();
 
 
        std::string alias;
 
 
 
 
#ifdef HC_API_MACRO_EXCLUDE_DOCS
 
 
 
        std::shared_ptr<CommandStatus> nextCommand = nullptr;
        std::shared_ptr<CommandStatus> prevCommand = nullptr;
        DeviceCommandPackage* commandPackage_ = nullptr;
 
 
 
        std::shared_ptr<CommandStatus_Internals> internals;
 
        bool busy = false;
        bool cancelled = false;
        bool failed = false;
 
#endif
    private:
        std::shared_ptr<CommandStateInfo> stateInfo_;
 
        bool autoAdvance = true;
        bool finished = false;
 
 
 
 
        bool preUpdateWaiting = false;
 
        int apiCommandId = -1;
        int apiDeviceId = -1;
 
        ControlSystem *system = nullptr;
        DeviceInfo *device = nullptr;
    };
 
    class ControlSystem;
    class DeviceController;
    class DeviceInfo_Internal;
    
    class HC_API DeviceInfo : public HardwareInfo {
    public:
        HC_CLASS_META_BASE(DeviceInfo)
        HC_SWIG_SHAREDPTR(DeviceInfo)
        DeviceInfo();
        virtual ~DeviceInfo();
 
        friend class ControlSystem;
        friend class DeviceController;
        friend class CommandStatus;
 
        #ifdef HC_API_MACRO_EXCLUDE_DOCS
 
            CommandStatus* activeCommand = nullptr;
        #endif
        bool preLoopCommandCheck(bool checkCancelled = true);
 
        bool isConnected() const;
 
        void setEnableCommandLogging(bool enable);
 
        void setCommandLoggingLevel(int level);
 
        bool commandLoggingEnabled() const;
        int commandLoggingLevel() const;
 
 
        //initialize a command package from the current state of the device. Alters commandPackage.
        virtual DeviceCommandPackage* initializeCommand(DeviceCommandPackage* commandPackage);
 
        //add a command to the device. return generic command status object.  use addCommand for normal use which will return a specific CommandStatus type.
        CommandStatus* addCommandGeneric(DeviceCommandPackage* package);
 
        DeviceController *deviceController() ;
 
        ControlSystem *controlSystem();
 
    protected:
    #ifdef HC_API_MACRO_EXCLUDE_DOCS
 
        std::shared_ptr<DeviceInfo_Internal> internal;
 
 
        DeviceController *controller = nullptr;
 
        ControlSystem* api = nullptr;
 
        bool connected = false;
        bool loggingEnabled = true;
        int loggingLevel = 0;
    #endif
    };
 
    class HC_API CommandCallbacks {
    public:
        HC_CLASS_META_BASE(CommandCallbacks)
        HC_SWIG_SHAREDPTR(CommandCallbacks)
        virtual ~CommandCallbacks() = default;
 
        virtual void onCommandFinished(CommandStatus *commandStatus, DeviceInfo *deviceInfo);
 
        virtual void onCommandUpdate(CommandStatus *commandStatus, DeviceInfo *deviceInfo);
    };
 
 
    class HC_API LoggerFunctionality {
    public:
        HC_CLASS_META_BASE(LoggerFunctionality)
        HC_SWIG_SHAREDPTR(LoggerFunctionality)
 
        virtual ~LoggerFunctionality() = default;
 
        std::shared_ptr<spdlog::logger> getLogger();
 
        std::string loggerName();
 
        
        protected:
            std::shared_ptr<spdlog::logger> logger;        
            ControlSystem* controlSystem = nullptr;
 
    };
 
    class ControlSystem_Internals;
    class HC_API ControlSystem : public LoggerFunctionality {
    public:
        HC_CLASS_META(ControlSystem)
        HC_SWIG_SHAREDPTR(ControlSystem)
 
        friend class LoggerFunctionality;
        friend class ControlSystem_Internals;
 
        ControlSystem();
        ControlSystem(ControlSystem& system);
        virtual ~ControlSystem();
 
 
        void addDeviceController(DeviceController* controller);
 
 
        virtual void initializeDevices();
 
        virtual void initializeController(DeviceController* controller);
 
        virtual void unInitialize();
 
        void muteConsole();
 
        void unMuteConsole();
 
 
        //Easy API functions
        CommandStatus *delay(std::string deviceAlias, float time_s);
        CommandStatus *delay(DeviceInfo *devInfo, float time_s);
 
        CommandStatus* addDeviceCommand(DeviceInfo* device, DeviceCommandPackage* package);
 
 
        CommandStatus* addDeviceCommandAlias(std::string deviceAlias, DeviceCommandPackage* package);
        
        CommandStatus *addDeviceCommandDevId(int deviceId, DeviceCommandPackage* package);
 
 
        DeviceInfo *getDeviceFromAlias(std::string deviceAlias);
 
        DeviceController *getControllerFromAlias(std::string controllerAlias);
 
 
 
#ifndef HC_API_MATLAB_PUBLIC_INTERFACE
        void runFullCommandListSeq(std::vector<CommandStatus *> commandList);
 
        void runFullCommandListParallel(std::vector<CommandStatus *> commandList);
 
        void runASyncCommandList(std::vector<CommandStatus *> commandList);
 
        void waitFinishedCommandList(std::vector<CommandStatus *> commandList);
#endif
 
 
        void setCommandCallback(std::shared_ptr<CommandCallbacks> callbackObj);
 
 
#ifdef HC_API_MACRO_EXCLUDE_DOCS
    std::shared_ptr<ControlSystem_Internals> internals;
 
#endif
 
    protected:
#ifdef HC_API_MACRO_EXCLUDE_DOCS
 
        
        void issueNewCommands();
 
 
        void packagePreCheck(DeviceCommandPackage *package);
 
 
        DeviceInfo *getDeviceFromDeviceId(int deviceId);
        DeviceController *getControllerFromDeviceId(int deviceId);
 
        CommandStatus* getBusyCommandFromDeviceId(int deviceId);
        int getDeviceIdFromAlias(std::string alias);
 
 
        std::vector<DeviceInfo*> getAllDevices();
 
 
        virtual CommandStatus* addDeviceCommand_Alias(std::string deviceAlias, DeviceCommandPackage* package);
        virtual CommandStatus* addDeviceCommand_Id(int deviceId, DeviceCommandPackage* package);
 
 
 
        std::shared_ptr<CommandCallbacks> mCallbackObj;
 
 
 
#endif
    };
 
 
    class HC_API DeviceController : public LoggerFunctionality {
    public:
        HC_CLASS_META(DeviceController)
        HC_SWIG_SHAREDPTR(DeviceController)
 
        friend class DeviceInfo;
        friend class ControlSystem;
 
        virtual ~DeviceController();
 
 
#ifdef HC_API_MACRO_EXCLUDE_DOCS
 
        //initialization function - called when controller is added to control system.  connects to serial ports, interfaces, etc.
        virtual bool init();
 
        //de-initialization function. called on disconnect.
        virtual bool deInit();
 
        virtual bool issueCommand(CommandStatus* command);
        //virtual bool CancelCommand(std::shared_ptr<CommandStatus> command);
        DeviceInfo* getDeviceInfoFromDeviceId(int apiDeviceId);
#endif
 
        virtual bool checkCommandPackage(int deviceId, DeviceCommandPackage* package);
 
 
        void addDeviceInfo(DeviceInfo* dev);
 
        void removeDeviceInfo(DeviceInfo* dev);
 
 
        void setDisconnectCallback(std::function<void(bool)> callback);
 
 
 
        std::string alias;
 
        std::string port;
 
        virtual void disconnect(bool expected = false);
 
        bool isConnected() { return connected; }
 
        int apiId() { return apiUniqueId; }
 
        void setSimulated(bool simulated);
 
        bool isSimulated();
 
 
    protected:
#ifdef HC_API_MACRO_EXCLUDE_DOCS
 
        ControlSystem *api = nullptr;
 
        std::vector<DeviceInfo*> mDeviceInfoList;
 
 
        float devicePollPeriodS = 0.1f;
 
        std::shared_ptr<std::thread> watchDogThread;
        bool watchDogEnabled = false;
 
 
        int apiUniqueId = 0;
 
        bool connected = false;
 
        bool initialized = false;
 
        bool simulated = false;
 
        std::function<void(bool)> disconnectCallback;
 
#endif
 
 
    };
 
 
    //casts for swig
 
    HC_API MovementStateInfo *As_MovementStateInfo(CommandStateInfo *obj);
    HC_API MovementCommandPackage *As_MovementCommandPackage(DeviceCommandPackage *obj);
 
    class HC_API Vector3D {
    public:
        Vector3D();
        Vector3D(float x, float y, float z);
        
        float x;
        float y;
        float z;
 
        bool IsZero();
    };
 
}// namespace ControlAPI
 
 
[[PREPROC_HEADER_GUARD_END]]