Ease tablet interaction — EnforceTabletReachability

Goal

In this tutorial, we will use EnforceTabletReachability in order to make Pepper reduce his movements, and therefore ease user interaction on the tablet.

Prerequisites

Before stepping in this tutorial, you should:

Let’s start a new project

  • Start a new project, let’s call it TabletReachabilityPepper.
  • Robotify it and make sure it implements the QiSDK & the Robot Life Cycle.

For further details, see: Creating a robot application.

Creating an EnforceTabletReachability action

In this section, we will see how to create an EnforceTabletReachability action.

Start by storing the following fields in your MainActivity:

// Store qiContext
private var qiContext: QiContext? = null

// Store the EnforceTabletReachability action.
private var enforceTabletReachability: EnforceTabletReachability? = null

// Store qiContext
private QiContext qiContext;

// Store the EnforceTabletReachability action.
private EnforceTabletReachability enforceTabletReachability;

Then, put the following code in the onRobotFocusGained method:

fun override onRobotFocusGained(qiContext: QiContext) {
    // Store qiContext
    this.qiContext = qiContext

    // Build EnforceTabletReachability action.
    enforceTabletReachability = EnforceTabletReachabilityBuilder.with(qiContext).build()

    ...
}

@Override
public void onRobotFocusGained(final QiContext qiContext) {
    // Store qiContext
    this.qiContext = qiContext;

    // Build EnforceTabletReachability action.
    enforceTabletReachability = EnforceTabletReachabilityBuilder.with(qiContext).build();

    ...
}

In order to observe the effect of EnforceTabletReachability, we will make Pepper talk when his tablet reaches the wanted position. To do so, add the following field in your MainActivity:

// Store the say action related to the moment when the position is reached.
private var positionReachedSay: Say? = null

// Store the say action related to the moment when the position is reached.
private Say positionReachedSay = null;

And add tho following code in the same onRobotFocusGained method:

// Build a say action to give feedback when the position is reached.
val positionReachedTex: String = "My movements are now limited. Cancel the action to see the difference."

positionReachedSay = SayBuilder.with(qiContext)
            .withText(positionReachedText)
            .build()

// On position reached listener
enforceTabletReachability?.addOnPositionReachedListener {
    Log.i(TAG, "The tablet now is in position.")
    positionReachedSay?.run()
}

String positionReachedText = "My movements are now limited. Cancel the action to see the difference.";

positionReachedSay = SayBuilder.with(qiContext)
        .withText(positionReachedText)
        .build();

// On position reached listener
enforceTabletReachability.addOnPositionReachedListener(() -> {
    Log.i(TAG, "The tablet now is in position.");
    positionReachedSay.run();
});

Think about cleaning the qiContext field and set listeners in the onRobotFocusLost method:

fun override onRobotFocusLost() {
    // Remove the QiContext.
    this.qiContext = null

    // Remove all the listeners
    enforceTabletReachability?.removeAllOnPositionReachedListeners()
}

@Override
public void onRobotFocusLost() {
    // Remove the QiContext.
    this.qiContext = null;

    // Remove all the listeners
    enforceTabletReachability.removeAllOnPositionReachedListeners();
}

Running the action

In this section, we will see how to run the EnforceTabletReachability action.

Start by storing this following fields in your MainActivity:

// Store the enforceTabletReachability action's future
private enforceTabletReachabilityFuture: Future<Void>? = null

// Store the say action related to the moment when the action is ended.
private var actionEndedSay: Say? = null

// Store the enforceTabletReachability action's future
private Future<Void> enforceTabletReachabilityFuture;

// Store the say action related to the moment when the action is ended.
private Say actionEndedSay = null;

Then, create a startEnforceTabletReachability() method in your MainActivity.

private fun startEnforceTabletReachability() {
    // Run the action asynchronously
    enforceTabletReachabilityFuture = enforceTabletReachability?.async()?.run()

    // Handle the action's end
    enforceTabletReachabilityFuture?.thenConsume { future ->
        // Log the eventual errors
        if (future.hasError()) {
            Log.e(TAG, "The EnforceTabletReachability action finished with error.", future.error)
        } else {
            Log.i(TAG, "The EnforceTabletReachability action has finished.")
        }

        // Give vocal feedback
        actionEndedSay?.run()
    }
}

