Files
Plugin/Source/ThirdParty/include/SenseGlove/Core/HapticGloveCalibrationCheck.hpp
T

164 lines
6.4 KiBLFS
C++

/**
* @file
*
* @author Max Lammers <max@senseglove.com>
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "DeviceTypes.hpp"
#include "Platform.hpp"
namespace SGCore
{
/// <summary> Startup Stage used to indicate where of not a glove must be recalibrated. </summary>
enum class SGCORE_API ECalibrationStage : uint8_t
{
/// <summary> We've only just started up. User needs to move their hands so we know if we're still in the same sensor range. </summary>
MoveFingers,
/// <summary> After moving, we've determined that a calibration must happen for proper hand tracking to happen. </summary>
CalibrationNeeded,
/// <summary> After moving, we've determined that a calibration must happen for proper hand tracking to happen. </summary>
Calibrating,
/// <summary> We've determined that this needs no (more) calibration to function as intended. </summary>
Done,
};
namespace Calibration
{
/// <summary> An algorithm that checks whether or not our current user is running in the same calibration range as last time. </summary>
class SGCORE_API HapticGloveCalibrationCheck;
class SensorRange;
}// namespace Calibration
namespace Kinematics
{
class Vect3D;
}// namespace Kinematics
}// namespace SGCore
/// <summary> An algorithm that checks whether or not our current user is running in the same calibration range as last time. </summary>
class SGCORE_API SGCore::Calibration::HapticGloveCalibrationCheck
{
public:
/// <summary> SenseGlove: How far from the threshold one can be where we would still call it 'the same as before'. </summary>
static float GetSenseGloveThreshold();
/// <summary> Nova: How far from the threshold one can be where we would still call it 'the same as before'. </summary>
static float GetNovaGloveThreshold();
/// <summary> SenseGlove: The minimum amount of sensor flexion movement before we start testing for a smaller hand. </summary>
static float GetSenseGloveMinFlexion();
/// <summary> Nova: The minimum amount of sensor flexion movement before we start testing for a smaller hand. </summary>
static float GetNovaGloveMinFlexion();
/// <summary> SenseGlove: The minimum amount of sensor movement on the thumb abduction before we start testing for a smaller hand. </summary>
static float GetSenseGloveMinAbduction();
/// <summary> Nova: The minimum amount of sensor movement on the thumb abduction before we start testing for a smaller hand. </summary>
static float GetNovaGloveMinAbduction();
public:
//------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Static Checker Functions
/// <summary> Returns true if this DeviceType requires a calibration check. </summary>
/// <param name="deviceType"></param>
/// <returns></returns>
static bool NeedsCheck(SGCore::EDeviceType deviceType);
/// <summary> Checks if current values are operating out of the previous range. Returns -1 if all is fine. 0...4 to indicate which finger is out of bounds. </summary>
/// <param name="previousRange"></param>
/// <param name="currentValues"></param>
/// <param name="type"></param>
/// <returns></returns>
static int32_t OutOfBounds(const SensorRange& previousRange,
const std::vector<Kinematics::Vect3D>& currentValues,
SGCore::EDeviceType deviceType);
/// <summary> Returns true if the user has moved enough in both flexion and thumb abduction movement to be considered 'active'. </summary>
/// <param name="currentRange"></param>
/// <param name="type"></param>
/// <returns></returns>
static bool MovedMinimum(const std::vector<Kinematics::Vect3D>& currentRange, SGCore::EDeviceType deviceType);
/// <summary> Returns true if the current sensor values have moved roughly as much as last time. </summary>
/// <param name="currentRange"></param>
/// <param name="lastRange"></param>
/// <param name="type"></param>
/// <returns></returns>
static bool MatchesLast(const std::vector<Kinematics::Vect3D>& currentRange,
const std::vector<Kinematics::Vect3D>& lastRange,
SGCore::EDeviceType deviceType);
private:
struct Impl;
std::unique_ptr<Impl> Pimpl;
public:
/// <summary> The last calibration range can be null, at which point you definitely need calibration. </summary>
HapticGloveCalibrationCheck();
/// <summary> The last calibration range can be null, at which point you definitely need calibration. </summary>
/// <param name="lastCalibrationRange"></param>
explicit HapticGloveCalibrationCheck(const SGCore::Calibration::SensorRange& lastCalibrationRange);
/**
* The copy constructor.
*/
HapticGloveCalibrationCheck(const HapticGloveCalibrationCheck& rhs);
/**
* The move constructor.
*/
HapticGloveCalibrationCheck(HapticGloveCalibrationCheck&& rhs) noexcept;
virtual ~HapticGloveCalibrationCheck();
public:
/**
* The copy assignment operator.
*/
HapticGloveCalibrationCheck& operator=(const HapticGloveCalibrationCheck& rhs);
/**
* The move assignment operator.
*/
HapticGloveCalibrationCheck& operator=(HapticGloveCalibrationCheck&& rhs) noexcept;
public:
SG_NODISCARD ECalibrationStage GetCalibrationStage() const;
/// <summary> Whether this algorithm has determined if calibration is required, or not. </summary>
SG_NODISCARD bool ReachedConclusion() const;
public:
/// <summary> Reset the calibration check. so it may be used again. This does not reset the last range. </summary>
void Reset();
/// <summary> Using the currently received Sensor Values, check if calibration is required. This function will have to be called until a conclusion can be reached. </summary>
/// <param name="currentValues"></param>
/// <param name="deltaSeconds"></param>
/// <param name="deviceType"></param>
void CheckRange(const std::vector<Kinematics::Vect3D>& currentValues, float deltaSeconds, EDeviceType deviceType);
};