Making NAO walk - Adorno-Lab/Nao-robot GitHub Wiki
Here is the Aldebaran documentation on locomotion control of the robot.
⚠️ IMPORTANT NOTES
- Although the documentation says the robot is able to walk on carpets, give preference to smoothier floor surfaces. On carpets, sometimes the robot seems stucked and unable to move despite taking the footsteps to do it.
- Call
moveInit()before starting walk commands. This method executes an initialization movement to put the robot in a right posture, for example, with both its feet flat on the ground, so it can then walk.- Do not use
killMove()to stop the robot walking unless it is an emergency. It will kill the task brutally and the robot could fall. Instead, usestopMove(), which will end the task only after the robot has its two feet on the ground. ThestopMove()method is slower thankillMove(), but safer. A more graceful option, despite slower (~0.8s), is setting the robot target velocity to zero, using themoveToward()method.
This tutorial will cover only the high level methods to control the robot's locomotion, i.e., moveTo(), move(), and moveToward(). To control the robot's footsteps, use the methods setFootSteps() and setFootStepsWithSpeed().
| Method | Properties and parameters |
|---|---|
moveTo() |
blocking call distances along x and y axes and angle around z |
move() |
non-blocking call velocities along x and y axes and around z |
moveToward() |
non-blocking call normalized velocities along x and y axes and around z |
The three methods can be used to configure the robot's gait, for example changing the height of its steps. You can find more about it here.
The moveTo() method was briefly covered in the First steps tutorial, and it sends the robot to a given pose in the ground plane relative to FRAME_ROBOT.
The parameters are the translation along x-axis and y-axis (in meters) and the rotation around z-axis (in radians). The translations and rotations are with respect to the FRAME_ROBOT at the moment the command is given. The method is a blocking call.
motion_proxy = ALProxy("ALMotion", ROBOT_IP, PORT)
motion_proxy.moveTo(x, y, theta)The move() method sets the linear and angular velocities along the x and y axes and around the z axis of FRAME_ROBOT. The velocities are in meters per second and radians per second. To move in negative directions, use negative values. The method is a non-blocking call, so a new command overwrites the previous one.
motion_proxy = ALProxy("ALMotion", ROBOT_IP, PORT)
motion_proxy.moveTo(x_vel, y_vel, theta_vel)Using velocity commands requires a stopping condition. This could be a voice command or the detection of something, for example. When you only care about the final pose, the moveTo() command would be a more appropriate choice, but if the velocities are also important, you can use the robot displacements to set the stopping conditions for the move() method.
The getRobotPosition() method returns the robot pose (position and orientation) relative to FRAME_WORLD. This frame is defined at the moment the robot is turned on. The robot's movements are not sufficiently precise for this frame to be used to track the robot pose during a long sequence of movements, because of the accumulated errors. For example, if you alternate wakeUp() and rest() commands multiple times, you will notice that the robot turns a bit after each repetition, ending up with a big error in the angle given by the getRobotPosition() method.
However, you can still use the getRobotPosition() to calculate the displacement and use it to set the stopping condition. Using this approach could be something like this
initial_pose = motion_proxy.getRobotPosition(False)
while True:
current_pose = motion_proxy.getRobotPosition(False)
delta_x = current_pose[0] - initial_pose[0]
delta_y = current_pose[1] - initial_pose[1]
delta_theta = current_pose[1] - initial_pose[1]
if abs(delta_x) < target_displacement_x:
x_vel = 0
if abs(delta_y) < distance_y:
y_vel = 0
if abs(delta_x) < angle_theta:
theta_vel = 0
motion_proxy.move(x_vel, y_vel, theta_vel)
if x_vel == 0 and y_vel == 0 and theta_vel == 0:
motion_proxy.waitUntilMoveIsFinished()
breakIn the above example, a WHILE loop checks the displacement in x and y and the rotation around z relative to the initial robot pose, and updates the velocity commands. When the target displacement and angles are achieved, the velocities are set to zero to make the robot stop. After sending the move(0,0,0) command, you can use the waitUntilMoveIsFinished() method to block the code until the robot stops, then break the loop and continue with the script.
You can also reduce the velocity as the robot approaches the target pose. Check the example code for a working example of this approach. You can use whatever stopping condition you want, but remember to include one in your script, to avoid having to send an emergency stop command or causing accidents that could damage the robot.