Haptic Mode

In this tutorial we will demonstrate use of the haptics mode of ORCA motors through the SDK.

In this tutorial we will set up the motor to apply a spring effect, while also applying an additional oscillating force using a sin wave.

Prerequisites


We’ll start with the following code, which is a modified example from the command stream tutorial displaying force instead of position. We recommend using command streaming when controlling the motor via haptic mode.

#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 Force: " << motor.stream_cache.force << "             \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 Force: " + str(motor.get_stream_data().force), end="        \r")

Set Up a Spring Effect

First let’s update the call to set_mode(), so that we enter haptic mode instead.

...
motor.set_mode(MotorMode::HapticMode);
...
from pyorcasdk import MotorMode
...
motor.set_mode(MotorMode.HapticMode)
...

When streaming in haptic mode, ORCA motors require that the client regularly stream the current haptic effects that should be active. For now, let’s update that to only include a spring effect.

...
motor.set_mode(MotorMode::HapticMode);

motor.update_haptic_stream_effects(ORCAReg::HAPTIC_STATUS_Values::SPRING_0_Mask);
...
import pyorcasdk.orca_registers as orca_reg
...
motor.set_mode(MotorMode.HapticMode)

motor.update_haptic_stream_effects(orca_reg.HAPTIC_STATUS_SPRING_0_Mask)
...

Try running the code, the motor should begin to apply a spring effect, with the parameters of the spring being whatever your saved effect is for the motor.

Timeout Error

Try closing your program and reopening it. You may notice that this time your motor doesn’t move. If you open IrisControls, you may notice a 2048 error. Haptic Mode is one of a few modes in ORCA motors which require regular communication when used from the SDK. If a period without communication occurs, the motor enters a safety ‘braking’ mode. To fix this, we must simply clear errors when beginning the program.

...
motor.set_mode(MotorMode::SleepMode);

motor.set_mode(MotorMode::HapticMode);
...
...
motor.set_mode(MotorMode.SleepMode)

motor.set_mode(MotorMode.HapticMode)
...

Configure the Spring Effect

Let’s update the parameters of that spring effect to something that we desire.

...
motor.set_mode(MotorMode::HapticMode);

motor.update_haptic_stream_effects(ORCAReg::HAPTIC_STATUS_Values::SPRING_0_Mask);

motor.set_spring_effect(
        0,    //Spring ID (0, 1, or 2)
        200,  //Spring strength
        40000 //Center position
);
...
...
motor.set_mode(MotorMode.HapticMode)

motor.update_haptic_stream_effects(orca_reg.HAPTIC_STATUS_SPRING_0_Mask)

motor.set_spring_effect(
        0,    #Spring ID (0, 1, or 2)
        200,  #Spring strength
        40000 #Center position
)
...

Our program now enables a spring effect and controls its parameters.

Add an Oscillation

Now let’s update the code to add an oscillation effect. Haptic mode includes a variety of effects that can be layered on top of each other simultaneously. Among these are oscillation effects which can apply a set of force signals which repeat themselves over time. First, let’s update our streamed haptic effects to include one.

...
motor.update_haptic_stream_effects(
        ORCAReg::HAPTIC_STATUS_Values::SPRING_0_Mask + ORCAReg::HAPTIC_STATUS_Values::OSCILLATOR_0_Mask
);
...
...
motor.update_haptic_stream_effects(
        orca_reg.HAPTIC_STATUS_SPRING_0_Mask + orca_reg.HAPTIC_STATUS_OSCILLATOR_0_Mask
)
...

Now we should have both a spring and an oscillator active. Next, similar to the spring, lets update the oscillator effect to have parameters we’d like.

...
motor.set_osc_effect(
        0,  //Oscillator ID (0 or 1)
        20, //Oscillator max force (newtons)
        10, //Frequency (decihertz),
        0,  //Duty cycle (unimportant for sin wave)
        ORCAReg::On_TYPE_Values::SINE
);
...
...
motor.set_osc_effect(
        0,  #Oscillator ID (0 or 1)
        20, #Oscillator max force (newtons)
        10, #Frequency (decihertz),
        0,  #Duty cycle (unimportant for sin wave)
        orca_reg.On_TYPE_SINE
)
...

We now have a program that commands 2 haptic effects at once, with both configured as we’d like.


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();

	motor.set_mode(MotorMode::SleepMode);

	motor.set_mode(MotorMode::HapticMode);

	motor.update_haptic_stream_effects(
		ORCAReg::HAPTIC_STATUS_Values::SPRING_0_Mask + ORCAReg::HAPTIC_STATUS_Values::OSCILLATOR_0_Mask
	);

	motor.set_spring_effect(
		0,    //Spring ID (0, 1, or 2)
		200,  //Spring strength
		40000 //Center position
	);

	motor.set_osc_effect(
		0,  //Oscillator ID (0 or 1)
		20, //Oscillator max force (newtons)
		10, //Frequency (decihertz),
		0,  //Duty cycle (unimportant for sin wave)
		ORCAReg::On_TYPE_Values::SINE
	);

	while (true) {
		motor.run();

		std::cout << "Current Force: " << motor.stream_cache.force << "             \r";
	}

	return 0;
}
from pyorcasdk import Actuator, MotorMode
import pyorcasdk.orca_registers as orca_reg

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()

motor.set_mode(MotorMode.SleepMode)

motor.set_mode(MotorMode.HapticMode)

motor.update_haptic_stream_effects(
    orca_reg.HAPTIC_STATUS_SPRING_0_Mask + orca_reg.HAPTIC_STATUS_OSCILLATOR_0_Mask
)

motor.set_spring_effect(
    0,    #Spring ID (0, 1, or 2)
    200,  #Spring strength
    40000 #Center position 
)

motor.set_osc_effect(
    0,  #Oscillator ID (0 or 1)
    20, #Oscillator max force (newtons)
    10, #Frequency (decihertz),
    0,  #Duty cycle (unimportant for sin wave)
    orca_reg.On_TYPE_SINE
)

while True:
    motor.run()

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