From 1e0845a308eb6641ba88538263c7c0291c0ade88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20K=C3=B6gel?= <koegel@vr.rwth-aachen.de> Date: Wed, 17 Aug 2022 12:26:38 +0200 Subject: [PATCH 1/9] Added GazeTrackingLog logstream and fixed duplicate debugLog --- .../StudyFrameworkPlugin/Private/Logging/SFLoggingUtils.cpp | 4 ++-- Source/StudyFrameworkPlugin/Private/SFParticipant.cpp | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Source/StudyFrameworkPlugin/Private/Logging/SFLoggingUtils.cpp b/Source/StudyFrameworkPlugin/Private/Logging/SFLoggingUtils.cpp index ead0f32..4b34f31 100644 --- a/Source/StudyFrameworkPlugin/Private/Logging/SFLoggingUtils.cpp +++ b/Source/StudyFrameworkPlugin/Private/Logging/SFLoggingUtils.cpp @@ -34,9 +34,9 @@ void FSFLoggingUtils::SetupLoggingStreams() ILogStream* SFLog = UniLog.NewLogStream("SFLog", "StudyFramework/DebuggingLogs", "SFLog.txt", false); SFLog->SetLogToDefaultLog(true); - //ParticipantLog, PositionLog are set up in Participant init function + //ParticipantLog, PositionLog, GazeTrackingLog are set up in Participant init function - ILogStream* SFErrorLog = UniLog.NewLogStream("SFErrorLog", "StudyFramework/Logs", "SFLog.txt", false); + ILogStream* SFErrorLog = UniLog.NewLogStream("SFErrorLog", "StudyFramework/DebuggingLogs", "SFLog.txt", false); SFErrorLog->SetLogToDefaultLog(true); SFErrorLog->SetPrefix(TEXT("Error: ")); SFErrorLog->SetLogOnScreenOnMaster(true); diff --git a/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp b/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp index 0556e77..4ffefa4 100644 --- a/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp +++ b/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp @@ -29,6 +29,11 @@ bool USFParticipant::Initialize(int Participant) Filename, false); ILogStream* PositionLog = UniLog.NewLogStream("PositionLog", "StudyFramework/StudyLogs/PositionLogs", "Position"+Filename, false); + if(USFGameInstance::Get()->GetStudySetup()->UseGazeTracker != EGazeTrackerMode::NotTracking) + { + ILogStream* GazeTrackingLog = UniLog.NewLogStream("GazeTrackingLog", "StudyFramework/StudyLogs/GazeTrackingLogs", + "GazeTracking" + Filename, false); + } StartTime = FPlatformTime::Seconds(); USFGameInstance::Get()->GetLogObject()->LogHeaderRows(); return true; -- GitLab From 3ddfe26f956d877eba0b778327c7f7027ca0c79a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20K=C3=B6gel?= <koegel@vr.rwth-aachen.de> Date: Wed, 17 Aug 2022 12:40:18 +0200 Subject: [PATCH 2/9] Changed names of position log functions in preparation for new gazelogging functions --- Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp | 4 ++-- Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp | 2 +- Source/StudyFrameworkPlugin/Private/SFParticipant.cpp | 2 +- Source/StudyFrameworkPlugin/Public/Logging/SFLogObject.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp index 46489c2..e632f00 100644 --- a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp +++ b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp @@ -50,7 +50,7 @@ void USFLogObject::Initialize() { } // NOTE: When changing header row, update output (see below) -void USFLogObject::LogHeaderRows() { +void USFLogObject::WritePositionLogHeaderRows() { FString PositionLogHeader = FString("ElapsedTime") + "\t" + FString("LogName") + "\t" + FString("Condition") + @@ -63,7 +63,7 @@ void USFLogObject::LogHeaderRows() { UniLog.Log(PositionLogHeader, "PositionLog"); } -void USFLogObject::LoggingLoopsLogToFile() { +void USFLogObject::WritePositionLogToFile() { if (!USFGameInstance::Get() || !USFGameInstance::Get()->GetLogObject()) { return; diff --git a/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp b/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp index 9d36463..9f5dcc2 100644 --- a/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp +++ b/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp @@ -524,7 +524,7 @@ USFParticipant* USFGameInstance::GetParticipant() const bool USFGameInstance::LogTick(float DeltaSeconds) { if (LogObject->bLoggingLoopsActive){ - LogObject->LoggingLoopsLogToFile(); + LogObject->WritePositionLogToFile(); } return true; } diff --git a/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp b/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp index 4ffefa4..52277de 100644 --- a/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp +++ b/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp @@ -35,7 +35,7 @@ bool USFParticipant::Initialize(int Participant) "GazeTracking" + Filename, false); } StartTime = FPlatformTime::Seconds(); - USFGameInstance::Get()->GetLogObject()->LogHeaderRows(); + USFGameInstance::Get()->GetLogObject()->WritePositionLogHeaderRows(); return true; } diff --git a/Source/StudyFrameworkPlugin/Public/Logging/SFLogObject.h b/Source/StudyFrameworkPlugin/Public/Logging/SFLogObject.h index d96088d..011febe 100644 --- a/Source/StudyFrameworkPlugin/Public/Logging/SFLogObject.h +++ b/Source/StudyFrameworkPlugin/Public/Logging/SFLogObject.h @@ -65,7 +65,7 @@ public: UFUNCTION() bool GetLoggingLoopsActive(); UFUNCTION() - static void LogHeaderRows(); + static void WritePositionLogHeaderRows(); UFUNCTION() - static void LoggingLoopsLogToFile(); + static void WritePositionLogToFile(); }; -- GitLab From 55bca58a9ed21376c39fc889f6d57263fa283ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20K=C3=B6gel?= <koegel@vr.rwth-aachen.de> Date: Wed, 17 Aug 2022 13:15:50 +0200 Subject: [PATCH 3/9] Switched to new Logcomment function --- .../Private/GazeTracking/SFGazeTracker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp b/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp index 615f974..a22bf73 100644 --- a/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp +++ b/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp @@ -1,5 +1,5 @@ #include "GazeTracking/SFGazeTracker.h" - +#include "Logging/SFLoggingBPLibrary.h" #include "SFGameInstance.h" #include "GazeTracking/SFGazeTarget.h" #include "GazeTracking/SFGazeTargetActor.h" @@ -26,7 +26,7 @@ void USFGazeTracker::Init(EGazeTrackerMode Mode) } else { - USFGameInstance::Get()->LogComment("No Vive Pro Eye present, use head rotation only for gaze tracking."); + USFLoggingBPLibrary::LogComment("No Vive Pro Eye present, use head rotation only for gaze tracking.", true); } #else FSFUtils::OpenMessageBox("SRanipal Plugin is not present, cannot use eye tracking! Check out, e.g., StudyFramework Wiki where to get it", true); -- GitLab From eafe628cc90b61ff6da79e92ff54c3595a1760d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20K=C3=B6gel?= <koegel@vr.rwth-aachen.de> Date: Wed, 17 Aug 2022 13:17:09 +0200 Subject: [PATCH 4/9] Implemented GazeTrackingLogging, further testing still to be done --- .../Private/Logging/SFLogObject.cpp | 38 +++++++++++++++++-- .../Private/SFGameInstance.cpp | 1 + .../Private/SFParticipant.cpp | 3 +- .../Public/Logging/SFLogObject.h | 9 ++++- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp index e632f00..87326b3 100644 --- a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp +++ b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp @@ -50,7 +50,7 @@ void USFLogObject::Initialize() { } // NOTE: When changing header row, update output (see below) -void USFLogObject::WritePositionLogHeaderRows() { +void USFLogObject::WritePositionLogHeaderRow() { FString PositionLogHeader = FString("ElapsedTime") + "\t" + FString("LogName") + "\t" + FString("Condition") + @@ -73,14 +73,14 @@ void USFLogObject::WritePositionLogToFile() { if (ComponentLoggingInfo.LogNextTick == true) { ComponentLoggingInfo.LogNextTick = false; //When starting in Debug-Mode (i.e. not through the HUD) no condition is defined. - FString currentCondition = USFGameInstance::Get()->GetParticipant()->GetCurrentCondition() ? + FString CurrentCondition = USFGameInstance::Get()->GetParticipant()->GetCurrentCondition() ? USFGameInstance::Get()->GetParticipant()->GetCurrentCondition()->UniqueName : FString("Debug"); // NOTE: When changing output, update header row (see above) FString out = USFGameInstance::Get()->GetParticipant()->GetCurrentTime() + "\t" + ComponentLoggingInfo.LogName + - "\t" + currentCondition + + "\t" + CurrentCondition + "\t" + FString::Printf(TEXT("%.3f"), ComponentLoggingInfo.ComponentToLog->GetComponentLocation().X) + "\t" + FString::Printf(TEXT("%.3f"), ComponentLoggingInfo.ComponentToLog->GetComponentLocation().Y) + "\t" + FString::Printf(TEXT("%.3f"), ComponentLoggingInfo.ComponentToLog->GetComponentLocation().Z) + @@ -99,6 +99,38 @@ void USFLogObject::WritePositionLogToFile() { } } +// NOTE: When changing header row, update output (see below) +void USFLogObject::WriteGazeTrackingLogHeaderRow() { + FString GazeTrackingLogHeader = FString("ElapsedTime") + + "\t" + FString("Condition") + + "\t" + FString("GazeTarget") + + "\t" + FString("HeadRotation-Origin") + + "\t" + FString("HeadRotation-Direction"); + UniLog.Log(GazeTrackingLogHeader, "GazeTrackingLog"); +} + +void USFLogObject::WriteGazeTrackingLogToFile() { + if (!USFGameInstance::Get() || !USFGameInstance::Get()->GetGazeTracker()) + { + return; + } + USFGazeTracker* GazeTracker = USFGameInstance::Get()->GetGazeTracker(); + FString GazeTarget = GazeTracker->GetCurrentGazeTarget() == "" ? "-" : GazeTracker->GetCurrentGazeTarget(); + //When starting in Debug-Mode (i.e. not through the HUD) no condition is defined. + FString CurrentCondition = USFGameInstance::Get()->GetParticipant()->GetCurrentCondition() ? + USFGameInstance::Get()->GetParticipant()->GetCurrentCondition()->UniqueName : + FString("Debug"); + // NOTE: When changing output, update header row (see above) + FString out = USFGameInstance::Get()->GetParticipant()->GetCurrentTime() + + "\t" + CurrentCondition + + "\t" + GazeTarget + + "\t" + GazeTracker->GetGazeDirection().Origin.ToCompactString() + + "\t" + GazeTracker->GetGazeDirection().Direction.ToCompactString(); + if (UniLog.GetLogStream("GazeTrackingLog")) + { + UniLog.Log(out, "GazeTrackingLog"); + } +} void USFLogObject::SetLoggingLoopsActive(bool LoggingLoopsActive) { bLoggingLoopsActive = LoggingLoopsActive; diff --git a/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp b/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp index 9f5dcc2..2487d90 100644 --- a/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp +++ b/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp @@ -525,6 +525,7 @@ bool USFGameInstance::LogTick(float DeltaSeconds) { if (LogObject->bLoggingLoopsActive){ LogObject->WritePositionLogToFile(); + LogObject->WriteGazeTrackingLogToFile(); } return true; } diff --git a/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp b/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp index 52277de..d77a15e 100644 --- a/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp +++ b/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp @@ -35,7 +35,8 @@ bool USFParticipant::Initialize(int Participant) "GazeTracking" + Filename, false); } StartTime = FPlatformTime::Seconds(); - USFGameInstance::Get()->GetLogObject()->WritePositionLogHeaderRows(); + USFGameInstance::Get()->GetLogObject()->WritePositionLogHeaderRow(); + USFGameInstance::Get()->GetLogObject()->WriteGazeTrackingLogHeaderRow(); return true; } diff --git a/Source/StudyFrameworkPlugin/Public/Logging/SFLogObject.h b/Source/StudyFrameworkPlugin/Public/Logging/SFLogObject.h index 011febe..b44a2bb 100644 --- a/Source/StudyFrameworkPlugin/Public/Logging/SFLogObject.h +++ b/Source/StudyFrameworkPlugin/Public/Logging/SFLogObject.h @@ -65,7 +65,14 @@ public: UFUNCTION() bool GetLoggingLoopsActive(); UFUNCTION() - static void WritePositionLogHeaderRows(); + static void WritePositionLogHeaderRow(); UFUNCTION() static void WritePositionLogToFile(); + + UFUNCTION() + static void WriteGazeTrackingLogHeaderRow(); + + UFUNCTION() + static void WriteGazeTrackingLogToFile(); + }; -- GitLab From 1be79781fdd2866738fb638411da1c41f289a7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20K=C3=B6gel?= <koegel@vr.rwth-aachen.de> Date: Fri, 19 Aug 2022 17:09:48 +0200 Subject: [PATCH 5/9] Added an entry into eyetracking logs specifying whether eyetracking is used. (Maybe not necessary, as it very unlikely to log data of a person looking straight ahead all the time, but can't hurt) --- Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp index 87326b3..144257c 100644 --- a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp +++ b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp @@ -103,6 +103,7 @@ void USFLogObject::WritePositionLogToFile() { void USFLogObject::WriteGazeTrackingLogHeaderRow() { FString GazeTrackingLogHeader = FString("ElapsedTime") + "\t" + FString("Condition") + + "\t" + FString("UsingEyetracking") + "\t" + FString("GazeTarget") + "\t" + FString("HeadRotation-Origin") + "\t" + FString("HeadRotation-Direction"); @@ -120,9 +121,11 @@ void USFLogObject::WriteGazeTrackingLogToFile() { FString CurrentCondition = USFGameInstance::Get()->GetParticipant()->GetCurrentCondition() ? USFGameInstance::Get()->GetParticipant()->GetCurrentCondition()->UniqueName : FString("Debug"); + FString isTrackingEyes = USFGameInstance::Get()->GetGazeTracker()->IsTrackingEyes() ? "1" : "0"; // NOTE: When changing output, update header row (see above) FString out = USFGameInstance::Get()->GetParticipant()->GetCurrentTime() + "\t" + CurrentCondition + + "\t" + isTrackingEyes + "\t" + GazeTarget + "\t" + GazeTracker->GetGazeDirection().Origin.ToCompactString() + "\t" + GazeTracker->GetGazeDirection().Direction.ToCompactString(); -- GitLab From f992c2ca74d880932665a021e01e05d17d5e399e Mon Sep 17 00:00:00 2001 From: "RZ-WIN\\vr-admin" <account@vr.rwth-aachen.de> Date: Thu, 24 Nov 2022 13:21:56 +0100 Subject: [PATCH 6/9] avoid crash if starting on study map for debugging (in which case a setup does not really exist...) --- .../Private/Logging/SFLoggingUtils.cpp | 2 +- .../Private/SFGameInstance.cpp | 7 ++++++- .../StudyFrameworkPlugin/Private/SFParticipant.cpp | 14 +++++++++----- Source/StudyFrameworkPlugin/Public/SFParticipant.h | 1 + 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Source/StudyFrameworkPlugin/Private/Logging/SFLoggingUtils.cpp b/Source/StudyFrameworkPlugin/Private/Logging/SFLoggingUtils.cpp index 4b34f31..0968565 100644 --- a/Source/StudyFrameworkPlugin/Private/Logging/SFLoggingUtils.cpp +++ b/Source/StudyFrameworkPlugin/Private/Logging/SFLoggingUtils.cpp @@ -34,7 +34,7 @@ void FSFLoggingUtils::SetupLoggingStreams() ILogStream* SFLog = UniLog.NewLogStream("SFLog", "StudyFramework/DebuggingLogs", "SFLog.txt", false); SFLog->SetLogToDefaultLog(true); - //ParticipantLog, PositionLog, GazeTrackingLog are set up in Participant init function + //ParticipantLog, PositionLog, GazeTrackingLog are set up in SFParticipant::SetupLoggingStreams() function ILogStream* SFErrorLog = UniLog.NewLogStream("SFErrorLog", "StudyFramework/DebuggingLogs", "SFLog.txt", false); SFErrorLog->SetLogToDefaultLog(true); diff --git a/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp b/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp index 2487d90..fa98ec3 100644 --- a/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp +++ b/Source/StudyFrameworkPlugin/Private/SFGameInstance.cpp @@ -131,10 +131,14 @@ void USFGameInstance::RestoreLastParticipantForDebugStart(USFCondition* InStartC const int ParticipantID = USFParticipant::GetLastParticipantId(); Participant = NewObject<USFParticipant>(this, FName(TEXT("Participant_") + FString::FromInt(ParticipantID))); + + StudySetup = USFParticipant::GetLastParticipantSetup(); + Participant->Initialize(ParticipantID); + Participant->SetupLoggingStreams(StudySetup->UseGazeTracker != EGazeTrackerMode::NotTracking); Participant->LoadConditionsFromJson(); - StudySetup = USFParticipant::GetLastParticipantSetup(); + InitFadeHandler(StudySetup->FadeConfig); StartCondition = InStartCondition; @@ -240,6 +244,7 @@ void USFGameInstance::PrepareWithStudySetup(ASFStudySetup* Setup) Participant = NewObject<USFParticipant>(this, FName(TEXT("Participant_") + FString::FromInt(ParticipantID))); Participant->Initialize(ParticipantID); + Participant->SetupLoggingStreams(StudySetup->UseGazeTracker != EGazeTrackerMode::NotTracking); Participant->SetStudyConditions(Conditions); if (bRecoverParticipantData) diff --git a/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp b/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp index 2fe47e0..b7fd611 100644 --- a/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp +++ b/Source/StudyFrameworkPlugin/Private/SFParticipant.cpp @@ -22,19 +22,24 @@ bool USFParticipant::Initialize(int Participant) { ParticipantID = Participant; + StartTime = FPlatformTime::Seconds(); + + return true; +} +void USFParticipant::SetupLoggingStreams(bool bGazeTracking) +{ const FString Timestamp = FDateTime::Now().ToString(); const FString Filename = "LogParticipant-" + FString::FromInt(ParticipantID) + "_" + Timestamp + ".txt"; ILogStream* ParticipantLog = UniLog.NewLogStream("ParticipantLog", "StudyFramework/StudyLogs/ParticipantLogs", - Filename, false); + Filename, false); ILogStream* PositionLog = UniLog.NewLogStream("PositionLog", "StudyFramework/StudyLogs/PositionLogs", - "Position"+Filename, false); - if(USFGameInstance::Get()->GetStudySetup()->UseGazeTracker != EGazeTrackerMode::NotTracking) + "Position" + Filename, false); + if (bGazeTracking) { ILogStream* GazeTrackingLog = UniLog.NewLogStream("GazeTrackingLog", "StudyFramework/StudyLogs/GazeTrackingLogs", "GazeTracking" + Filename, false); } - StartTime = FPlatformTime::Seconds(); if (USFGameInstance::Get()) { USFGameInstance::Get()->GetLogObject()->WritePositionLogHeaderRow(); @@ -44,7 +49,6 @@ bool USFParticipant::Initialize(int Participant) { FSFLoggingUtils::Log("GameInstance not set up yet, no header rows are written to participant logs."); } - return true; } void USFParticipant::SetStudyConditions(TArray<USFCondition*> NewConditions) diff --git a/Source/StudyFrameworkPlugin/Public/SFParticipant.h b/Source/StudyFrameworkPlugin/Public/SFParticipant.h index 9c73aef..6a0f89e 100644 --- a/Source/StudyFrameworkPlugin/Public/SFParticipant.h +++ b/Source/StudyFrameworkPlugin/Public/SFParticipant.h @@ -29,6 +29,7 @@ public: ~USFParticipant(); bool Initialize(int Participant); + void SetupLoggingStreams(bool bGazeTracking); void SetStudyConditions(TArray<USFCondition*> NewConditions); bool StartStudy(); -- GitLab From 9e63c45a82183d677d6995e248f33bc1cdbbdce9 Mon Sep 17 00:00:00 2001 From: "RZ-WIN\\vr-admin" <account@vr.rwth-aachen.de> Date: Thu, 24 Nov 2022 14:43:36 +0100 Subject: [PATCH 7/9] imrpove gaze tracking and logging --- .../Private/GazeTracking/SFGazeTracker.cpp | 65 +++++++++++++------ .../Private/HUD/SFMasterHUD.cpp | 4 ++ .../Private/Logging/SFLogObject.cpp | 12 ++-- .../Public/GazeTracking/SFGazeTracker.h | 11 +++- .../Public/HUD/SFMasterHUD.h | 2 + 5 files changed, 69 insertions(+), 25 deletions(-) diff --git a/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp b/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp index a22bf73..f98c1ac 100644 --- a/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp +++ b/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp @@ -34,10 +34,11 @@ void USFGazeTracker::Init(EGazeTrackerMode Mode) } } -FGazeRay USFGazeTracker::GetGazeDirection() +FGazeRay USFGazeTracker::GetLocalGazeDirection() { if(!IsTrackingEyes()) { + // if no eye tracker is used we always "look ahead" FGazeRay GazeRay; GazeRay.Origin = FVector::ZeroVector; GazeRay.Direction = FVector::ForwardVector;; @@ -54,29 +55,52 @@ FGazeRay USFGazeTracker::GetGazeDirection() return GazeRay; } -FString USFGazeTracker::GetCurrentGazeTarget() +FGazeRay USFGazeTracker::GetWorldGazeDirection() { - FString GazedAtTarget = ""; - const float Distance = 1000.0f; - - FGazeRay GazeRay = GetGazeDirection(); - // if no eye tracker is used we always "look ahead" - // GazeDirection = FVector(1,0,0); + FGazeRay LocalGazeRay = GetLocalGazeDirection(); UWorld* World = USFGameInstance::Get()->GetWorld(); //the gaze ray is relative to the HMD const APlayerCameraManager* CamManager = World->GetFirstPlayerController()-> - PlayerCameraManager; + PlayerCameraManager; const FVector CameraLocation = CamManager->GetCameraLocation(); const FRotator CameraRotation = CamManager->GetCameraRotation(); - const FVector RayCastOrigin = CameraLocation + CameraRotation.RotateVector(GazeRay.Origin); - const FVector RayCastEnd = (CameraRotation.RotateVector(GazeRay.Direction) * Distance) + RayCastOrigin; + + FGazeRay GazeRay; + GazeRay.Origin = CameraLocation + CameraRotation.RotateVector(LocalGazeRay.Origin); + GazeRay.Direction = CameraRotation.RotateVector(LocalGazeRay.Direction); + + return GazeRay; +} + +FString USFGazeTracker::GetCurrentGazeTarget() +{ + FString GazedAtTarget = ""; + const float Distance = 1000.0f; + + FGazeRay GazeRay = GetWorldGazeDirection(); + + + const FVector RayCastOrigin = GazeRay.Origin; + const FVector RayCastEnd = (GazeRay.Direction * Distance) + RayCastOrigin; //FSFUtils::Log("Cast Ray from "+RayCastOrigin.ToString()+" to "+RayCastEnd.ToString()); FHitResult HitResult; - World->LineTraceSingleByChannel(HitResult, RayCastOrigin, RayCastEnd, EYE_TRACKING_TRACE_CHANNEL); + UWorld* World = USFGameInstance::Get()->GetWorld(); + FCollisionQueryParams QueryParams; + QueryParams.AddIgnoredActor(World->GetFirstPlayerController()->AcknowledgedPawn); + QueryParams.AddIgnoredActor(USFGameInstance::Get()->GetHUD()->GetHUDHelper()); + + World->LineTraceSingleByChannel(HitResult, RayCastOrigin, RayCastEnd, EYE_TRACKING_TRACE_CHANNEL, QueryParams); + + if (bDebugRenderRayTraces) + { + //this line trace is more comfortable for debug drawing, however has problems with channel tracing, so we use LineTraceSingleByChannel() above + FHitResult TmpHitRes; + UKismetSystemLibrary::LineTraceSingle(World, RayCastOrigin, RayCastEnd, ETraceTypeQuery::TraceTypeQuery4, false, {}, EDrawDebugTrace::ForDuration, TmpHitRes, true); + } if (HitResult.bBlockingHit) @@ -104,17 +128,20 @@ FString USFGazeTracker::GetCurrentGazeTarget() void USFGazeTracker::LaunchCalibration() { #ifdef WITH_SRANIPAL - //TODO: not tested yet! ViveSR::anipal::Eye::LaunchEyeCalibration(nullptr); #endif } bool USFGazeTracker::IsTrackingEyes() { - //TODO: maybe use - //#ifdef WITH_SRANIPAL - //ViveSR::anipal::AnipalStatus Status; - //int Error = ViveSR::anipal::GetStatus(ViveSR::anipal::Eye::ANIPAL_TYPE_EYE_V2, &Status); - //#endif - return bEyeTrackingStarted; + if (!bEyeTrackingStarted) + return false; + //TODO: this does not seem to work properly!!!! check gaze logs +#ifdef WITH_SRANIPAL + ViveSR::anipal::AnipalStatus Status; + int Error = ViveSR::anipal::GetStatus(ViveSR::anipal::Eye::ANIPAL_TYPE_EYE_V2, &Status); + return Status == ViveSR::anipal::AnipalStatus::WORKING; +#endif + + return true; } diff --git a/Source/StudyFrameworkPlugin/Private/HUD/SFMasterHUD.cpp b/Source/StudyFrameworkPlugin/Private/HUD/SFMasterHUD.cpp index e4f63fb..cd18fb6 100644 --- a/Source/StudyFrameworkPlugin/Private/HUD/SFMasterHUD.cpp +++ b/Source/StudyFrameworkPlugin/Private/HUD/SFMasterHUD.cpp @@ -245,3 +245,7 @@ void ASFMasterHUD::OnShowConditionsButtonPressed() } } } + +const ASFHMDSpectatorHUDHelp* ASFMasterHUD::GetHUDHelper() { + return HMDHUDHelper; +} diff --git a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp index 144257c..d646a53 100644 --- a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp +++ b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp @@ -105,8 +105,8 @@ void USFLogObject::WriteGazeTrackingLogHeaderRow() { "\t" + FString("Condition") + "\t" + FString("UsingEyetracking") + "\t" + FString("GazeTarget") + - "\t" + FString("HeadRotation-Origin") + - "\t" + FString("HeadRotation-Direction"); + "\t" + FString("Gaze-Origin-X-Y-Z") + + "\t" + FString("Gaze-Direction-X-Y-Z"); UniLog.Log(GazeTrackingLogHeader, "GazeTrackingLog"); } @@ -127,8 +127,12 @@ void USFLogObject::WriteGazeTrackingLogToFile() { "\t" + CurrentCondition + "\t" + isTrackingEyes + "\t" + GazeTarget + - "\t" + GazeTracker->GetGazeDirection().Origin.ToCompactString() + - "\t" + GazeTracker->GetGazeDirection().Direction.ToCompactString(); + "\t" + FString::Printf(TEXT("%.3f"), GazeTracker->GetWorldGazeDirection().Origin.X) + + "\t" + FString::Printf(TEXT("%.3f"), GazeTracker->GetWorldGazeDirection().Origin.Y) + + "\t" + FString::Printf(TEXT("%.3f"), GazeTracker->GetWorldGazeDirection().Origin.Z) + + "\t" + FString::Printf(TEXT("%.3f"), GazeTracker->GetWorldGazeDirection().Direction.X) + + "\t" + FString::Printf(TEXT("%.3f"), GazeTracker->GetWorldGazeDirection().Direction.Y) + + "\t" + FString::Printf(TEXT("%.3f"), GazeTracker->GetWorldGazeDirection().Direction.Z); if (UniLog.GetLogStream("GazeTrackingLog")) { UniLog.Log(out, "GazeTrackingLog"); diff --git a/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h b/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h index 96b9bc0..f1a8d4a 100644 --- a/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h +++ b/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h @@ -30,20 +30,27 @@ class STUDYFRAMEWORKPLUGIN_API USFGazeTracker : public UObject public: void Init(EGazeTrackerMode Mode); - //returns pair of Origin and Direction, relative to the head! + //returns pair of Origin and Direction, in world coordinates UFUNCTION(BlueprintCallable) - FGazeRay GetGazeDirection(); + FGazeRay GetWorldGazeDirection(); //returns the name of the gaze target or empty string if none found or not tracking UFUNCTION(BlueprintCallable) FString GetCurrentGazeTarget(); + //returns pair of Origin and Direction, relative to the head! + UFUNCTION(BlueprintCallable) + FGazeRay GetLocalGazeDirection(); + UFUNCTION(BlueprintCallable) void LaunchCalibration(); UFUNCTION(BlueprintCallable) bool IsTrackingEyes(); + UPROPERTY(BlueprintReadWrite) + bool bDebugRenderRayTraces = false; + private: bool bEyeTrackingStarted = false; diff --git a/Source/StudyFrameworkPlugin/Public/HUD/SFMasterHUD.h b/Source/StudyFrameworkPlugin/Public/HUD/SFMasterHUD.h index a674f75..5ab2e32 100644 --- a/Source/StudyFrameworkPlugin/Public/HUD/SFMasterHUD.h +++ b/Source/StudyFrameworkPlugin/Public/HUD/SFMasterHUD.h @@ -61,6 +61,8 @@ public: UFUNCTION() void OnShowConditionsButtonPressed(); + const ASFHMDSpectatorHUDHelp* GetHUDHelper(); + protected: UPROPERTY(VisibleAnywhere) USFHUDWidget* HUDWidget; -- GitLab From 42d91d0f14da738c495a92733cc4fc14557e0be2 Mon Sep 17 00:00:00 2001 From: "RZ-WIN\\vr-admin" <account@vr.rwth-aachen.de> Date: Fri, 25 Nov 2022 14:04:22 +0100 Subject: [PATCH 8/9] is Tracking Eyes fixed --- .../Private/GazeTracking/SFGazeTracker.cpp | 12 +++++++----- .../Private/Logging/SFLogObject.cpp | 2 +- .../Public/GazeTracking/SFGazeTracker.h | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp b/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp index f98c1ac..9838a59 100644 --- a/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp +++ b/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp @@ -36,7 +36,7 @@ void USFGazeTracker::Init(EGazeTrackerMode Mode) FGazeRay USFGazeTracker::GetLocalGazeDirection() { - if(!IsTrackingEyes()) + if(!bEyeTrackingStarted) { // if no eye tracker is used we always "look ahead" FGazeRay GazeRay; @@ -136,11 +136,13 @@ bool USFGazeTracker::IsTrackingEyes() { if (!bEyeTrackingStarted) return false; - //TODO: this does not seem to work properly!!!! check gaze logs + #ifdef WITH_SRANIPAL - ViveSR::anipal::AnipalStatus Status; - int Error = ViveSR::anipal::GetStatus(ViveSR::anipal::Eye::ANIPAL_TYPE_EYE_V2, &Status); - return Status == ViveSR::anipal::AnipalStatus::WORKING; + ViveSR::anipal::Eye::EyeData_v2 Data; + ViveSR::anipal::Eye::GetEyeData_v2(&Data); + + //no_user apparently is true, when a user is there... (weird but consistent) + return Data.no_user; #endif return true; diff --git a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp index d646a53..c3d2e26 100644 --- a/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp +++ b/Source/StudyFrameworkPlugin/Private/Logging/SFLogObject.cpp @@ -103,7 +103,7 @@ void USFLogObject::WritePositionLogToFile() { void USFLogObject::WriteGazeTrackingLogHeaderRow() { FString GazeTrackingLogHeader = FString("ElapsedTime") + "\t" + FString("Condition") + - "\t" + FString("UsingEyetracking") + + "\t" + FString("TrackingEyes") + "\t" + FString("GazeTarget") + "\t" + FString("Gaze-Origin-X-Y-Z") + "\t" + FString("Gaze-Direction-X-Y-Z"); diff --git a/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h b/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h index f1a8d4a..0aee44b 100644 --- a/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h +++ b/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h @@ -45,6 +45,7 @@ public: UFUNCTION(BlueprintCallable) void LaunchCalibration(); + //whether currently the eyes are tracked, otherwise head-forward is used (this can change during execution if the HMD is taken off etc.) UFUNCTION(BlueprintCallable) bool IsTrackingEyes(); -- GitLab From 63aae67299fde488ca63d5b3fad67530ec845173 Mon Sep 17 00:00:00 2001 From: "RZ-WIN\\vr-admin" <account@vr.rwth-aachen.de> Date: Fri, 25 Nov 2022 14:12:37 +0100 Subject: [PATCH 9/9] fix minor merge error (fixing the same bug in two branchen in different ways... tzzzz...) --- Source/StudyFrameworkPlugin/Private/SFStudySetup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/StudyFrameworkPlugin/Private/SFStudySetup.cpp b/Source/StudyFrameworkPlugin/Private/SFStudySetup.cpp index 5ac661f..684c0af 100644 --- a/Source/StudyFrameworkPlugin/Private/SFStudySetup.cpp +++ b/Source/StudyFrameworkPlugin/Private/SFStudySetup.cpp @@ -148,7 +148,7 @@ void ASFStudySetup::GenerateTestStudyRuns() const { const TArray<USFCondition*> Conditions = GetAllConditionsForRun(ParticipantID); USFParticipant* TmpParticipant = NewObject<USFParticipant>(); - TmpParticipant->Initialize(ParticipantID, true); + TmpParticipant->Initialize(ParticipantID); TmpParticipant->SetStudyConditions(Conditions); //this also saves it to json } } -- GitLab