NAV
C++ C# Python

Introduction

cout << "Sensing is Fun!" << endl;

//you can get the version of MSCL like this
cout << mscl::LibVersion::asString() << endl;
Console.WriteLine("Sensing is Fun!");

//you can get the version of MSCL like this
Console.WriteLine(mscl.LibVersion.asString());
print "Sensing is Fun!"

# you can get the version of MSCL like this
print mscl.LibVersion.asString()

Welcome to the MSCL (MicroStrain Communication Library) Quick Start Guide!

You can use MSCL to interact with wireless and wired sensors developed by LORD MicroStrain Sensing Systems.

MSCL has language bindings in C++, .NET (C#, VB, LabView, MATLAB), and Python! You can view code examples in the area to the right, and you can switch the programming language of the examples with the tabs above that.

This guide will help get you started with using MSCL. It does not encompass everything that MSCL can do. Please see the complete Documentation for a list of all functionality.

Wireless

Creating a BaseStation

#include "mscl/Communication/Connection.h"
#include "mscl/MicroStrain/Wireless/BaseStation.h"

//create the connection object with port and baud rate
mscl::Connection connection = mscl::Connection::Serial("COM3", 921600);

//create the BaseStation, passing in the connection
mscl::BaseStation basestation(connection);
//create the connection object with port and baud rate
mscl.Connection connection = mscl.Connection.Serial("COM3", 921600);

//create the BaseStation, passing in the connection
mscl.BaseStation basestation = new mscl.BaseStation(connection);
import mscl

#create the connection object with port and baud rate
connection = mscl.Connection.Serial("COM3", 921600)

#create the BaseStation, passing in the connection
basestation = mscl.BaseStation(connection)

Make sure to replace COM3 and 921600 with your own port settings.

To interface with a wireless device, you will first need to create a BaseStation that represents a physical BaseStation or Gateway.

A BaseStation takes a Connection as a parameter.

Serial, TcpIp, and UnixSocket are all available as connection types.

Creating a WirelessNode

#include "mscl/MicroStrain/Wireless/WirelessNode.h"

//create a WirelessNode with the BaseStation
mscl::WirelessNode node(31849, baseStation);
//create a WirelessNode with the BaseStation we created
mscl.WirelessNode node = new mscl.WirelessNode(31849, baseStation);
# create a WirelessNode with the BaseStation we created
node = mscl.WirelessNode(31849, baseStation)

Make sure to replace 31849 with the Node Address of your Wireless Node.

To communicate with any Wireless Node, create a WirelessNode instance, providing the Node Address of the physical Node, and the BaseStation that you wish to communicate to the Node with.

Communicating with a Node

//ping the Node
mscl::PingResponse response = node.ping();

//if the ping response was a success
if(response.success()) 
{
    response.baseRssi(); //the BaseStation RSSI
    response.nodeRssi(); //the Node RSSI
}
//ping the Node
mscl.PingResponse response = node.ping();

//if the ping response was a success
if (response.success())
{
    response.baseRssi(); //the BaseStation RSSI
    response.nodeRssi(); //the Node RSSI
}
# ping the Node
response = node.ping()

# if the ping response was a success
if response.success():
    response.baseRssi() # the BaseStation RSSI
    response.nodeRssi() # the Node RSSI

A Wireless Node, when powered on, can be in 1 of 3 states:

Node State Description
Idle The Node is awake and waiting for commands.
Sleep The Node is in a low power sleep state.
Sampling The Node is actively sampling / sending data.

If a Node is in an Idle state, it will respond to pings, can be configured, and can be put into the other states (sleep or sampling). To test communicating with a WirelessNode that is in an idle state, use the ping() function.

//call the setToIdle function and get the resulting SetToIdleStatus object
mscl::SetToIdleStatus idleStatus = node.setToIdle();

// checks if the set to idle operation has completed (successfully or with a failure)
while(!idleStatus.complete())
{
    cout << ".";

    if(userCancels)
        idleStatus.cancel();
}

//check the result of the Set to Idle operation
switch(idleStatus.result())
{
case mscl::SetToIdleStatus::setToIdleResult_success:
    cout << "Node is now in idle mode." << endl;
    break;

case mscl::SetToIdleStatus::setToIdleResult_canceled:
    cout << "Set to Idle was canceled!" << endl;
    break;

case mscl::SetToIdleStatus::setToIdleResult_failed:
    cout << "Set to Idle has failed!" << endl;
    break;
}
//call the setToIdle function and get the resulting SetToIdleStatus object
mscl.SetToIdleStatus idleStatus = node.setToIdle();

// checks if the Set to Idle operation has completed (successfully or with a failure)
while (!idleStatus.complete())
{
    Console.Write(".");

    if(userCancels)
        idleStatus.cancel();
}

//check the result of the Set to Idle operation
switch (idleStatus.result())
{
    case mscl.SetToIdleStatus.SetToIdleResult.setToIdleResult_success:
        Console.WriteLine("Node is now in idle mode.");
        break;

    case mscl.SetToIdleStatus.SetToIdleResult.setToIdleResult_canceled:
        Console.WriteLine("Set to Idle was canceled!");
        break;

    case mscl.SetToIdleStatus.SetToIdleResult.setToIdleResult_failed:
        Console.WriteLine("Set to Idle has failed!");
        break;
}
# call the setToIdle function and get the resulting SetToIdleStatus object
idleStatus = node.setToIdle()

# checks if the Set to Idle operation has completed (successfully or with a failure)
while not idleStatus.complete():
    print ".",

    if userCancels:
        idleStatus.cancel()

# check the result of the Set to Idle operation
result = idleStatus.result()
if result == mscl.SetToIdleStatus.setToIdleResult_success:
    print "Node is now in idle mode."
elif result == mscl.SetToIdleStatus.setToIdleResult_canceled:
    print "Set to Idle was canceled!"
else:
    print "Set to Idle has failed!"

If a Node is in the Sleep state or Sampling state, it cannot be directly communicated with. In order to communicate with the Node, it must be put back into the Idle state. This can be done by using the setToIdle() function.

The Set to Idle operation uses all of the BaseStation’s bandwidth to attempt to stop/wake the Node. Thus, this can only be performed on a single Node at a time. Once started, the operation will continue until canceled by calling the cancel() function on the SetToIdleStatus object returned from the setToIdle() function.

Configuring a Node

Getting Current Config

//get the number of datalogging sessions stored on the node
node.getNumDatalogSessions();  

//get the user inactivity timeout in seconds
node.getInactivityTimeout();

//get the ActiveChannels
node.getActiveChannels();

//get the number of sweeps to sample for
node.getNumSweeps();

//verify Thermocouple Type is supported by this Node
if(node.features().supportsThermocoupleType())
{
    //get the thermocouple type
    node.getThermocoupleType();
}
//get the number of datalogging sessions stored on the node
node.getNumDatalogSessions();  

//get the user inactivity timeout in seconds
node.getInactivityTimeout();

//get the ActiveChannels
node.getActiveChannels();

//get the number of sweeps to sample for
node.getNumSweeps();

//verify Thermocouple Type is supported by this Node
if(node.features().supportsThermocoupleType())
{
    //get the thermocouple type
    node.getThermocoupleType();
}
# get the number of datalogging sessions stored on the node
node.getNumDatalogSessions()

# get the user inactivity timeout in seconds
node.getInactivityTimeout()

# get the ActiveChannels
node.getActiveChannels()

# get the number of sweeps to sample for
node.getNumSweeps()

# verify Thermocouple Type is supported by this Node
if node.features().supportsThermocoupleType():
    # get the thermocouple type
    node.getThermocoupleType()

To get the current configuration settings of a Wireless Node, each setting has an individual function on the WirelessNode object.

However, not all settings are supported by all Nodes. If a function is called (such as getThermocoupleType()) on a Node that doesn’t support that feature (doesn’t support thermocouples), it will throw an Error_NotSupported exception.

Use the NodeFeatures class (node.features()) to check which features are available for the Wireless Node.















Setting the Config

//create a WirelessNodeConfig which is used to set all node configuration options
mscl::WirelessNodeConfig config;

//set the configuration options that we want to change
config.bootMode(mscl::WirelessTypes::bootMode_normal);
config.inactivityTimeout(7200);
config.samplingMode(mscl::WirelessTypes::samplingMode_sync);
config.sampleRate(mscl::WirelessTypes::sampleRate_256Hz);
config.unlimitedDuration(true);

//apply the configuration to the Node
node.applyConfig(config);
//create a WirelessNodeConfig which is used to set all node configuration options
mscl.WirelessNodeConfig config = new mscl.WirelessNodeConfig();

//set some of the node's configuration options
config.bootMode(mscl.WirelessTypes.BootMode.bootMode_normal);
config.inactivityTimeout(7200);
config.samplingMode(mscl.WirelessTypes.SamplingMode.samplingMode_sync);
config.sampleRate(mscl.WirelessTypes.WirelessSampleRate.sampleRate_256Hz);
config.unlimitedDuration(true);

//apply the configuration to the Node
node.applyConfig(config);
# create a WirelessNodeConfig which is used to set all node configuration options
config = mscl.WirelessNodeConfig()

# set the configuration options that we want to change
config.bootMode(mscl.WirelessTypes.bootMode_normal)
config.inactivityTimeout(7200)
config.samplingMode(mscl.WirelessTypes.samplingMode_sync)
config.sampleRate(mscl.WirelessTypes.sampleRate_256Hz)
config.unlimitedDuration(True)

# apply the configuration to the Node
node.applyConfig(config)

These are just some examples of the Wireless Node config options available. See the complete API Documentation for the full list of available options.

To change configuration settings of a Wireless Nodes, use the WirelessNodeConfig object. This object contains functions for all Wireless Node config options.

When setting an option in the WirelessNodeConfig, the value is just stored on that object itself. The object must then be given as a parameter in the node.applyConfig() function to write all of the changed options to the physical Node. In this way, you can apply the same WirelessNodeConfig object to multiple Nodes if desired.

Some of the configuration options may conflict with other options that are being set, or that are currently set on the Wireless Node. For example, only certain Sample Rates are supported in the Burst Sync Sampling mode. If you only update the WirelessNodeConfig object’s sample rate, this will be checked against the current sampling mode on the Node when applying and will throw an Error_InvalidNodeConfig exception if it is invalid for that sampling mode. If both the sample rate and sampling mode are set in the WirelessNodeConfig, they will be checked against each other before applying to the Node.

Not all settings are supported by all Nodes. If the WirelessNodeConfig has an option set (such as thermocoupleType()) and that config is applied to a Node that doesn’t support that feature (doesn’t support thermocouples), it will throw an Error_InvalidNodeConfig exception.

Use the NodeFeatures class (node.features()) to check which features are available for the Wireless Node.

Starting Sampling

There are 3 main sampling modes: Synchronized Sampling, Non-Synchronized Sampling, and Armed Datalogging.

//create a SyncSamplingNetwork object, giving it the BaseStation that will be the master BaseStation for the network
mscl::SyncSamplingNetwork network(baseStation);

//add a WirelessNode to the network.
//Note: The Node must already be configured for Sync Sampling before adding to the network, or else Error_InvalidNodeConfig will be thrown.
network.addNode(node);

network.ok();               //check if the network status is ok
network.lossless(true);     //enable Lossless for the network
network.percentBandwidth(); //get the total percent of bandwidth of the network

//apply the network configuration to every node in the network
network.applyConfiguration();

//start all the nodes in the network sampling.
network.startSampling();
//create a SyncSamplingNetwork object, giving it the BaseStation that will be the master BaseStation for the network
mscl.SyncSamplingNetwork network = new mscl.SyncSamplingNetwork(baseStation);

//add a WirelessNode to the network.
//Note: The Node must already be configured for Sync Sampling before adding to the network, or else Error_InvalidNodeConfig will be thrown.
network.addNode(node);

network.ok();               //check if the network status is ok
network.lossless(true);     //enable Lossless for the network
network.percentBandwidth(); //get the total percent of bandwidth of the network

//apply the network configuration to every node in the network
network.applyConfiguration();

//start all the nodes in the network sampling.
network.startSampling();
# create a SyncSamplingNetwork object, giving it the BaseStation that will be the master BaseStation for the network
network = mscl.SyncSamplingNetwork(baseStation)

# add a WirelessNode to the network.
# Note: The Node must already be configured for Sync Sampling before adding to the network, or else Error_InvalidNodeConfig will be thrown.
network.addNode(node)

network.ok()                # check if the network status is ok
network.lossless(true)      # enable Lossless for the network
network.percentBandwidth()  # get the total percent of bandwidth of the network

# apply the network configuration to every node in the network
network.applyConfiguration()

# start all the nodes in the network sampling.
network.startSampling()

Synchronized Sampling

Synchronized Sampling involves creating a Time Division Multiple Access (TDMA) network with one or more Wireless Nodes tied to a single Base Station. In this mode, all of the Nodes will have a common timestamp that is transmitted with the data, so that data can be accurately aligned. The BaseStation provides a beacon which keeps the Nodes in the network time-synchronized to +/- 32 microseconds.

To start a Sync Sampling network, create a SyncSamplingNetwork instance. This takes a BaseStation as a parameter, which will be the master BaseStation that communicates with all of the Nodes, starts them sampling, and provides the beacon.

After you have configured all of the Nodes, add them to the network using the networks addNode() function.

Once all of the Nodes have been added to the network, start the network using the network’s startSampling() function.

//start the Non-Sync Sampling session.
node.startNonSyncSampling();
//start the Non-Sync Sampling session.
node.startNonSyncSampling();
# start the Non-Sync Sampling session.
node.startNonSyncSampling()

Non-Synchronized Sampling

Non-Synchronized Sampling requires no beacon, or network. Instead, each Node is set to sample individually.

Since there is no synchronization, there is a high chance of data loss, as Nodes could send their data at the same time as other Nodes, resulting in a loss of packets. This sampling mode also does not transmit timestamps with the data. Instead, timestamps will be assigned to the data when MSCL receives it.

To start a Non-Sync Sampling network, use the startNonSyncSampling() function on the WirelessNode object.

//create a ArmedDataloggingNetwork object, giving it the BaseStation that will be the master BaseStation for the network
mscl::ArmedDataloggingNetwork network(baseStation);

//add WirelessNode(s) to the network.
//Note: The Node must already be configured for Armed Datalogging before adding to the network, or else Error_InvalidNodeConfig will be thrown.
network.addNode(node);
network.addNode(node2);

//start datalogging with all the nodes in the network.
network.startSampling();
//create a ArmedDataloggingNetwork object, giving it the BaseStation that will be the master BaseStation for the network
mscl.SyncSamplingNetwork network = new mscl.SyncSamplingNetwork(baseStation);

//add WirelessNode(s) to the network.
//Note: The Node must already be configured for Armed Datalogging before adding to the network, or else Error_InvalidNodeConfig will be thrown.
network.addNode(node);
network.addNode(node2);

//start datalogging with all the nodes in the network.
network.startSampling();
# create a ArmedDataloggingNetwork object, giving it the BaseStation that will be the master BaseStation for the network
network = mscl.ArmedDataloggingNetwork(baseStation)

# add WirelessNode(s) to the network.
# Note: The Node must already be configured for Armed Datalogging before adding to the network, or else Error_InvalidNodeConfig will be thrown.
network.addNode(node)
network.addNode(node2)

# start datalogging with all the nodes in the network.
network.startSampling()

Armed Datalogging

Armed Datalogging involves creating a network with one or more Wireless Nodes and starting all of the Nodes simultaneously.

There is no beacon keeping the nodes aligned, and all data is logged to each Node’s internal storage, to be downloaded later.

Collecting Data

//create the BaseStation, passing in the connection
mscl::BaseStation basestation(connection);

while(true)
{
    //get all the data sweeps that have been collected, with a timeout of 500 milliseconds
    mscl::DataSweeps sweeps = basestation.getData(500);

    for(mscl::DataSweep sweep : sweeps)
    {
        sweep.nodeAddress();    //the node address the sweep is from
        sweep.timestamp();      //the TimeStamp of the sweep
        sweep.tick();           //the tick of the sweep (0 - 65535 counter)
        sweep.sampleRate();     //the sample rate of the sweep
        sweep.samplingType();   //the SamplingType of the sweep (sync, nonsync, burst, etc.)
        sweep.nodeRssi();       //the signal strength at the Node
        sweep.baseRssi();       //the signal strength at the BaseStation
        sweep.frequency();      //the radio frequency this was collected on

        //get the vector of data in the sweep
        mscl::ChannelData data = sweep.data();

        //iterate over each point in the sweep (one point per channel)
        for(mscl::WirelessDataPoint dataPoint : data)
        {
            dataPoint.channelName();    //the name of the channel for this point
            dataPoint.storedAs();       //the ValueType that the data is stored as
            dataPoint.as_float();       //get the value as a float
        }
    }
}
//create the BaseStation, passing in the connection
mscl.BaseStation basestation = new mscl.BaseStation(connection);

while(true)
{
    //get all the data sweeps that have been collected, with a timeout of 500 milliseconds
    mscl.DataSweeps sweeps = basestation.getData(500);

    foreach(mscl.DataSweep sweep in sweeps)
    {
        sweep.nodeAddress();    //the node address the sweep is from
        sweep.timestamp();      //the TimeStamp of the sweep
        sweep.tick();           //the tick of the sweep (0 - 65535 counter)
        sweep.sampleRate();     //the sample rate of the sweep
        sweep.samplingType();   //the SamplingType of the sweep (sync, nonsync, burst, etc.)
        sweep.nodeRssi();       //the signal strength at the Node
        sweep.baseRssi();       //the signal strength at the BaseStation
        sweep.frequency();      //the radio frequency this was collected on

        //get the vector of data in the sweep
        mscl.ChannelData data = sweep.data();

        //iterate over each point in the sweep (one point per channel)
        foreach(mscl.WirelessDataPoint dataPoint in data)
        {
            dataPoint.channelName();    //the name of the channel for this point
            dataPoint.storedAs();       //the ValueType that the data is stored as
            dataPoint.as_float();       //get the value as a float
        }
    }
}
#create the BaseStation, passing in the connection
basestation = mscl.BaseStation(connection)

while True:

    # get all the data sweeps that have been collected, with a timeout of 500 milliseconds
    sweeps = basestation.getData(500)

    for sweep in sweeps:
        sweep.nodeAddress()    # the node address the sweep is from
        sweep.timestamp()      # the TimeStamp of the sweep
        sweep.tick()           # the tick of the sweep (0 - 65535 counter)
        sweep.sampleRate()     # the sample rate of the sweep
        sweep.samplingType()   # the SamplingType of the sweep (sync, nonsync, burst, etc.)
        sweep.nodeRssi()       # the signal strength at the Node
        sweep.baseRssi()       # the signal strength at the BaseStation
        sweep.frequency()      # the radio frequency this was collected on

        # get the vector of data in the sweep
        data = sweep.data()

        # iterate over each point in the sweep (one point per channel)
        for dataPoint in data:
            dataPoint.channelName()    # the name of the channel for this point
            dataPoint.storedAs()       # the ValueType that the data is stored as
            dataPoint.as_float()       # get the value as a float

as_float() returns the dataPoint value as a 4-byte float. However there are more options, such as as_uint16(), as_double(), as_string(), etc. The ValueType that is returned from the storedAs() function determines how the data is actually stored.

As soon as the BaseStation object is created, all incoming packets will be parsed and stored in an internal circular buffer.

So if a Wireless Node is already sampling on the same frequency as your BaseStation, you can simply access and consume the data that is being transmitted.

basestation.getData() will return a vector of DataSweep objects. This will contain all of the sweeps that have been collected after the BaseStation object was created.

Each DataSweep contains various information describing it. The DataSweep’s data() function will return a vector of WirelessDataPoint objects. This will have one point for each active channel that was enabled on the Node.

Each data point will be stored as a certain type. The datapoint’s storedAs() function will return an enum specifying which type the data is stored in (valueType_float, valueType_uint16, etc).

Using this information, you can call one of the datapoint’s as_XXXXX() functions (as_float(), as_uint16(), etc) to get the value in the way it was stored.

Inertial

Creating an InertialNode

#include "mscl/Communication/Connection.h"
#include "mscl/MicroStrain/Inertial/InertialNode.h"

//create the connection object with port and baud rate
mscl::Connection::Serial connection("COM3", 921600);

//create the InertialNode, passing in the connection
mscl::InertialNode node(connection);
//create the connection object with port and baud rate
mscl.Connection connection = mscl.Connection.Serial("COM3", 921600);

//create the InertialNode, passing in the connection
mscl.InertialNode node = new mscl.InertialNode(connection);
import mscl

#create the connection object with port and baud rate
connection = mscl.Connection.Serial("COM3", 921600)

#create the InertialNode, passing in the connection
node = mscl.InertialNode(connection)

Make sure to replace COM3 and 921600 with your own port settings.

To interace with an Inertial Node, create an InertialNode object.

An InertialNode takes a Connection as a parameter.

Serial, TcpIp, and UnixSocket are all available as connection types.

Communicating with a Node

//ping the Node
bool success = node.ping();
//ping the Node
bool success = node.ping();
# ping the Node
success = node.ping()

To test communicating with an Inertial Node, use the ping() function.





//put the Inertial Node into its idle state
node.setToIdle();
//put the Inertial Node into its idle state
node.setToIdle();
# put the Inertial Node into its idle state
node.setToIdle()

Unlike a Wireless Node, an Inertial Node can be directly communicated with even if it is sampling. However, in most cases, it is still useful to set the Node to an idle state between sampling sessions and when changing configurations. To do this, use the setToIdle() function.

Configuring a Node

//get all of the active channels for the GPS category on the Node
mscl::InertialChannels activeChs = node.getActiveChannelFields(mscl::InertialTypes::CATEGORY_GPS);
//get all of the active channels for the GPS category on the Node
mscl.InertialChannels activeChs = node.getActiveChannelFields(mscl.InertialTypes.InertialCategory.CATEGORY_GPS);
# get all of the active channels for the GPS category on the Node
activeChs = node.getActiveChannelFields(mscl.InertialTypes.CATEGORY_GPS)

Each Inertial Node has 1 or more Categories of sensors on the Node:

Category Code
Sensor CATEGORY_SENSOR
GPS CATEGORY_GPS
Estimation Filter CATEGORY_ESTFILTER

When getting and setting configuration options, it is sometimes necessary to choose the category to target for the command. This is the case in getting the active channels that are currently enabled on the Node.

//build up the channels to set
mscl::InertialChannels chs;

chs.push_back(mscl::InertialChannel(mscl::InertialTypes::CH_FIELD_SENSOR_RAW_ACCEL_VEC, mscl::SampleRate::Hertz(500)));

chs.push_back(mscl::InertialChannel(mscl::InertialTypes::CH_FIELD_SENSOR_RAW_GYRO_VEC, mscl::SampleRate::Hertz(100)));

//set the active channels for the Sensor category on the Node
node.setActiveChannelFields(mscl::InertialTypes::CATEGORY_SENSOR, chs);


//get information about the Node
mscl::InertialNodeInfo info = node.info();

if(info.supportsCategory(mscl::InertialTypes::CATEGORY_SENSOR))
{
    mscl::InertialTypes::ChannelFields fields = info.supportedChannelFields(mscl::InertialTypes::CATEGORY_SENSOR);
}
//build up the channels to set
mscl::InertialChannels chs = new mscl.InertialChannels();

chs.Add(new mscl.InertialChannel(mscl.InertialTypes.ChannelField.CH_FIELD_SENSOR_RAW_ACCEL_VEC, mscl.SampleRate.Hertz(500)));

chs.Add(new mscl.InertialChannel(mscl.InertialTypes.ChannelField.CH_FIELD_SENSOR_RAW_GYRO_VEC, mscl.SampleRate.Hertz(100)));

//set the active channels for the Sensor category on the Node
node.setActiveChannelFields(mscl.InertialTypes.InertialCategory.CATEGORY_SENSOR, chs);


//get information about the Node
mscl.InertialNodeInfo info = node.info();

if(info.supportsCategory(mscl.InertialTypes.InertialCategory.CATEGORY_SENSOR))
{
    mscl.InertialTypes.ChannelFields fields = info.supportedChannelFields(mscl.InertialTypes.InertialCategory.CATEGORY_SENSOR);
}
# build up the channels to set
chs = mscl.InertialChannels()

chs.append(mscl.InertialChannel(mscl.InertialTypes.CH_FIELD_SENSOR_RAW_ACCEL_VEC, mscl.SampleRate.Hertz(500)))

chs.append(mscl.InertialChannel(mscl.InertialTypes.CH_FIELD_SENSOR_RAW_GYRO_VEC, mscl.SampleRate.Hertz(100)))

# set the active channels for the Sensor category on the Node
node.setActiveChannelFields(mscl.InertialTypes.CATEGORY_SENSOR, chs)


# get information about the Node
info = node.info();

if info.supportsCategory(mscl.InertialTypes.CATEGORY_SENSOR):
    fields = info.supportedChannelFields(mscl.InertialTypes.CATEGORY_SENSOR)

Setting the active channels involves building an InertialChannels container, and then passing that to the setActiveChannelFields function for a specific category.

Not all categories and channel fields are supported by each Inertial Node. Use the node.info() function to get this information on the Node.

Starting Sampling

//start sampling on the Sensor category of the Node
node.enableDataStream(mscl::InertialTypes::CATEGORY_SENSOR);

//start sampling on the GPS category of the Node
node.enableDataStream(mscl::InertialTypes::CATEGORY_GPS);
//start sampling on the Sensor category of the Node
node.enableDataStream(mscl.InertialTypes.InertialCategory.CATEGORY_SENSOR);

//start sampling on the GPS category of the Node
node.enableDataStream(mscl.InertialTypes.InertialCategory.CATEGORY_GPS);
# start sampling on the Sensor category of the Node
node.enableDataStream(mscl.InertialTypes.CATEGORY_SENSOR)

# start sampling on the GPS category of the Node
node.enableDataStream(mscl.InertialTypes.CATEGORY_GPS)

You can provide an optional 2nd parameter to the enableDataStream function which is a boolean that allows enabling (true, default), or disabling (false) of the data stream.

There are a couple ways to start sampling on an Inertial Node. The first is the enableDataStream command. This allows you to start sampling on individual categories of the Node.











//use the resume command to return to the mode before setToIdle
node.resume();
//use the resume command to return to the mode before setToIdle
node.resume();
# use the resume command to return to the mode before setToIdle
node.resume()

Alternatively, you can use the resume() command. This command places the Node back into the mode it was in before issuing the setToIdle() command. So if the Node was previously sampling on all of its categories, then setToIdle() was called, calling resume() will start the Node sampling again.

Collecting Data

//create the InertialNode, passing in the connection
mscl::InertialNode node = mscl.InertialNode(connection);

while(true)
{
        //get all the packets that have been collected, with a timeout of 500 milliseconds
        mscl::InertialDataPackets packets = node.getDataPackets(500);

        for(mscl::InertialDataPacket packet : packets)
        {
                packet.descriptorSet(); //the descriptor set of the packet
                packet.timestamp();     //the PC time when this packet was received

                //get all of the points in the packet
                mscl::InertialDataPoints points = packet.data();

                for(mscl::InertialDataPoint dataPoint : points)
                {
                        dataPoint.channelName();  //the name of the channel for this point
                        dataPoint.storedAs();     //the ValueType that the data is stored as
                        dataPoint.as_float();     //get the value as a float
                }
        }
}
//create the InertialNode, passing in the connection
mscl.InertialNode node = new mscl.InertialNode(connection);

while(true)
{
        //get all the packets that have been collected, with a timeout of 500 milliseconds
        mscl.InertialDataPackets packets = node.getDataPackets(500);

        foreach(mscl.InertialDataPacket packet in packets)
        {
                packet.descriptorSet();  //the descriptor set of the packet
                packet.timestamp();      //the PC time when this packet was received

                //get all of the points in the packet
                mscl.InertialDataPoints points = packet.data();

                foreach(mscl.InertialDataPoint dataPoint in points)
                {
                        dataPoint.channelName();  //the name of the channel for this point
                        dataPoint.storedAs();     //the ValueType that the data is stored as
                        dataPoint.as_float();     //get the value as a float
                }
        }
}
# create the InertialNode, passing in the connection
node = mscl.InertialNode(connection)

while True:

        # get all the packets that have been collected, with a timeout of 500 milliseconds
        packets = node.getDataPackets(500)

        for packet in packets:
                packet.descriptorSet()  # the descriptor set of the packet
                packet.timestamp()      # the PC time when this packet was received

                # get all of the points in the packet
                points = packet.data()

                for dataPoint in points:
                        dataPoint.channelName()   # the name of the channel for this point
                        dataPoint.storedAs()      # the ValueType that the data is stored as
                        dataPoint.as_float()      # get the value as a float
        }

