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