Lab 3 — Communicate something with Haply

Code Structure

Once I thought of a potential word, I used whatever existing sketch I had (from the examples or my previous lab/project work) as a base that I felt would most easily allow me to implement the word representation. Once I was happy with all three representations, I merged them into a single sketch and used a mode-based structure where pressing “1”, “2”, or “3” on the keyboard would switch between each representation. The participant was only able to see the screen below during testing, regardless of mode. For the sake of clarity and context, however, the visuals are shown in this blog post.

Word 1: Rugged

Being fairly new to haptics, I wasn’t sure how to start; conveying an intended meaning with *only* grounded force-feedback is obviously a challenge. My initial approach was to experiment with creating several combinations of fisica library objects and force-feedback effects, think about what I had felt, and reiterate from there until I felt satisfied with a possible representation. That seemed like a lot of work, so naturally I used my work from the previous labs and project as a starting point. The “point grid” I created in lab 2 for the maze using a 2-D FBox array had a very “bumpy” texture to it when the points were large enough to hinder but not block the movement of the Haply. This gave me the idea to incorporate a vibrational effect to the sketch to create the sensation of a rugged/rough terrain texture. A vibration sensation was added by inducing small, random forces with the fEE.x or fEE.y commands. This was simple enough to create and what I believed would be an easy first word for participants to guess. I had also thought of a “pinball” type effect, where the end-effector would “bounce” off points, but that seemed complex to design and refine, especially given the time constraints. Maybe for another day.

Word 2: Pressure

The second word occurred to me while I was hopping through the packaged Haply example sketches to look for ideas. The maze example contained a shallow pool of water and that gave me the idea to implement the sensation of hydrostatic pressure in a deep body of water; imagine the end-effector as a submarine diving down the Mariana Trench. The further down you go, the greater is the pressure acting on you. Additionally, temperatures are lower at the bottom. This results in a slightly higher density of water making it somewhat more difficult to move through. Based on my experience, I felt that this could easily be represented via damping as a function of the Haply’s vertical position. Here, the body of water is represented by an FBox covering a significant portion of the sketch window.

Notice the change in y-pos values as the end-effector is moved down. The value at the bottom of the trench (i.e., maximum value) is approximately 20.
//Y and C represent the gradient and intercept of the equationmode2_damping = round(k * posEE.y + c);
int mode2_index;
int[] mode2_thresholds = { 6, 7, 9, 11, 14, 16, 19 };
int[] mode2_durations = { 60, 50, 40, 30, 20, 16, 12};
float mode2_tLastChange = Float.NEGATIVE_INFINITY;
for (int i = mode2_thresholds.length - 1; i >=0; i--)
if (posEE.y > mode2_thresholds[i] && mode2_index != mode2_thresholds[i])
mode2_index = mode2_thresholds[i];
if (millis() - mode2_tLastChange > mode2_durations[mode2_index])
fEE.x = random(-5, 5);
fEE.y = random(-1, 1);
mode2_tLastChange = millis();

Word 3: Tick Tock 🕒

Lastly, I wanted to incorporate the Haply’s motion guidance mechanism for my last communicative movement. I used my PID lab’s modified code to generate a staircase-path that endlessly went up and down, as I felt that it would be an easy pattern to both design and guess. Unfortunately, I wasn’t satisfied with the resulting motion; I was able to generate a nice-looking staircase path visually, but the end-effector wouldn’t track it as smoothly, regardless of the PID tuning or speed with which the movement occurred. Ultimately, I ditched the code and decided to work on “point-based” navigation, in which the Haply moves sequentially through a series of points, spending a second at each point. This was done by setting up a position vector array with the desired points, and then generating and applying the force vector to the Haply (F(t) = kX(t)).

PVector[] mode3_locations = {
new PVector(-0.055, 0.0323),
new PVector(-0.022, 0.0724),
new PVector(0.0184, 0.0810),
int mode3_index;
float mode3_tDuration = 1000;
float mode3_tLastChange = Float.NEGATIVE_INFINITY;
// every X ms interval ...
if (millis() - mode3_tLastChange > mode3_tDuration)
//cycle back to 0 after going through last point
if (mode3_index == mode3_locations.length - 1)
mode3_index = -1;

mode3_tLastChange = millis();
PVector xDiff = (posEE.copy()).sub(mode3_locations[mode3_index]);
float mode3_tDuration = 1000; // ms
float mode3_tVib = 40; // ms, how long to vibrate the Haply before moving to next point
else if (millis() — mode3_tLastChange > mode3_tDuration — mode3_tVib)
fEE.x = random(-10, 10);

Results & Reflection

I was only able to test my sketch with one participant, who came up with these words for each respective representation:

  1. Bumpy/Rough
  2. Static, buzzing
  3. Guided



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store