mirror of
https://github.com/EyeTrackVR/EyeTrackVR.git
synced 2025-11-04 14:39:42 +08:00
Rename from SmartInversion to MirrorTrack, and inversion bug fixes!
Renamed all mentions of Smart Inversion to Mirror Track. Also fixed the stare / inversion rapid cycling, yippee!
This commit is contained in:
parent
f7d16212f3
commit
705fe0243c
@ -217,13 +217,15 @@ class EyeTrackSettingsConfig(BaseModel):
|
|||||||
gui_OutputMultiplier: float = 1
|
gui_OutputMultiplier: float = 1
|
||||||
gui_use_module: bool = False
|
gui_use_module: bool = False
|
||||||
|
|
||||||
#SmartInversionTracking
|
#mirrortrackTracking
|
||||||
gui_smartinversion_enabled: bool = False
|
gui_mirrortrack_enabled: bool = False
|
||||||
gui_smartinversion_select_right: bool = True
|
gui_mirrortrack_select_right: bool = True
|
||||||
gui_smartinversion_frame_count: int = 30
|
gui_mirrortrack_cycle_count_inv: int = 20
|
||||||
gui_smartinversion_smoothing_rate: float = 0.025
|
gui_mirrortrack_cycle_count_stare: int = 20
|
||||||
gui_smartinversion_minthresh: float = 0.3
|
#gui_mirrortrack_smoothing_rate: float = 0.025
|
||||||
gui_smartinversion_rotation_clamp: float = 1.0
|
gui_mirrortrack_minthresh: float = 0.3
|
||||||
|
gui_mirrortrack_rotation_clamp: float = 0.5
|
||||||
|
gui_mirrortrack_enable_inv: bool = True
|
||||||
|
|
||||||
class EyeTrackConfig(BaseModel):
|
class EyeTrackConfig(BaseModel):
|
||||||
version: int = 1
|
version: int = 1
|
||||||
|
|||||||
@ -38,7 +38,7 @@ from settings.algo_settings_widget import AlgoSettingsWidget
|
|||||||
from osc.osc import OSCManager
|
from osc.osc import OSCManager
|
||||||
from osc.OSCMessage import OSCMessage
|
from osc.OSCMessage import OSCMessage
|
||||||
from utils.misc_utils import is_nt, resource_path
|
from utils.misc_utils import is_nt, resource_path
|
||||||
from utils.smart_inversion import SmartInversion
|
from utils.mirrortrack import mirrortrack
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import uuid
|
import uuid
|
||||||
@ -284,7 +284,7 @@ def main():
|
|||||||
config.register_listener_callback(osc_manager.update)
|
config.register_listener_callback(osc_manager.update)
|
||||||
config.register_listener_callback(eyes[0].on_config_update)
|
config.register_listener_callback(eyes[0].on_config_update)
|
||||||
config.register_listener_callback(eyes[1].on_config_update)
|
config.register_listener_callback(eyes[1].on_config_update)
|
||||||
config.register_listener_callback(SmartInversion.config_update)
|
config.register_listener_callback(mirrortrack.config_update)
|
||||||
|
|
||||||
osc_manager.register_listeners(
|
osc_manager.register_listeners(
|
||||||
config.settings.gui_osc_recenter_address,
|
config.settings.gui_osc_recenter_address,
|
||||||
@ -302,7 +302,7 @@ def main():
|
|||||||
)
|
)
|
||||||
|
|
||||||
osc_manager.start()
|
osc_manager.start()
|
||||||
SmartInversion.init_config(config)
|
mirrortrack.init_config(config)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
tint = 33
|
tint = 33
|
||||||
|
|||||||
@ -29,7 +29,7 @@ import time
|
|||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC, resource_path
|
from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC, resource_path
|
||||||
from utils.eye_falloff import velocity_falloff
|
from utils.eye_falloff import velocity_falloff
|
||||||
from utils.smart_inversion import SmartInversion
|
from utils.mirrortrack import mirrortrack
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
import threading
|
import threading
|
||||||
@ -337,8 +337,8 @@ class cal:
|
|||||||
var.past_x = out_x_mult
|
var.past_x = out_x_mult
|
||||||
var.past_y = out_y_mult
|
var.past_y = out_y_mult
|
||||||
|
|
||||||
if(self.settings.gui_smartinversion_enabled):
|
if(self.settings.gui_mirrortrack_enabled):
|
||||||
out_x, out_y = SmartInversion.process(self.eye_id, out_x, out_y)
|
out_x, out_y = mirrortrack.process(self.eye_id, out_x, out_y)
|
||||||
else:
|
else:
|
||||||
out_x, out_y = velocity_falloff(self, var, out_x, out_y)
|
out_x, out_y = velocity_falloff(self, var, out_x, out_y)
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ from settings.BaseSettings import BaseSettingsWidget
|
|||||||
from settings.modules.GeneralSettingsModule import GeneralSettingsModule
|
from settings.modules.GeneralSettingsModule import GeneralSettingsModule
|
||||||
from settings.modules.OneEuroSettingsModule import OneEuroSettingsModule
|
from settings.modules.OneEuroSettingsModule import OneEuroSettingsModule
|
||||||
from settings.modules.OSCSettingsModule import OSCSettingsModule
|
from settings.modules.OSCSettingsModule import OSCSettingsModule
|
||||||
from settings.modules.SmartInversionSettingsModule import SmartInversionSettingsModule
|
from settings.modules.MirrorTrackSettingsModule import MirrorTrackSettingsModule
|
||||||
|
|
||||||
|
|
||||||
class SettingsWidget(BaseSettingsWidget):
|
class SettingsWidget(BaseSettingsWidget):
|
||||||
@ -39,7 +39,7 @@ class SettingsWidget(BaseSettingsWidget):
|
|||||||
settings_modules = [
|
settings_modules = [
|
||||||
GeneralSettingsModule,
|
GeneralSettingsModule,
|
||||||
OneEuroSettingsModule,
|
OneEuroSettingsModule,
|
||||||
SmartInversionSettingsModule,
|
MirrorTrackSettingsModule,
|
||||||
OSCSettingsModule,
|
OSCSettingsModule,
|
||||||
]
|
]
|
||||||
super().__init__(widget_id, main_config, settings_modules)
|
super().__init__(widget_id, main_config, settings_modules)
|
||||||
|
|||||||
131
EyeTrackApp/settings/modules/MirrorTrackSettingsModule.py
Normal file
131
EyeTrackApp/settings/modules/MirrorTrackSettingsModule.py
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
from pydantic import AfterValidator
|
||||||
|
from typing_extensions import Annotated
|
||||||
|
|
||||||
|
from settings.modules.BaseModule import BaseSettingsModule, BaseValidationModel
|
||||||
|
from settings.constants import BACKGROUND_COLOR
|
||||||
|
import PySimpleGUI as sg
|
||||||
|
|
||||||
|
from settings.modules.CommonFieldValidators import try_convert_to_float
|
||||||
|
from settings.modules.CommonFieldValidators import try_convert_to_int
|
||||||
|
|
||||||
|
class MirrorTrackValidationModule(BaseValidationModel):
|
||||||
|
gui_mirrortrack_enabled: bool
|
||||||
|
gui_mirrortrack_select_right: bool
|
||||||
|
gui_mirrortrack_cycle_count_inv: Annotated[int, AfterValidator(try_convert_to_int)]
|
||||||
|
gui_mirrortrack_cycle_count_stare: Annotated[int, AfterValidator(try_convert_to_int)]
|
||||||
|
gui_mirrortrack_minthresh: Annotated[float, AfterValidator(try_convert_to_float)]
|
||||||
|
gui_mirrortrack_rotation_clamp: Annotated[float, AfterValidator(try_convert_to_float)]
|
||||||
|
gui_mirrortrack_enable_inv: bool
|
||||||
|
#gui_mirrortrack_smoothing_rate: Annotated[float, AfterValidator(try_convert_to_float)]
|
||||||
|
|
||||||
|
class MirrorTrackSettingsModule(BaseSettingsModule):
|
||||||
|
def __init__(self, config, widget_id, **kwargs):
|
||||||
|
super().__init__(config=config, widget_id=widget_id, **kwargs)
|
||||||
|
self.validation_model = MirrorTrackValidationModule
|
||||||
|
self.gui_mirrortrack_enabled = f"-gui_mirrortrack_enabled{widget_id}-"
|
||||||
|
self.gui_mirrortrack_select_right = f"-gui_mirrortrack_select_right{widget_id}-"
|
||||||
|
self.gui_mirrortrack_cycle_count_inv =f"-gui_mirrortrack_cycle_count_inv{widget_id}-"
|
||||||
|
self.gui_mirrortrack_cycle_count_stare =f"-gui_mirrortrack_cycle_count_stare{widget_id}-"
|
||||||
|
self.gui_mirrortrack_minthresh =f"-gui_mirrortrack_minthresh{widget_id}-"
|
||||||
|
self.gui_mirrortrack_rotation_clamp =f"-gui_mirrortrack_rotation_clamp{widget_id}-"
|
||||||
|
self.gui_mirrortrack_enable_inv =f"-gui_mirrortrack_enable_inv{widget_id}-"
|
||||||
|
#self.gui_mirrortrack_smoothing_rate =f"-gui_mirrortrack_smoothing_rate{widget_id}-"
|
||||||
|
|
||||||
|
def get_layout(self):
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
sg.Text("MirrorTrack System:", background_color='#242224'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
sg.Checkbox(
|
||||||
|
"Enable:",
|
||||||
|
default=self.config.gui_mirrortrack_enabled,
|
||||||
|
key=self.gui_mirrortrack_enabled,
|
||||||
|
background_color="#424042",
|
||||||
|
tooltip="Enables MirrorTrack System",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
sg.Radio(
|
||||||
|
"Use Left Eye",
|
||||||
|
"mirrortrack_selectedeye",
|
||||||
|
background_color="#424042",
|
||||||
|
tooltip="Uses the left eye as the tracked eye.",
|
||||||
|
),
|
||||||
|
|
||||||
|
sg.Radio(
|
||||||
|
"Use Right Eye",
|
||||||
|
"mirrortrack_selectedeye",
|
||||||
|
default=self.config.gui_mirrortrack_select_right,
|
||||||
|
key=self.gui_mirrortrack_select_right,
|
||||||
|
background_color="#424042",
|
||||||
|
tooltip="Uses the right eye as the tracked eye.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
[
|
||||||
|
sg.Text("Inwards Look Threshold", background_color=BACKGROUND_COLOR,tooltip=
|
||||||
|
"Sets the minimum distance of looking in that's required before state can chaned to cross-eyed."
|
||||||
|
"\n Lower value will make cross-eye detection more sensitive."
|
||||||
|
),
|
||||||
|
sg.InputText(
|
||||||
|
self.config.gui_mirrortrack_minthresh,
|
||||||
|
key=self.gui_mirrortrack_minthresh,
|
||||||
|
size=(0, 10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
sg.Text("Transition Cycle Count (Cross Eye)", background_color=BACKGROUND_COLOR,tooltip=
|
||||||
|
"How long it takes to detect you are cross-eyed, or no longer cross-eyed."
|
||||||
|
"\n Higher number means longer duration before changing in or out of being cross-eyed state."
|
||||||
|
),
|
||||||
|
sg.InputText(
|
||||||
|
self.config.gui_mirrortrack_cycle_count_inv,
|
||||||
|
key=self.gui_mirrortrack_cycle_count_inv,
|
||||||
|
size=(0, 10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
sg.Text("Transition Cycle Count (Stare Forward)", background_color=BACKGROUND_COLOR,tooltip=
|
||||||
|
"How long it takes to detect you are staring ahead, or no longer staring ahead."
|
||||||
|
"\n Higher number means longer duration before changing in or out of being in stare ahead state."
|
||||||
|
),
|
||||||
|
sg.InputText(
|
||||||
|
self.config.gui_mirrortrack_cycle_count_stare,
|
||||||
|
key=self.gui_mirrortrack_cycle_count_stare,
|
||||||
|
size=(0, 10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
#[
|
||||||
|
# sg.Text("Smoothing Decay Rate", background_color=BACKGROUND_COLOR,tooltip=
|
||||||
|
# "How quickly eye smoothing decays when you enter or leave a cross-eyed state."
|
||||||
|
# "\nHigher number = shorter smoothing duration."
|
||||||
|
# ),
|
||||||
|
# sg.InputText(
|
||||||
|
# self.config.gui_mirrortrack_smoothing_rate,
|
||||||
|
# key=self.gui_mirrortrack_smoothing_rate,
|
||||||
|
# size=(0, 10),
|
||||||
|
# ),
|
||||||
|
#],
|
||||||
|
|
||||||
|
[
|
||||||
|
sg.Checkbox(
|
||||||
|
"Allow cross-eye:",
|
||||||
|
default=self.config.gui_mirrortrack_enable_inv,
|
||||||
|
key=self.gui_mirrortrack_enable_inv,
|
||||||
|
background_color="#424042",
|
||||||
|
tooltip="Enables cross-eye functionality",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
sg.Text("Maximum allowed cross-eye", background_color=BACKGROUND_COLOR,tooltip=
|
||||||
|
"Defines the maximum inwards rotation that is output when cross-eyed."
|
||||||
|
"\n0 = will only look straight ahead \n0.5 = will go a little bit cross-eyed \n1 = maximum hurr durr "
|
||||||
|
),
|
||||||
|
sg.InputText(
|
||||||
|
self.config.gui_mirrortrack_rotation_clamp,
|
||||||
|
key=self.gui_mirrortrack_rotation_clamp,
|
||||||
|
size=(0, 10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
]
|
||||||
@ -1,106 +0,0 @@
|
|||||||
from pydantic import AfterValidator
|
|
||||||
from typing_extensions import Annotated
|
|
||||||
|
|
||||||
from settings.modules.BaseModule import BaseSettingsModule, BaseValidationModel
|
|
||||||
from settings.constants import BACKGROUND_COLOR
|
|
||||||
import PySimpleGUI as sg
|
|
||||||
|
|
||||||
from settings.modules.CommonFieldValidators import try_convert_to_float
|
|
||||||
from settings.modules.CommonFieldValidators import try_convert_to_int
|
|
||||||
|
|
||||||
class SmartInversionValidationModule(BaseValidationModel):
|
|
||||||
gui_smartinversion_enabled: bool
|
|
||||||
gui_smartinversion_select_right: bool
|
|
||||||
gui_smartinversion_frame_count: Annotated[int, AfterValidator(try_convert_to_int)]
|
|
||||||
gui_smartinversion_smoothing_rate: Annotated[float, AfterValidator(try_convert_to_float)]
|
|
||||||
gui_smartinversion_minthresh: Annotated[float, AfterValidator(try_convert_to_float)]
|
|
||||||
gui_smartinversion_rotation_clamp: Annotated[float, AfterValidator(try_convert_to_float)]
|
|
||||||
|
|
||||||
class SmartInversionSettingsModule(BaseSettingsModule):
|
|
||||||
def __init__(self, config, widget_id, **kwargs):
|
|
||||||
super().__init__(config=config, widget_id=widget_id, **kwargs)
|
|
||||||
self.validation_model = SmartInversionValidationModule
|
|
||||||
self.gui_smartinversion_enabled = f"-gui_smartinversion_enabled{widget_id}-"
|
|
||||||
self.gui_smartinversion_select_right = f"-gui_smartinversion_select_right{widget_id}-"
|
|
||||||
self.gui_smartinversion_frame_count =f"-gui_smartinversion_frame_count{widget_id}-"
|
|
||||||
self.gui_smartinversion_smoothing_rate =f"-gui_smartinversion_smoothing_rate{widget_id}-"
|
|
||||||
self.gui_smartinversion_minthresh =f"-gui_smartinversion_minthresh{widget_id}-"
|
|
||||||
self.gui_smartinversion_rotation_clamp =f"-gui_smartinversion_rotation_clamp{widget_id}-"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_layout(self):
|
|
||||||
return [
|
|
||||||
[
|
|
||||||
sg.Text("Smart Inversion Tracking System:", background_color='#242224'),
|
|
||||||
],
|
|
||||||
[
|
|
||||||
sg.Checkbox(
|
|
||||||
"Enable:",
|
|
||||||
default=self.config.gui_smartinversion_enabled,
|
|
||||||
key=self.gui_smartinversion_enabled,
|
|
||||||
background_color="#424042",
|
|
||||||
tooltip="Enables Smart Inversion Tracking System",
|
|
||||||
),
|
|
||||||
|
|
||||||
sg.Radio(
|
|
||||||
"Use Left Eye",
|
|
||||||
"smartinversion_selectedeye",
|
|
||||||
background_color="#424042",
|
|
||||||
tooltip="Uses the left eye as the tracked eye.",
|
|
||||||
),
|
|
||||||
|
|
||||||
sg.Radio(
|
|
||||||
"Use Right Eye",
|
|
||||||
"smartinversion_selectedeye",
|
|
||||||
default=self.config.gui_smartinversion_select_right,
|
|
||||||
key=self.gui_smartinversion_select_right,
|
|
||||||
background_color="#424042",
|
|
||||||
tooltip="Uses the right eye as the tracked eye.",
|
|
||||||
)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
sg.Text("Inwards Look Threshold", background_color=BACKGROUND_COLOR,tooltip=
|
|
||||||
"Sets the minimum distance of looking in that's required before state can chaned to cross-eyed."
|
|
||||||
"\n Lower value will make cross-eye detection more sensitive."
|
|
||||||
),
|
|
||||||
sg.InputText(
|
|
||||||
self.config.gui_smartinversion_minthresh,
|
|
||||||
key=self.gui_smartinversion_minthresh,
|
|
||||||
size=(0, 10),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
[
|
|
||||||
sg.Text("Inversion Trigger Frame Count", background_color=BACKGROUND_COLOR,tooltip=
|
|
||||||
"How long it takes to detect you are cross-eyed, or no longer cross-eyed."
|
|
||||||
"\n Higher number means longer duration before changing in or out of being cross-eyed state."
|
|
||||||
),
|
|
||||||
sg.InputText(
|
|
||||||
self.config.gui_smartinversion_frame_count,
|
|
||||||
key=self.gui_smartinversion_frame_count,
|
|
||||||
size=(0, 10),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
[
|
|
||||||
sg.Text("Smoothing Decay Rate", background_color=BACKGROUND_COLOR,tooltip=
|
|
||||||
"How quickly eye smoothing decays when you enter or leave a cross-eyed state."
|
|
||||||
"\nHigher number = shorter smoothing duration."
|
|
||||||
),
|
|
||||||
sg.InputText(
|
|
||||||
self.config.gui_smartinversion_smoothing_rate,
|
|
||||||
key=self.gui_smartinversion_smoothing_rate,
|
|
||||||
size=(0, 10),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
[
|
|
||||||
sg.Text("Maximum allowed cross-eye", background_color=BACKGROUND_COLOR,tooltip=
|
|
||||||
"Defines the maximum inwards rotation that is output when cross-eyed."
|
|
||||||
"\n0 = will only look straight ahead \n0.5 = will go a little bit cross-eyed \n1 = maximum hurr durr "
|
|
||||||
),
|
|
||||||
sg.InputText(
|
|
||||||
self.config.gui_smartinversion_rotation_clamp,
|
|
||||||
key=self.gui_smartinversion_rotation_clamp,
|
|
||||||
size=(0, 10),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
]
|
|
||||||
@ -15,7 +15,7 @@ class CycleCounter:
|
|||||||
def reset(self):
|
def reset(self):
|
||||||
self.count = 0
|
self.count = 0
|
||||||
|
|
||||||
def complete(self):
|
def is_complete(self):
|
||||||
if self.count >= self.max_count:
|
if self.count >= self.max_count:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -28,3 +28,9 @@ class CycleCounter:
|
|||||||
|
|
||||||
def get_count(self):
|
def get_count(self):
|
||||||
return self.count
|
return self.count
|
||||||
|
|
||||||
|
def update(self,max_count):
|
||||||
|
self.max_count = max_count
|
||||||
|
|
||||||
|
def force_complete(self):
|
||||||
|
self.count = self.max_count
|
||||||
@ -4,7 +4,7 @@ from config import EyeTrackConfig
|
|||||||
from utils.CycleCounter import *
|
from utils.CycleCounter import *
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
class SmartInversion:
|
class mirrortrack:
|
||||||
|
|
||||||
#Defines our possible tracking states
|
#Defines our possible tracking states
|
||||||
class States(Enum):
|
class States(Enum):
|
||||||
@ -15,7 +15,6 @@ class SmartInversion:
|
|||||||
state = States.TRACKING
|
state = States.TRACKING
|
||||||
|
|
||||||
#Defines our tracked positions
|
#Defines our tracked positions
|
||||||
thread_lock = threading.Lock()
|
|
||||||
rx_left_x = 0.0
|
rx_left_x = 0.0
|
||||||
rx_left_y = 0.0
|
rx_left_y = 0.0
|
||||||
rx_right_x = 0.0
|
rx_right_x = 0.0
|
||||||
@ -39,7 +38,7 @@ class SmartInversion:
|
|||||||
#Defines variables that require settings
|
#Defines variables that require settings
|
||||||
@classmethod
|
@classmethod
|
||||||
def init_config(cls,config: EyeTrackConfig):
|
def init_config(cls,config: EyeTrackConfig):
|
||||||
if config.settings.gui_smartinversion_select_right:
|
if config.settings.gui_mirrortrack_select_right:
|
||||||
cls.dom_eye = EyeId.RIGHT
|
cls.dom_eye = EyeId.RIGHT
|
||||||
cls.rec_eye = EyeId.LEFT
|
cls.rec_eye = EyeId.LEFT
|
||||||
cls.is_r_dom = True
|
cls.is_r_dom = True
|
||||||
@ -48,35 +47,50 @@ class SmartInversion:
|
|||||||
cls.rec_eye = EyeId.RIGHT
|
cls.rec_eye = EyeId.RIGHT
|
||||||
cls.is_r_dom = False
|
cls.is_r_dom = False
|
||||||
|
|
||||||
cls.inv_x_thresh = config.settings.gui_smartinversion_minthresh
|
#Inversion related
|
||||||
cls.cycle_counts = config.settings.gui_smartinversion_frame_count
|
cls.inv_is_enabled = config.settings.gui_mirrortrack_enable_inv
|
||||||
cls.inv_clamp = config.settings.gui_smartinversion_rotation_clamp
|
cls.inv_x_thresh = config.settings.gui_mirrortrack_minthresh
|
||||||
|
cls.inv_clamp = config.settings.gui_mirrortrack_rotation_clamp
|
||||||
|
|
||||||
cls.inv_counter = CycleCounter(cls.cycle_counts*1.25)
|
cls.cyc_counts_inv = config.settings.gui_mirrortrack_cycle_count_inv
|
||||||
cls.stare_counter = CycleCounter(cls.cycle_counts)
|
cls.cyc_counts_stare = config.settings.gui_mirrortrack_cycle_count_stare
|
||||||
|
|
||||||
|
cls.cyc_counter_inv = CycleCounter(cls.cyc_counts_inv)
|
||||||
|
cls.cyc_counter_stare = CycleCounter(cls.cyc_counts_stare)
|
||||||
|
|
||||||
|
cls.thread_lock = threading.Lock()
|
||||||
|
|
||||||
#Receives changes in configuration and applies them accordingly
|
#Receives changes in configuration and applies them accordingly
|
||||||
@classmethod
|
@classmethod
|
||||||
def config_update(cls,data):
|
def config_update(cls,data):
|
||||||
print(f"Smart inversion heard that some settings were changed!")
|
|
||||||
|
|
||||||
if "gui_smartinversion_select_right" in data:
|
if "gui_mirrortrack_select_right" in data:
|
||||||
cls.dom_eye = EyeId.RIGHT if data["gui_smartinversion_select_right"] else EyeId.LEFT
|
cls.dom_eye = EyeId.RIGHT if data["gui_mirrortrack_select_right"] else EyeId.LEFT
|
||||||
cls.rec_eye = EyeId.LEFT if data["gui_smartinversion_select_right"] else EyeId.RIGHT
|
cls.rec_eye = EyeId.LEFT if data["gui_mirrortrack_select_right"] else EyeId.RIGHT
|
||||||
cls.is_r_dom = True if data["gui_smartinversion_select_right"] else False
|
cls.is_r_dom = True if data["gui_mirrortrack_select_right"] else False
|
||||||
print(f"Dominant eye changed to {cls.dom_eye.name}")
|
print(f"Dominant eye changed to {cls.dom_eye.name}")
|
||||||
|
|
||||||
if "gui_smartinversion_minthresh" in data:
|
if "gui_mirrortrack_minthresh" in data:
|
||||||
cls.inv_x_thresh = data["gui_smartinversion_minthresh"]
|
cls.inv_x_thresh = data["gui_mirrortrack_minthresh"]
|
||||||
print(f"Smart inversion transition threshold changed to {cls.inv_x_thresh}")
|
print(f"MirrorTrack transition threshold changed to {cls.inv_x_thresh}")
|
||||||
|
|
||||||
if "gui_smartinversion_frame_count" in data:
|
if "gui_mirrortrack_cycle_count_inv" in data:
|
||||||
cls.cycle_counts = data["gui_smartinversion_frame_count"]
|
cls.cyc_counts_stare = data["gui_mirrortrack_cycle_count_inv"]
|
||||||
print(f"Smart inversion transition condition required cycle count changed to {cls.cycle_counts}")
|
cls.cyc_counter_stare.update(cls.cyc_counts_stare)
|
||||||
|
print(f"MirrorTrack inversion transition condition required cycle count changed to {cls.cyc_counts_inv}")
|
||||||
|
|
||||||
if "gui_smartinversion_rotation_clamp" in data:
|
if "gui_mirrortrack_cycle_count_stare" in data:
|
||||||
cls.inv_clamp = data["gui_smartinversion_rotation_clamp"]
|
cls.cyc_counts_inv = data["gui_mirrortrack_cycle_count_stare"]
|
||||||
print(f"Smart inversion maximum allowed cross-eye changed to {cls.cycle_counts}")
|
cls.cyc_counter_stare.update(cls.cyc_counts_inv)
|
||||||
|
print(f"MirrorTrack stare transition condition required cycle count changed to {cls.cyc_counts_stare}")
|
||||||
|
|
||||||
|
if "gui_mirrortrack_rotation_clamp" in data:
|
||||||
|
cls.inv_clamp = data["gui_mirrortrack_rotation_clamp"]
|
||||||
|
print(f"MirrorTrack maximum allowed cross-eye changed to {cls.inv_clamp}")
|
||||||
|
|
||||||
|
if "gui_mirrortrack_enable_inv" in data:
|
||||||
|
cls.inv_is_enabled = data["gui_mirrortrack_enable_inv"]
|
||||||
|
print(f"MirrorTrack allow cross-eye is set to {cls.inv_is_enabled}")
|
||||||
|
|
||||||
#Main processing function
|
#Main processing function
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -84,7 +98,10 @@ class SmartInversion:
|
|||||||
with cls.thread_lock:
|
with cls.thread_lock:
|
||||||
cls.store_tracked_positions(eye_id,out_x,out_y)
|
cls.store_tracked_positions(eye_id,out_x,out_y)
|
||||||
cls.check_for_stare()
|
cls.check_for_stare()
|
||||||
cls.check_for_inversion()
|
|
||||||
|
if cls.inv_is_enabled:
|
||||||
|
cls.check_for_inversion()
|
||||||
|
|
||||||
out_x, out_y = cls.update_new_position(eye_id,out_x,out_y)
|
out_x, out_y = cls.update_new_position(eye_id,out_x,out_y)
|
||||||
cls.store_processed_positions(eye_id,out_x,out_y)
|
cls.store_processed_positions(eye_id,out_x,out_y)
|
||||||
return out_x, out_y
|
return out_x, out_y
|
||||||
@ -125,54 +142,45 @@ class SmartInversion:
|
|||||||
if cls.dom_is_inward() and cls.rec_is_inward():
|
if cls.dom_is_inward() and cls.rec_is_inward():
|
||||||
|
|
||||||
#Updates the counter for stare activation
|
#Updates the counter for stare activation
|
||||||
if not cls.is_stare_mode() and not cls.stare_counter.complete():
|
if not cls.is_stare_mode() and not cls.cyc_counter_stare.is_complete():
|
||||||
cls.stare_counter.increase()
|
cls.cyc_counter_stare.increase()
|
||||||
|
|
||||||
#Sets the state to stare if count completes
|
#Sets the state to stare if count is_completes
|
||||||
elif not cls.is_stare_mode() and cls.stare_counter.complete() and not cls.bypass_stare:
|
elif not cls.is_stare_mode() and cls.cyc_counter_stare.is_complete() and not cls.bypass_stare:
|
||||||
cls.set_state("STARE")
|
cls.set_state("STARE")
|
||||||
print(f"State is {cls.state.name}")
|
|
||||||
|
|
||||||
elif cls.is_stare_mode():
|
elif cls.cyc_counter_stare.active():
|
||||||
if cls.stare_counter.active():
|
cls.cyc_counter_stare.decrease()
|
||||||
cls.stare_counter.decrease()
|
|
||||||
if not cls.stare_counter.active():
|
|
||||||
if cls.bypass_stare:
|
|
||||||
cls.bypass_stare = False
|
|
||||||
print(f"bypass_stare disabled by check_for_stare")
|
|
||||||
cls.set_state("TRACKING")
|
|
||||||
print(f"State set to {cls.state.name}")
|
|
||||||
|
|
||||||
elif not cls.stare_counter.active():
|
if not cls.cyc_counter_stare.active():
|
||||||
cls.stare_counter.decrease()
|
if cls.bypass_stare:
|
||||||
|
cls.bypass_stare = False
|
||||||
|
if not cls.is_tracking_mode():
|
||||||
|
cls.set_state("TRACKING")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def check_for_inversion(cls):
|
def check_for_inversion(cls):
|
||||||
if cls.dom_is_inward() and cls.rec_meets_thresh() and cls.is_stare_mode():
|
if cls.dom_is_inward() and cls.rec_meets_thresh() and (cls.is_stare_mode() or cls.bypass_stare):
|
||||||
|
|
||||||
#Updates the counter for activation
|
#Updates the counter for activation
|
||||||
if not cls.is_inverted_mode() and not cls.inv_counter.complete():
|
if not cls.is_inverted_mode() and not cls.cyc_counter_inv.is_complete():
|
||||||
cls.inv_counter.increase()
|
cls.cyc_counter_inv.increase()
|
||||||
#print(f"Inversion activation counter is increasing: {cls.inv_counter.get_count()}")
|
#print(f"Inversion activation counter is increasing: {cls.cyc_counter_inv.get_count()}")
|
||||||
|
|
||||||
#Sets the state to inverted if enough cycles have completed
|
#Sets the state to inverted if enough cycles have is_completed
|
||||||
elif not cls.is_inverted_mode() and cls.inv_counter.complete():
|
elif not cls.is_inverted_mode() and cls.cyc_counter_inv.is_complete():
|
||||||
cls.set_state("INVERTED")
|
cls.set_state("INVERTED")
|
||||||
print(f"State set to {cls.state.name}")
|
|
||||||
cls.bypass_stare = True
|
cls.bypass_stare = True
|
||||||
|
|
||||||
#Begins the counter for deactivation if conditions are not met
|
#Begins the counter for deactivation if conditions are not met
|
||||||
elif cls.is_inverted_mode():
|
elif cls.cyc_counter_inv.active():
|
||||||
if cls.inv_counter.active():
|
cls.cyc_counter_inv.decrease()
|
||||||
cls.inv_counter.decrease()
|
|
||||||
if not cls.inv_counter.active():
|
|
||||||
if cls.bypass_stare:
|
|
||||||
cls.bypass_stare = False
|
|
||||||
print(f"bypass_stare disabled by check_for_inv")
|
|
||||||
|
|
||||||
#Decreases the counter if conditions are not met, and inversion isn't active.
|
if not cls.cyc_counter_inv.active():
|
||||||
elif cls.inv_counter.active():
|
if cls.bypass_stare:
|
||||||
cls.inv_counter.decrease()
|
cls.bypass_stare = False
|
||||||
|
cls.cyc_counter_stare.force_complete()
|
||||||
|
cls.check_for_stare()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_new_position(cls,eye_id,out_x,out_y):
|
def update_new_position(cls,eye_id,out_x,out_y):
|
||||||
@ -206,6 +214,7 @@ class SmartInversion:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def set_state(cls,new_state: str):
|
def set_state(cls,new_state: str):
|
||||||
cls.state = cls.States[new_state]
|
cls.state = cls.States[new_state]
|
||||||
|
print(f"State set to {cls.state.name}")
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_dominant_eye(cls,eye_id):
|
def is_dominant_eye(cls,eye_id):
|
||||||
return eye_id == cls.dom_eye
|
return eye_id == cls.dom_eye
|
||||||
16
conftest.py
16
conftest.py
@ -75,13 +75,15 @@ def eyetrack_settings_config():
|
|||||||
gui_vrc_native=False,
|
gui_vrc_native=False,
|
||||||
gui_pupil_dilation=True,
|
gui_pupil_dilation=True,
|
||||||
|
|
||||||
#Smart Inversion Tracking
|
#MirrorTrack
|
||||||
gui_smartinversion_enabled=False,
|
gui_mirrortrack_enabled=False,
|
||||||
gui_smartinversion_select_right=True,
|
gui_mirrortrack_select_right=True,
|
||||||
gui_smartinversion_frame_count=10,
|
gui_mirrortrack_cycle_count_inv=20,
|
||||||
gui_smartinversion_smoothing_rate=0.025,
|
gui_mirrortrack_cycle_count_stare=20,
|
||||||
gui_smartinversion_minthresh=0.3,
|
#gui_mirrortrack_smoothing_rate=0.025,
|
||||||
gui_smartinversion_rotation_clamp=1.0,
|
gui_mirrortrack_minthresh=0.3,
|
||||||
|
gui_mirrortrack_rotation_clamp=0.3,
|
||||||
|
gui_mirrortrack_enable_inv=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user