as_float() returns the dataPoint value as a 4-byte float. However there are more options, such as as_uint16(), as_double(), as_string(), etc. The ValueType that is returned from the storedAs() function determines how the data is actually stored.

As soon as the InertialNode object is created, all data packets will be parsed and stored in an internal circular buffer.

node.getDataPackets() will return a vector of InertialDataPacket objects. This will contain all of the packets that have been collected after the InertialNode object was created.

Each InertialDataPacket contains various information describing it. The InertialDataPacket’s data() function will return a vector of InertialDataPoint objects. These data points represent data from the active channels that were sampling on the Node.

Each data point will be stored as a certain type. The datapoint’s storedAs() function will return an enum specifying which type the data is stored in (valueType_float, valueType_uint16, etc).

Using this information, you can call one of the data point’s as_XXXXX() functions (as_float(), as_uint16(), etc) to get the value in the was it was stored.

Exceptions

MSCL uses the following Exceptions. Check the full documentation for details of which exceptions are thrown by each function.

Exception Description
Error An error has occurred.
Error_NotSupported A command or feature was used that is not supported.
Error_NoData There is no data available.
Error_BadDataType A value was accessed as a type that it cannot be converted to.
Error_UnknownSampleRate The sample rate is unknown or invalid.
Error_Timeout A read/write timeout has occurred.
Error_InvalidResponse An invalid response was received for a command.
Error_InvalidChecksum An invalid checksum was received.
Error_Communication Failed to communicate with a device.
Error_NodeCommunication Failed to communicate with a Wireless Node.
Error_Connection An error has occurred with the connection.
Error_InvalidSerialPort An error has occurred with the COM port.
Error_InvalidTcpServer An error has occured with the TCP/IP port.
Error_InvalidUnixSocket An error has occurred with the Unix Socket.
Error_InertialCmdFailed The Inertial Command has failed.
Error_InvalidConfig The configuration is invalid.
Error_InvalidNodeConfig The configuration for a WirelessNode is invalid.