# Understanding GoTo¶

Goal

In this tutorial, we will make Pepper move, using the GoTo action.

Prerequisites

Before stepping in this tutorial, you should be familiar with the action notion.

For further details, see: Running Actions on Pepper.

Let’s start a new project

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

For further details, see: Creating a robot application.

## Moving Pepper around¶

Let’s see how to make Pepper move at a predefined location.

To do this, we need to create the position to go to.

## Building the target frame¶

A Frame is a data which describes a spacial position.

Here we need to get the target frame: this is the location we want Pepper to go to.

To retrieve the target frame, we will first need to get the robot frame.

The robot frame is provided by a service called Actuation. We can retrieve it if we use the getActuation method on the QiContext.

Put the following code in the onRobotFocusGained method:

// Get the Actuation service from the QiContext.
val actuation: Actuation = qiContext.actuation


// Get the Actuation service from the QiContext.
Actuation actuation = qiContext.getActuation();



Now we can get the robot frame:

// Get the robot frame.
val robotFrame: Frame = actuation.robotFrame()


// Get the robot frame.
Frame robotFrame = actuation.robotFrame();



Next, we create a 1 meter forward translation corresponding to the transform between the robot frame current location and the target frame:

// Create a transform corresponding to a 1 meter forward translation.
val transform: Transform = TransformBuilder.create().fromXTranslation(1.0)


// Create a transform corresponding to a 1 meter forward translation.
Transform transform = TransformBuilder.create().fromXTranslation(1);



We will now create the target frame. The Mapping service provides a method to create a FreeFrame:

// Get the Mapping service from the QiContext.
val mapping: Mapping = qiContext.mapping

// Create a FreeFrame with the Mapping service.
val targetFrame: FreeFrame = mapping.makeFreeFrame()


// Get the Mapping service from the QiContext.
Mapping mapping = qiContext.getMapping();

// Create a FreeFrame with the Mapping service.
FreeFrame targetFrame = mapping.makeFreeFrame();



A FreeFrame represents a location free to be placed anywhere, that does not move when other frames move.

The global position of a FreeFrame can be updated by applying a Transform to a base Frame. The timestamp is left to 0, to update targetFrame relatively to the last known location of robotFrame.

// Update the target location relatively to Pepper's current location.
targetFrame.update(robotFrame, transform, 0L)


// Update the target location relatively to Pepper's current location.
targetFrame.update(robotFrame, transform, 0L);



We now have the target frame. We will use it to build the GoTo action.

## Moving to the target frame¶

You can make Pepper move by using the GoTo interface.

Add a GoTo field in your MainActivity:

// Store the GoTo action.
private var goTo: GoTo? = null


// Store the GoTo action.
private GoTo goTo;



We will create a GoTo action with a GoToBuilder in the onRobotFocusGained method:

// Create a GoTo action.
goTo = GoToBuilder.with(qiContext) // Create the builder with the QiContext.
.withFrame(targetFrame.frame()) // Set the target frame.
.build() // Build the GoTo action.


// Create a GoTo action.
goTo = GoToBuilder.with(qiContext) // Create the builder with the QiContext.
.withFrame(targetFrame.frame()) // Set the target frame.
.build(); // Build the GoTo action.



The GoTo interface has a addOnStartedListener method that allows you to be notified when the GoTo action starts. We will use it to log to the console:

// Add an on started listener on the GoTo action.
goTo?.addOnStartedListener { Log.i(TAG, "GoTo action started.") }


// Add an on started listener on the GoTo action.
goTo.addOnStartedListener(() -> Log.i(TAG, "GoTo action started."));



Do not forget to remove this listener on GoTo in the onRobotFocusLost method:

// Remove on started listeners from the GoTo action.
goTo?.removeAllOnStartedListeners()


// Remove on started listeners from the GoTo action.
if (goTo != null) {
goTo.removeAllOnStartedListeners();
}



We will now run the GoTo in the onRobotFocusGained method:

 // Execute the GoTo action asynchronously.
val goToFuture: Future<Void>? = goTo?.async()?.run()


// Execute the GoTo action asynchronously.
Future<Void> goToFuture = goTo.async().run();



And display a log trace indicating that the action finished with success or error:

// Add a lambda to the action execution.
goToFuture?.thenConsume { future ->
if (future.isSuccess) {
Log.i(TAG, "GoTo action finished with success.")
} else if (future.hasError()) {
Log.e(TAG, "GoTo action finished with error.", future.error)
}
}


// Add a lambda to the action execution.
goToFuture.thenConsume(future -> {
if (future.isSuccess()) {
Log.i(TAG, "GoTo action finished with success.");
} else if (future.hasError()) {
Log.e(TAG, "GoTo action finished with error.", future.getError());
}
});



You can adjust the maximum navigation speed (in m/s) by using GoToBuilder.withMaxSpeed.

Update the GoTo creation by the following code:

goTo = GoToBuilder.with(qiContext)
.withFrame(targetFrame.frame())
.withMaxSpeed(0.55f) // Set the max speed.
.build()


goTo = GoToBuilder.with(qiContext)
.withFrame(targetFrame.frame())
.withMaxSpeed(0.55f) // Set the max speed.
.build();



For more details, see Tuning GoTo behavior.

## Let’s try it¶

The sources for this tutorial are available on GitHub.

Step Action

Install and run the application.

For further details, see: Running an application.

Choose “Step forward”.

You should observe the following:

• the log trace “GoTo action started.” is displayed in the console,

• Pepper moves 1 meter forward,

• the log trace “GoTo action finished with success.” is displayed in the console.

You are now able to make Pepper move!