Hold/release autonomous abilities

In this tutorial, we will see how to toggle Pepper’s autonomous abilities.

Note

For further details on autonomous abilities, see: Autonomous Abilities.

Prerequisites

Before stepping in this tutorial, you should be familiar with the notion of Future. You can refer to Chaining operations if you need.

Let’s start a new project

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

For further details, see: Creating a robot application.

Hold abilities

In the MainActivity class, create a new holdAbilities method:

private fun holdAbilities(qiContext: QiContext) {
    // Build and store the holder for the abilities.
    var holder: Holder = HolderBuilder.with(qiContext)
            .withAutonomousAbilities(
                    AutonomousAbilitiesType.BACKGROUND_MOVEMENT,
                    AutonomousAbilitiesType.BASIC_AWARENESS,
                    AutonomousAbilitiesType.AUTONOMOUS_BLINKING
            )
            .build()

    // Hold the abilities asynchronously.
    val holdFuture: Future<Void> = holder.async().hold()
}
private void holdAbilities(QiContext qiContext) {
    // Build the holder for the abilities.
    Holder holder = HolderBuilder.with(qiContext)
            .withAutonomousAbilities(
                    AutonomousAbilitiesType.BACKGROUND_MOVEMENT,
                    AutonomousAbilitiesType.BASIC_AWARENESS,
                    AutonomousAbilitiesType.AUTONOMOUS_BLINKING
            )
            .build();

    // Hold the abilities asynchronously.
    Future<Void> holdFuture = holder.async().hold();
}

To hold the abilities, we first build a Holder with a HolderBuilder. We pass the autonomous abilities we want to hold to the builder, by using the AutonomousAbilitiesType enum.

Next, we can call the async and hold methods on the holder to hold the abilities asynchronously.

Now that we know how to disable autonomous abilities, we will see how to re-enable them.

Release abilities

In this section, we will see how to release autonomous abilities.

Create a new releaseAbilities method:

private fun releaseAbilities(holder: Holder) {
    // Release the holder asynchronously.
    val releaseFuture: Future<Void> = holder.async().release()
}
private void releaseAbilities(Holder holder) {
    // Release the holder asynchronously.
    Future<Void> releaseFuture = holder.async().release();
}

To release autonomous abilities asynchronously, call the async and release methods on the corresponding Holder instance.

Next, we will implement an example to test the hold and release functionalities.

Testing hold/release

Let’s test our code using a button_switch_autonomous.

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/button_switch_autonomous"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="Hold"/>

Create these fields in the MainActivity:

// A boolean used to store the abilities status.
private var abilitiesHeld: Boolean = false
// The holder for the abilities.
private var holder: Holder? = null
// The QiContext provided by the QiSDK.
private var qiContext: QiContext? = null
// The button_switch_autonomous used to toggle the abilities.
private Button buttonSwitchAutonomous;
// A boolean used to store the abilities status.
private boolean abilitiesHeld = false;
// The holder for the abilities.
private Holder holder;
// The QiContext provided by the QiSDK.
private QiContext qiContext;

Put the following code for the onRobotFocusGained and onRobotFocusLost methods:

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

override fun onRobotFocusLost() {
    // Remove the QiContext.
    this.qiContext = null
}
@Override
public void onRobotFocusGained(QiContext qiContext) {
    // Store the provided QiContext.
    this.qiContext = qiContext;
}

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

Set the button_switch_autonomous onClick listener in the onCreate method.

// Set the button_switch_autonomous onClick listener.
button_switch_autonomous.setOnClickListener {
    // Check that the Activity owns the focus.
    if (qiContext != null) {
        toggleAbilities()
    }
}
// Find the button_switch_autonomous in the view.
buttonSwitchAutonomous = (Button) findViewById(R.id.button_switch_autonomous);

// Set the buttonSwitchAutonomous onClick listener.
buttonSwitchAutonomous.setOnClickListener(v -> {
    // Check that the Activity owns the focus.
    if (qiContext != null) {
        toggleAbilities();
    }
});

Add a toggleAbilities method:

fun void toggleAbilities() {
    // Disable the button_switch_autonomous.
    button_switch_autonomous.isEnable = false

    if (abilitiesHeld) {
        releaseAbilities(holder)
    } else {
        holdAbilities(qiContext)
    }
}
private void toggleAbilities() {
    // Disable the buttonSwitchAutonomous.
    buttonSwitchAutonomous.setEnabled(false);

    if (abilitiesHeld) {
        releaseAbilities(holder);
    } else {
        holdAbilities(qiContext);
    }
}

Now, update the holdAbilities method with the following code:

// Build and store the holder for the abilities.
holder = HolderBuilder.with(qiContext)
                      .withAutonomousAbilities(
                              AutonomousAbilitiesType.BACKGROUND_MOVEMENT,
                              AutonomousAbilitiesType.BASIC_AWARENESS,
                              AutonomousAbilitiesType.AUTONOMOUS_BLINKING
                      )
                      .build()

// Hold the abilities asynchronously.
val holdFuture: Future<Void> = holder.async().hold()

// Chain the hold with a lambda on the UI thread.
holdFuture.andThenConsume(Qi.onUiThread(Consumer {
    // Store the abilities status.
    abilitiesHeld = true
    // Change the button_switch_autonomous text.
    button_switch_autonomous.text = "Release"
    // Enable the button_switch_autonomous.
    button_switch_autonomous.isEnabled = true
}))
// Build and store the holder for the abilities.
holder = HolderBuilder.with(qiContext)
                      .withAutonomousAbilities(
                              AutonomousAbilitiesType.BACKGROUND_MOVEMENT,
                              AutonomousAbilitiesType.BASIC_AWARENESS,
                              AutonomousAbilitiesType.AUTONOMOUS_BLINKING
                      )
                      .build();

// Hold the abilities asynchronously.
Future<Void> holdFuture = holder.async().hold();

// Chain the hold with a lambda on the UI thread.
holdFuture.andThenConsume(Qi.onUiThread((Consumer<Void>) ignore -> {
    // Store the abilities status.
    abilitiesHeld = true;
    // Change the buttonSwitchAutonomous text.
    buttonSwitchAutonomous.setText("Release");
    // Enable the buttonSwitchAutonomous.
    buttonSwitchAutonomous.setEnabled(true);
}));

Finally, chain releaseFuture in the releaseAbilities method with a lambda on the UI thread:

// Chain the release with a lambda on the UI thread.
releaseFuture.andThenConsume(Qi.onUiThread(Consumer {
    // Store the abilities status.
    abilitiesHeld = false
    // Change the button_switch_autonomous text.
    button_switch_autonomous.text = "Hold"
    // Enable the button_switch_autonomous.
    button_switch_autonomous.isEnabled = true
}))
// Chain the release with a lambda on the UI thread.
releaseFuture.andThenConsume(Qi.onUiThread((Consumer<Void>) ignore -> {
    // Store the abilities status.
    abilitiesHeld = false;
    // Change the buttonSwitchAutonomous text.
    buttonSwitchAutonomous.setText("Hold");
    // Enable the buttonSwitchAutonomous.
    buttonSwitchAutonomous.setEnabled(true);
}));

Note

We have to execute the lambdas on the UI thread because we update the button_switch_autonomous properties in them.

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 “Hold/release autonomous abilities”.

Notice that the robot moves slightly, blinks, and tracks your movements.

Click on the button_switch_autonomous and the robot will stop these behaviours after a short time.

Click again on the button_switch_autonomous and the robot will reactivate his abilities.

../../../_images/abilities.png

We can now toggle abilities!

That’s it, you know how to hold and release autonomous abilities.