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
and921600
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 asas_uint16()
,as_double()
,as_string()
, etc. TheValueType
that is returned from thestoredAs()
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
and921600
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 asas_uint16()
,as_double()
,as_string()
, etc. TheValueType
that is returned from thestoredAs()
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. |