.. _haptic-mode: 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 ------------- - :ref:`motor-modes` - :ref:`motor-error-handling` - :ref:`command-stream` - (Optional) We recommend reading the ORCA Series Reference Manual's section "Controllers -> Haptic Controller". The reference manual can be found `on our downloads page `_. ---- 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. .. tab-set:: :sync-group: language .. tab-item:: C++ :sync: cpp .. literalinclude:: shared/boilerplate-streaming-force.cpp :language: cpp .. tab-item:: Python :sync: python .. literalinclude:: shared/boilerplate-streaming-force.py :language: python Set Up a Spring Effect ---------------------- First let's update the call to ``set_mode()``, so that we enter haptic mode instead. .. tab-set:: :sync-group: language .. tab-item:: C++ :sync: cpp .. code-block:: cpp ... motor.set_mode(MotorMode::HapticMode); ... .. tab-item:: Python :sync: python .. code-block:: python 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. .. tab-set:: :sync-group: language .. tab-item:: C++ :sync: cpp .. code-block:: cpp ... motor.set_mode(MotorMode::HapticMode); motor.update_haptic_stream_effects(ORCAReg::HAPTIC_STATUS_Values::SPRING_0_Mask); ... .. tab-item:: Python :sync: python .. code-block:: python 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. .. tab-set:: :sync-group: language .. tab-item:: C++ :sync: cpp .. code-block:: cpp ... motor.set_mode(MotorMode::SleepMode); motor.set_mode(MotorMode::HapticMode); ... .. tab-item:: Python :sync: python .. code-block:: python ... 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. .. tab-set:: :sync-group: language .. tab-item:: C++ :sync: cpp .. code-block:: cpp ... 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 ); ... .. tab-item:: Python :sync: python .. code-block:: python ... 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. .. tab-set:: :sync-group: language .. tab-item:: C++ :sync: cpp .. code-block:: cpp ... motor.update_haptic_stream_effects( ORCAReg::HAPTIC_STATUS_Values::SPRING_0_Mask + ORCAReg::HAPTIC_STATUS_Values::OSCILLATOR_0_Mask ); ... .. tab-item:: Python :sync: python .. code-block:: python ... 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. .. tab-set:: :sync-group: language .. tab-item:: C++ :sync: cpp .. code-block:: cpp ... 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 ); ... .. tab-item:: Python :sync: python .. code-block:: python ... 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 ---------------- .. tab-set:: :sync-group: language .. tab-item:: C++ :sync: cpp .. literalinclude:: Haptic-Mode/main.cpp :language: cpp .. tab-item:: Python :sync: python .. literalinclude:: Haptic-Mode/main.py :language: python