private void startEnforceTabletReachability() {
    // Run the action asynchronously
    enforceTabletReachabilityFuture = enforceTabletReachability.async().run();

    // Handle the action's end
    enforceTabletReachabilityFuture.thenConsume(future -> {
        // Log the eventual errors
        if (future.hasError()) {
            Log.e(TAG, "The EnforceTabletReachability action finished with error.", future.getError());
        } else {
            Log.i(TAG, "The EnforceTabletReachability action has finished.");
        }

        // Give vocal feedback
        actionEndedSay.run();
    });
}

Calling this method will run the EnforceTabletReachability action asynchronously. We also added code to make Pepper talk when the action is done. This will allow us to observe the difference in Pepper’s movements when the action is running or not. However, let’s not forget to initialize this say action in the onRobotFocusGained callback:

...

// Build a say action to give feedback when the action ends.
val actionEndedText: String = "My movements are back to normal. Run the action again to see the difference."

actionEndedSay = SayBuilder.with(qiContext)
        .withText(actionEndedText)
        .build()

...

// Build a say action to give feedback when the action ends.
String actionEndedText = "My movements are back to normal. Run the action again to see the difference.";

actionEndedSay = SayBuilder.with(qiContext)
        .withText(actionEndedText)
        .build();

Stopping the action

Add this simple stopEnforceTabletReachability to your MainActivity:

private void stopEnforceTabletReachability() {
    enforceTabletReachabilityFuture?.requestCancellation()
}

private void stopEnforceTabletReachability() {
    enforceTabletReachabilityFuture.requestCancellation();
}

Calling this method will stop the EnforceTabletReachability action that is running.

Testing EnforceTabletReachability

Let’s test our code using a button:

Note

The following code is just a quick way to test the functionality, this is not what you would do in a real application.

In the activity_main.xml layout file, add the following Button:

<Button
    android:id="@+id/tablet_reachability_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Enforce tablet reachability"/>

In the onCreate method, add the following code:

// Run the EnforceTabletReachability when button clicked.
tablet_reachability_button.setOnClickListener {
    if (enforceTabletReachability == null) {
        Log.e(TAG, "EnforceTabletReachability has not been built yet")
    } else if (enforceTabletReachabilityFuture == null || enforceTabletReachabilityFuture.isDone {
        // The EnforceTabletReachability action is not running
        startEnforceTabletReachability()
    } else {
        // The EnforceTabletReachability is running
        enforceTabletReachabilityFuture?.requestCancellation()
    }
}

// Run the EnforceTabletReachability when button clicked.
Button enforceTabletReachabilityButton = (Button) findViewById(R.id.tablet_reachability_button);
enforceTabletReachabilityButton.setOnClickListener(v -> {
    if (enforceTabletReachability == null) {
        Log.e(TAG, "EnforceTabletReachability has not been built yet");
    } else if (enforceTabletReachabilityFuture == null || enforceTabletReachabilityFuture.isDone()) {
        // The EnforceTabletReachability action is not running
        startEnforceTabletReachability();
    } else {
        // The EnforceTabletReachability is running
        enforceTabletReachabilityFuture.requestCancellation();
    }
});

Clicking on the button will either start or stop the EnforceTabletReachability action, accordingly to its running state.

Let’s try it

github_icon The sources for this tutorial are available on GitHub.

Step Action

Install and run the application.

For further details, see: Running an application.

Choose “Enforce tablet reachability”.

Notice that Pepper moves his arms and torso while talking.

Click on the button and the robot will reduce his movements, easing tablet interaction.

Click again on the button and the robot will go back to his previous state.

/sites/default/files/repository/64_rst_pepper/public/source/_build/html/_images/enforcetabletreachability.png

You are now able to ease tablet interaction on Pepper!