Command Stream

In this tutorial we introduce an important concept for communicating with ORCA motors with the SDK, Command Streaming. Command streaming allows for sending commands to the motor while simultaneously reading commonly used data. It is also the only method of asynchronous communication with an ORCA available within the SDK.

For more details see the ORCA Series Modbus RTU User Guide pdf available through our Downloads page.


We’ll start with the following code as our baseline:

#include <iostream>
#include "actuator.h"

using namespace orcaSDK ;

int main() {
	Actuator motor;

	int serial_port;
	std::cout << "Please input the serial port number of your connected motor. ";
	std::cin >> serial_port;

	motor.open_serial_port(serial_port);

	while(true)
	{
		std::cout << "Current Position: " << motor.get_position_um().value << "          \r";
	}

	return 0;
}
from pyorcasdk import Actuator

motor = Actuator()

serial_port = int(input("Please input the serial port number of your connected motor. "))

motor.open_serial_port(serial_port)

while True:
	print("Current Position: " + str(motor.get_position_um().value), end="        \r")

Enabling Command Streaming

Command streaming can be enabled by a call to the enable_stream() method of your Actuator object.

...
motor.enable_stream();
...
...
motor.enable_stream()
...

When this method is called, the SDK will now attempt to send and receive asynchronous messages to the motor. Note that enabling streaming doesn’t dispatch a new thread of execution. In order for the SDK to perform any streaming work, it must be explicitly requested to do so. To send and receive command stream messages, we must add regular calls to our Actuator object’s run() method. We’ll introduce it within the while (true) loop.

...
while (true)
{
        motor.run();

        std::cout << "Current Position: " << motor.get_position_um().value << "          \r";
}
...
...
while True:
        motor.run()

        print("Current Position: " + str(motor.get_position_um().value), end="        \r")
...

Note

The run() method acts as a simple self-contained state machine. It checks to see if there’s room to insert a new command stream message, and sends one if there is room. It then monitors for a response by the ORCA, and automatically reads, validates, and stores the response data. It isn’t necessary to worry about what the content of the run() method is doing at any given time, it is good enough and preferred to simply place it in a place where it will get called regularly.

Reading Returned Data

run() does not return any data. Instead, it deposits the returned data from the motor into a local cache. Let’s replace the call to get_position_um() with an equivalent read from the cache.

Note

run() doesn’t return any data because it performs many jobs, and it isn’t easy to predict what it is doing at any given time. This is why it deposits into a cache. At any given time, this cache will always contain the data from the most recent response.

...
while (true)
{
        motor.run();

        std::cout << "Current Position: " << motor.stream_cache.position << "          \r";
}
...
...
while True:
        motor.run()

        print("Current Position: " + str(motor.get_stream_data().position), end="        \r")
...

Now instead of injecting additional read messages in order to get the motor’s position, we’re using the position data automatically returned while streaming.


Complete Example

#include <iostream>
#include "actuator.h"

using namespace orcaSDK;

int main() {
	Actuator motor;

	int serial_port;
	std::cout << "Please input the serial port number of your connected motor. ";
	std::cin >> serial_port;

	motor.open_serial_port(serial_port);

	motor.enable_stream();

	while (true) {
		motor.run();

		std::cout << "Current Position: " << motor.stream_cache.position << "             \r";
	}

	return 0;
}
from pyorcasdk import Actuator

motor = Actuator()

serial_port = int(input("Please input the serial port number of your connected motor. "))

motor.open_serial_port(serial_port)

motor.enable_stream()

while True:
    motor.run()

    print("Current Position: " + str(motor.get_stream_data().position), end="        \r")