Mind Control with C# (and the Emotiv and Emotiv Engine Client Library)

Description

Today's Wild Wednesday project is one that's mind blowing (well actually, mind reading).

Emotiv Engine Client Library

I finally got my act together and posted the code for my EmoEngineClientLibrary, which is a C# wrapper around the DotNetEmotivSDK.dll assembly that ships with the Emotiv SDK.

You may recall this code library from such blog posts as:

With this API, you can collect realtime neurodata from the EPOC headset in a managed application. The API simplifies databinding by exposing EmoEngine methods as CLR properties. Also, it provides a PropertyChanged event that notifies your code when new neurodata and other signals arrive. You also get a lightweight WPF visualization library that renders neurodata in realtime.

emoClient4_3

Emotiv Engine Client

Project Description
Provides an event-driven .NET framework wrapper around the managed Emotiv EPOC neuroheadset API.
Requirements

  • Emotiv EPOC neuroheadset Research Edition SDK: Available from Emotiv, list price $750.00.
  • Visual Studio 2010: Available from Microsoft.
  • Windows 7 or higher: Widely available, e.g., Microsoft Store.


Documentation
Reasonably complete documentation (EmoEngineClientLibrary Documentation) is built in the project by using Sandcastle. A brief overview is provided in the Documentation tab.

So lets take a peek at the Solution.

image

If you get an error loading the Documentation project, Documentation.shfbproj, and you're interested in see it (it's not required or build critical, it's the Sandcastle related doc builder) check out the Sandcastle Help File Builder and the installer on SHFB v1.9.3.4 Beta 2 (VS2010 Support). On a related note, the guided installer for SHFB v1.9.3.4 Beta 2 is pretty neat all in itself. It walks you through checking for and installing the many components and parts that make up Sandcastle and the Sandcastle Help File Builder.

image

imageimageimage

What's cool is that the library implements IPropertyNotify so you can use binding.

<DockPanel >

            <eecontrol:NeuroHeadsetStatusControl HeadsetDataSource="{StaticResource emoEngineClient}" BorderBrush="{StaticResource VaLightBorderBrush}" BorderThickness="1" >

            </eecontrol:NeuroHeadsetStatusControl>

            <Grid x:Name="_neuroDataGrid" HorizontalAlignment="Stretch" Height="Auto" Width="Auto">
                <Grid.RowDefinitions>
                    <RowDefinition Height="25" />
                    <RowDefinition Height="25" />
                    <RowDefinition Height="25" />
                    <RowDefinition Height="139.695*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Label Name="label1" VerticalContentAlignment="Center" Padding="0" Foreground="{StaticResource VaLightBlueBrush}">Polling</Label>
                <Label Grid.Column="1" Name="label3" Background="{Binding Source={StaticResource emoEngineClient}, Path=IsPolling, Converter={StaticResource boolToBrushConverter} }" ></Label>
                <Label Name="label2" Grid.Row="1" VerticalContentAlignment="Center" Padding="0" Foreground="{StaticResource VaLightBlueBrush}" >Sampling Rate</Label>
                <Label Grid.Column="1" Grid.Row="1" Name="label4" Content="{Binding Source={StaticResource emoEngineClient}, Path=SamplingRate}" Foreground="{StaticResource VaLightBlueBrush}" ></Label>
                <Label  Grid.Row="2" VerticalContentAlignment="Center" Padding="0" Foreground="{StaticResource VaLightBlueBrush}">Buffer Size</Label>
                <Label Grid.Column="1" Grid.Row="2" Content="{Binding Source={StaticResource emoEngineClient}, Path=BufferSize}" Foreground="{StaticResource VaLightBlueBrush}"></Label>
                <eecontrol:NeuroDataControl x:Name="_neuroDataControl" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" DataFrameSource="{StaticResource emoEngineClient}" ChannelsToDisplay="{StaticResource channelsToDisplay}" HorizontalAlignment="Stretch" BorderBrush="{StaticResource VaLightBorderBrush}" Foreground="{StaticResource VaLightBlueBrush}" />
                <Label Height="28" Name="_watermarkLabel" Foreground="#99FFFFFF" Grid.Column="1" Margin="0" Grid.Row="3" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="Auto">Copyright © James Galasyn 2010</Label>

            </Grid>

        </DockPanel>

One of the other things mentioned is the event driven capability of the library. Here's some related snips;

void engine_EmoStateUpdated( object sender, EmoStateUpdatedEventArgs e )
        {
            // ctor clones the EmoState object.
            EmoState emoState = new EmoState( e.emoState );

            // Notifies the client thread that the EmotivState changed.
            this._processEventsWorker.ReportProgress( 0, emoState );
        }

        void engine_InternalStateChanged( object sender, EmoEngineEventArgs e )
        {
            Trace.WriteLine( e.ToString() );
        }

        void engine_EmoEngineConnected( object sender, EmoEngineEventArgs e )
        {
            this.UserID = e.userId;
        }

        void emotivEngine_UserAdded( object sender, EmoEngineEventArgs e )
        {
            this.UserID = e.userId;
        }

What are the States?

imageimage

image

Okay, maybe it doesn't really read your mind, but the possibilities of the kinds of apps you can build (say like a mind reading skateboard) are mind blowing, aren't they?

 

Here’s a few more links you might find interesting:

The Discussion

  • User profile image
    alex

    would like to get a headset but having to pay $200 more just to use it as a developer kind of ruins it for me.

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to send us feedback you can Contact Us.