Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Eye-Tracking Classroom
/
gaze-server.cs
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
1
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
3663b358
authored
5 years ago
by
Stefan Schreistetter
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added Fake Tracker Class. re-implemented Gaze decimator.
parent
54d4ce37
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
193 additions
and
114 deletions
+193
-114
GazeWebSocketServer/Program.cs
+8
-25
TrackerBridge/DSP/GazeDecimator.cs
+53
-50
TrackerBridge/DSP/IGazeFilter.cs
+2
-3
TrackerBridge/FakeTracker.cs
+61
-0
TrackerBridge/GazeData.cs
+12
-0
TrackerBridge/GazeDataProcessor.cs
+32
-17
TrackerBridge/IBridgeTracker.cs
+10
-1
TrackerBridge/TobiiEyeTracker.cs
+10
-17
TrackerBridge/TrackerBridge.csproj
+5
-1
No files found.
GazeWebSocketServer/Program.cs
View file @
3663b358
using
System
;
using
System.Threading.Tasks
;
using
TrackerBridge
;
using
System.Windows.Forms
;
using
System.Drawing
;
using
System.Timers
;
using
TrackerBridge.DSP
;
namespace
GazeWebSocketServer
...
...
@@ -11,16 +8,18 @@ namespace GazeWebSocketServer
public
class
Program
{
private
static
GazeServer
gazeServer
;
private
static
GazeDecimatorFixedLength
decimator
=
new
GazeDecimatorFixedLength
(
1
,
600
);
public
static
void
Main
(
string
[]
args
)
{
ConfigurationData
.
InitializeUnexistingWithDefaults
();
ConfigurationData
config
=
ConfigurationData
.
ParseToObject
();
IBridgeTracker
tracker
;
if
(
args
.
Length
>
0
&&
args
[
0
]
==
"-d"
)
{
Task
.
Run
(()
=>
SimulateGazeDataHz
(
600
));
tracker
=
new
FakeTracker
(
600
);
tracker
.
GazeDataAvailable
+=
OnGazeDataAvailable
;
//TODO: Extend interface usage
//tracker.GazeDataProcessor.OutputFrequency = config.OutputFrequency;
}
else
{
...
...
@@ -36,25 +35,9 @@ namespace GazeWebSocketServer
Console
.
ReadLine
();
}
private
static
void
SimulateGazeDataHz
(
Int32
frequency
)
{
System
.
Timers
.
Timer
timer
=
new
System
.
Timers
.
Timer
(
1000.0
/
frequency
);
timer
.
Elapsed
+=
(
Object
sender
,
ElapsedEventArgs
e
)
=>
{
Point
mousePosition
=
Control
.
MousePosition
;
GazeData
data
=
new
GazeData
(
mousePosition
.
X
,
mousePosition
.
Y
,
mousePosition
.
X
,
mousePosition
.
Y
,
0
,
0
);
if
(
gazeServer
!=
null
&&
gazeServer
.
isRunning
)
{
decimator
.
Input
(
data
);
if
(
decimator
.
Output
.
HasValue
)
gazeServer
.
Publish
(
data
);
}
};
timer
.
AutoReset
=
true
;
timer
.
Start
();
}
private
static
void
OnGazeDataAvailable
(
TobiiEyeTracker
sender
,
GazeData
data
)
private
static
void
OnGazeDataAvailable
(
GazeData
data
,
Object
sender
)
{
if
(
gazeServer
!=
null
&&
gazeServer
.
isRunning
)
{
...
...
@@ -62,12 +45,12 @@ namespace GazeWebSocketServer
}
}
private
static
void
OnConnectionTimeout
(
TobiiEy
eTracker
sender
)
private
static
void
OnConnectionTimeout
(
IBridg
eTracker
sender
)
{
Console
.
WriteLine
(
"Timeout while searching for trackers."
);
}
private
static
void
OnConnectionEstablished
(
TobiiEy
eTracker
sender
)
private
static
void
OnConnectionEstablished
(
IBridg
eTracker
sender
)
{
Console
.
WriteLine
(
$"Tracker
{
sender
.
SerialNumber
}
connected."
);
ConfigurationData
config
=
ConfigurationData
.
ParseToObject
();
...
...
This diff is collapsed.
Click to expand it.
TrackerBridge/DSP/GazeDecimator
FixedLength
.cs
→
TrackerBridge/DSP/GazeDecimator.cs
View file @
3663b358
...
...
@@ -3,91 +3,94 @@ using System.Collections.Generic;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
using
System.Timers
;
namespace
TrackerBridge.DSP
{
public
class
GazeDecimatorFixedLength
:
IGazeFilter
class
GazeDecimator
:
IGazeFilter
{
p
rivate
GazeData
[]
buffer
;
private
Int32
currentValueIndex
;
p
ublic
event
GazeDataHandler
OutputAvailable
;
private
Single
inputFrequency
;
private
GazeData
?
output
;
private
GazeData
output
;
private
Single
outputFrequency
;
private
Object
outputLock
=
new
Object
();
private
Object
inputLock
=
new
Object
();
private
Object
valueCountLock
=
new
Object
();
private
Int64
valueCount
;
public
event
EventHandler
<
GazeData
>
OutputAvailable
;
public
Single
InputFrequency
{
get
{
return
inputFrequency
;
}
public
Single
InputFrequency
{
get
=>
inputFrequency
;
set
=>
inputFrequency
=
value
;
}
private
Int64
ValueCount
{
get
{
lock
(
valueCountLock
)
{
return
valueCount
;
}
}
set
{
inputFrequency
=
value
;
Reset
();
lock
(
valueCountLock
)
{
valueCount
=
value
;
}
}
}
public
GazeData
?
Output
{
private
GazeData
Output
{
get
{
lock
(
outputLock
)
{
GazeData
?
temp
=
null
;
if
(
output
.
HasValue
)
{
temp
=
output
.
Value
;
output
=
null
;
}
return
temp
;
return
output
;
}
}
}
public
Single
OutputFrequency
{
get
{
return
outputFrequency
;
}
set
{
outputFrequency
=
value
;
Reset
();
lock
(
outputLock
)
{
output
=
value
;
}
}
}
public
GazeDecimator
FixedLength
(
Single
outputFrequency
,
Single
inputFrequency
)
public
GazeDecimator
(
Single
outputFrequency
,
Single
inputFrequency
)
{
this
.
outputFrequency
=
outputFrequency
;
this
.
i
nputFrequency
=
inputFrequency
;
Reset
(
);
this
.
I
nputFrequency
=
inputFrequency
;
Task
.
Run
(()
=>
TriggerOutput
(
outputFrequency
)
);
}
public
void
Input
(
GazeData
input
)
public
void
Input
(
GazeData
input
,
Object
sender
=
null
)
{
lock
(
inputLock
)
if
(
ValueCount
==
0
)
{
currentValueIndex
=
(
currentValueIndex
+
1
)
%
buffer
.
Length
;
Output
=
input
;
}
buffer
[
currentValueIndex
]
=
input
;
if
(
currentValueIndex
==
buffer
.
Length
-
1
)
else
{
GazeData
sum
=
buffer
[
0
];
for
(
Int32
index
=
1
;
index
<
buffer
.
Length
;
index
++)
{
sum
+=
buffer
[
index
];
}
sum
/=
buffer
.
Length
;
//Cumulative moving average (CMA) -> https://en.wikipedia.org/wiki/Moving_average#Cumulative_moving_average
lock
(
outputLock
)
{
output
=
sum
;
output
+=
(
input
-
output
)
/
(
ValueCount
+
1
)
;
}
}
}
ValueCount
++;
}
public
void
Reset
()
{
Int32
bufferLength
=
Convert
.
ToInt32
(
InputFrequency
/
OutputFrequency
);
buffer
=
new
GazeData
[
bufferLength
];
currentValueIndex
=
-
1
;
output
=
null
;
ValueCount
=
0
;
}
private
void
TriggerOutput
(
Single
frequency
)
{
Timer
timer
=
new
Timer
(
1000.0
/
frequency
);
//TODO: Implement Dispose
timer
.
Elapsed
+=
(
Object
sender
,
ElapsedEventArgs
e
)
=>
{
if
(
ValueCount
>
0
)
{
OutputAvailable
?.
Invoke
(
Output
,
this
);
Reset
();
}
};
timer
.
AutoReset
=
true
;
timer
.
Start
();
}
}
}
This diff is collapsed.
Click to expand it.
TrackerBridge/DSP/IGazeFilter.cs
View file @
3663b358
...
...
@@ -8,9 +8,8 @@ namespace TrackerBridge.DSP
{
interface
IGazeFilter
{
event
EventHandler
<
GazeData
>
OutputAvailable
;
GazeData
?
Output
{
get
;
}
void
Input
(
GazeData
input
);
event
GazeDataHandler
OutputAvailable
;
void
Input
(
GazeData
input
,
Object
sender
=
null
);
void
Reset
();
}
}
This diff is collapsed.
Click to expand it.
TrackerBridge/FakeTracker.cs
0 → 100644
View file @
3663b358
using
System
;
using
System.Drawing
;
using
System.Threading.Tasks
;
using
System.Timers
;
using
System.Windows.Forms
;
namespace
TrackerBridge
{
public
class
FakeTracker
:
IBridgeTracker
{
private
event
GazeDataHandler
gazeDataAvailable
;
public
event
GazeDataHandler
GazeDataAvailable
{
add
{
gazeDataAvailable
+=
value
;
GazeDataProcessor
.
AddClient
(
value
);
}
remove
{
gazeDataAvailable
-=
value
;
GazeDataProcessor
.
RemoveClient
(
value
);
}
}
public
event
EventHandler
<
Single
>
TrackingFrequencyChanged
;
private
Single
trackerFrequency
;
public
GazeDataHandler
GazeDataAvailableMembers
=>
gazeDataAvailable
;
public
String
SerialNumber
=>
throw
new
NotImplementedException
();
public
GazeDataProcessor
GazeDataProcessor
{
get
;
}
public
FakeTracker
(
Single
frequency
)
{
trackerFrequency
=
frequency
;
GazeDataProcessor
=
new
GazeDataProcessor
(
this
);
//GazeDataProcessor.OutputFrequency = 1;
Task
.
Run
(()
=>
SimulateGazeDataHz
(
frequency
));
}
private
void
SimulateGazeDataHz
(
Single
frequency
)
{
System
.
Timers
.
Timer
timer
=
new
System
.
Timers
.
Timer
(
1000.0
/
frequency
);
//TODO: Implement Dispose
timer
.
Elapsed
+=
(
Object
sender
,
ElapsedEventArgs
e
)
=>
{
Point
mousePosition
=
Control
.
MousePosition
;
GazeData
data
=
new
GazeData
(
mousePosition
.
X
,
mousePosition
.
Y
,
mousePosition
.
X
,
mousePosition
.
Y
,
0
,
0
);
GazeDataProcessor
.
Process
(
this
,
data
);
};
timer
.
AutoReset
=
true
;
timer
.
Start
();
}
public
Single
GetTrackingFrequency
()
{
return
trackerFrequency
;
}
public
void
SetTrackingFrequency
(
Single
value
)
{
throw
new
NotImplementedException
();
}
}
}
This diff is collapsed.
Click to expand it.
TrackerBridge/GazeData.cs
View file @
3663b358
...
...
@@ -44,6 +44,18 @@ namespace TrackerBridge
return
result
;
}
public
static
GazeData
operator
-(
GazeData
a
,
GazeData
b
)
{
GazeData
result
=
new
GazeData
(
a
.
leftX
-
b
.
leftX
,
a
.
leftY
-
b
.
leftY
,
a
.
rightX
-
b
.
rightX
,
a
.
rightY
-
b
.
rightY
,
Math
.
Abs
(
a
.
trackerTimeStamp
-
b
.
trackerTimeStamp
),
Math
.
Abs
(
a
.
systemTimeStamp
-
b
.
systemTimeStamp
));
return
result
;
}
public
static
GazeData
operator
/(
GazeData
a
,
Single
b
)
{
GazeData
result
=
new
GazeData
(
a
.
leftX
/
b
,
...
...
This diff is collapsed.
Click to expand it.
TrackerBridge/GazeDataProcessor.cs
View file @
3663b358
...
...
@@ -11,8 +11,6 @@ namespace TrackerBridge
{
public
class
GazeDataProcessor
{
public
event
EventHandler
<
GazeData
>
ProcessedGazeDataAvailable
;
private
readonly
IGazeFilter
[]
gazeFilters
;
private
readonly
Single
screenHeight
;
private
readonly
Single
screenWidth
;
...
...
@@ -26,15 +24,37 @@ namespace TrackerBridge
}
}
public
GazeDataProcessor
(
IBridgeTracker
tracker
)
{
tracker
.
TrackingFrequencyChanged
+=
OnTrackingFrequencyChanged
;
screenHeight
=
Convert
.
ToSingle
(
SystemParameters
.
PrimaryScreenHeight
);
screenWidth
=
Convert
.
ToSingle
(
SystemParameters
.
PrimaryScreenWidth
);
gazeFilters
=
new
IGazeFilter
[
1
];
gazeFilters
[
0
]
=
new
GazeDecimatorFixedLength
(
outputFrequency
,
tracker
.
GetTrackingFrequency
());
gazeFilters
[
0
]
=
new
GazeDecimator
(
60
,
tracker
.
GetTrackingFrequency
());
//TODO: Refactor frequency passthrough
//Chain filters
for
(
Int32
index
=
0
;
index
<
gazeFilters
.
Length
;
index
++)
{
if
(
index
==
gazeFilters
.
Length
-
1
)
{
gazeFilters
[
index
].
OutputAvailable
+=
tracker
.
GazeDataAvailableMembers
;
}
else
{
gazeFilters
[
index
].
OutputAvailable
+=
gazeFilters
[
index
+
1
].
Input
;
}
}
}
public
void
AddClient
(
GazeDataHandler
gazeDataHandler
)
{
gazeFilters
[
gazeFilters
.
Length
-
1
].
OutputAvailable
+=
gazeDataHandler
;
}
public
void
RemoveClient
(
GazeDataHandler
gazeDataHandler
)
{
gazeFilters
[
gazeFilters
.
Length
-
1
].
OutputAvailable
-=
gazeDataHandler
;
}
public
void
Initialize
()
{
foreach
(
IGazeFilter
filter
in
gazeFilters
)
...
...
@@ -42,8 +62,8 @@ namespace TrackerBridge
filter
.
Reset
();
}
}
public
GazeData
?
Process
(
GazeDataEventArgs
e
)
public
void
Process
(
Object
sender
,
GazeDataEventArgs
e
)
{
GazeData
data
=
new
GazeData
(
e
.
LeftEye
.
GazePoint
.
PositionOnDisplayArea
.
X
*
screenWidth
,
e
.
LeftEye
.
GazePoint
.
PositionOnDisplayArea
.
Y
*
screenHeight
,
...
...
@@ -53,23 +73,18 @@ namespace TrackerBridge
e
.
SystemTimeStamp
);
gazeFilters
[
0
].
Input
(
data
);
for
(
Int32
index
=
1
;
index
<
gazeFilters
.
Length
;
index
++)
{
if
(
gazeFilters
[
index
-
1
].
Output
.
HasValue
)
{
gazeFilters
[
index
].
Input
(
gazeFilters
[
index
-
1
].
Output
.
Value
);
}
}
//TODO: If output, invoke event
return
gazeFilters
[
gazeFilters
.
Length
-
1
].
Output
;
}
public
void
Process
(
Object
sender
,
GazeData
input
)
{
gazeFilters
[
0
].
Input
(
input
);
}
private
void
OnTrackingFrequencyChanged
(
Object
sender
,
Single
frequency
)
{
foreach
(
IGazeFilter
filter
in
gazeFilters
)
{
if
(
filter
.
GetType
()
==
typeof
(
GazeDecimator
FixedLength
))
if
(
filter
.
GetType
()
==
typeof
(
GazeDecimator
))
{
GazeDecimator
FixedLength
decimator
=
(
GazeDecimatorFixedLength
)
filter
;
GazeDecimator
decimator
=
(
GazeDecimator
)
filter
;
decimator
.
InputFrequency
=
frequency
;
}
}
...
...
This diff is collapsed.
Click to expand it.
TrackerBridge/IBridgeTracker.cs
View file @
3663b358
...
...
@@ -6,10 +6,19 @@ using System.Threading.Tasks;
namespace
TrackerBridge
{
public
delegate
void
ConnectionEventHandler
(
IBridgeTracker
sender
);
public
delegate
void
GazeDataHandler
(
GazeData
data
,
Object
sender
);
public
interface
IBridgeTracker
{
event
GazeDataHandler
GazeDataAvailable
;
event
EventHandler
<
Single
>
TrackingFrequencyChanged
;
void
SetTrackingFrequency
(
Single
value
);
GazeDataHandler
GazeDataAvailableMembers
{
get
;
}
GazeDataProcessor
GazeDataProcessor
{
get
;}
String
SerialNumber
{
get
;
}
Single
GetTrackingFrequency
();
void
SetTrackingFrequency
(
Single
value
);
}
}
This diff is collapsed.
Click to expand it.
TrackerBridge/TobiiEyeTracker.cs
View file @
3663b358
...
...
@@ -9,8 +9,8 @@ namespace TrackerBridge
{
public
class
TobiiEyeTracker
:
IBridgeTracker
{
public
delegate
void
ConnectionEventHandler
(
TobiiEyeTracker
sender
);
public
delegate
void
GazeDataHandler
(
TobiiEyeTracker
sender
,
GazeData
data
);
//
public delegate void ConnectionEventHandler(TobiiEyeTracker sender);
//
public delegate void GazeDataHandler(TobiiEyeTracker sender, GazeData data);
public
event
ConnectionEventHandler
ConnectionEvent
;
public
event
ConnectionEventHandler
ConnectionTimeout
;
...
...
@@ -19,10 +19,16 @@ namespace TrackerBridge
private
IEyeTracker
eyeTracker
=
null
;
public
GazeDataProcessor
GazeDataProcessor
{
get
;
set
;
}
public
GazeDataProcessor
GazeDataProcessor
{
get
;
}
public
Boolean
IsConnected
{
get
;
private
set
;
}
=
false
;
public
String
SerialNumber
{
get
;
private
set
;
}
=
null
;
public
GazeDataHandler
GazeDataAvailableMembers
{
get
{
return
GazeDataAvailable
;
}
}
public
TobiiEyeTracker
()
{
GazeDataProcessor
=
new
GazeDataProcessor
(
this
);
...
...
@@ -62,10 +68,6 @@ namespace TrackerBridge
eyeTracker
.
SetGazeOutputFrequency
(
value
);
}
}
void
IBridgeTracker
.
SetTrackingFrequency
(
Single
value
)
{
throw
new
NotImplementedException
();
}
private
void
InitiateConnection
()
{
...
...
@@ -103,22 +105,13 @@ namespace TrackerBridge
ConnectionTimeout
?.
Invoke
(
this
);
}
}
eyeTracker
.
GazeDataReceived
+=
OnGazeDataReceived
;
eyeTracker
.
GazeDataReceived
+=
GazeDataProcessor
.
Process
;
eyeTracker
.
GazeOutputFrequencyChanged
+=
OnGazeOutputFrequencyChanged
;
SerialNumber
=
eyeTracker
.
SerialNumber
;
SetTrackingFrequency
(
600f
);
ConnectionEvent
?.
Invoke
(
this
);
}
private
void
OnGazeDataReceived
(
object
sender
,
GazeDataEventArgs
e
)
{
GazeData
?
gazeData
=
GazeDataProcessor
.
Process
(
e
);
if
(
gazeData
.
HasValue
)
{
GazeDataAvailable
?.
Invoke
(
this
,
gazeData
.
Value
);
}
}
private
void
OnGazeOutputFrequencyChanged
(
Object
sender
,
GazeOutputFrequencyEventArgs
e
)
{
TrackingFrequencyChanged
?.
Invoke
(
this
,
e
.
GazeOutputFrequency
);
...
...
This diff is collapsed.
Click to expand it.
TrackerBridge/TrackerBridge.csproj
View file @
3663b358
...
...
@@ -34,9 +34,12 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
...
...
@@ -48,7 +51,8 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="DSP\GazeDecimatorFixedLength.cs" />
<Compile Include="DSP\GazeDecimator.cs" />
<Compile Include="FakeTracker.cs" />
<Compile Include="GazeData.cs" />
<Compile Include="GazeDataProcessor.cs" />
<Compile Include="DSP\IGazeFilter.cs" />
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment