Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This tutorial will show you how to use two Nao’s for puppeteering. This allows you to control the movement of one robot by moving the other robot.

Follow the Getting started with a the Nao robot. You should now have the following set up at the end:

  1. Redis is running on your laptop and you have SIC installed locally

  2. SIC is running on the Nao’s

Approach

This tutorial will show you how to do puppeteering with two Nao’s. Since we will be using several joints of the robots which require some setup, this tutorial is split into two parts:

  1. Connecting separately with both Nao’s and setting up their default behavior

  2. Connecting the Nao’s to each other using the NaoqiMotionStreamerService

Connecting to two Nao’s

First, let’s create a Python file demo_puppeteering.yp that contains our SIC program.

Then, add some imports and the definition of the joint we will use (JOINTS) and those we will set fixed (FIXED_JOINTS)

Code Block
languagepy
import time
from sic_framework.devices import Nao
from sic_framework.devices.common_naoqi.naoqi_autonomous import NaoBasicAwarenessRequest, NaoBackgroundMovingRequest, NaoRestRequest
from sic_framework.devices.common_naoqi.naoqi_motion_streamer import StartStreaming, StopStreaming, NaoMotionStreamerConf
from sic_framework.devices.common_naoqi.naoqi_stiffness import Stiffness
from sic_framework.devices.common_naoqi.naoqi_text_to_speech import NaoqiTextToSpeechRequest

JOINTS = ["Head", "RArm", "LArm"]
FIXED_JOINTS = ["RLeg", "LLeg"]

To connect with the first Nao (assuming it is has IP address 192.168.0.191), we create a Nao object and use the NaoMotionStreamerConf as configuration for the MotionStreamer component. Note that this only sets the number of samples per seconds to capture the motion.

Code Block
languagepy
conf = NaoMotionStreamerConf(samples_per_second=30)
puppet_master = Nao("192.168.0.191", motion_stream_conf=conf)

We then want to disable the BasicAwareness and BackgroundMoving of the Nao’s. Moreover, we want to set the stiffness of all the joints that we will be moving to 0.0 such that we are able to move them.

Code Block
languagepy
puppet_master.autonomous.request(NaoBasicAwarenessRequest(False))
puppet_master.autonomous.request(NaoBackgroundMovingRequest(False))
puppet_master.stiffness.request(Stiffness(0.0, joints=JOINTS))

Now, we repeat the same steps for the second Nao, but we don’t need to set a NaoMotionStreamerConf anymore since this Nao will be the puppet and will just listen to the pupper_master. Moreover, we will set the stiffness of the puppet to 0.5 such that it can easily execute the movements.

Code Block
languagepy
puppet = Nao("192.168.0.239")
puppet.autonomous.request(NaoBasicAwarenessRequest(False))
puppet.autonomous.request(NaoBackgroundMovingRequest(False))
puppet.stiffness.request(Stiffness(0.5, joints=JOINTS))

Finally, we want to set the stiffness of the joints we will not be using to 0.7 such that the Nao’s

...

sda
dsd

...

don't fall over. Furthermore, we will let both Nao’s start in their Rest position.

Code Block
languagepy
# Set fixed joints to high stiffness such that the robots don't fall
puppet_master.stiffness.request(Stiffness(0.7, joints=FIXED_JOINTS))
puppet.stiffness.request(Stiffness(0.7, joints=FIXED_JOINTS))

# Start both robots in rest pose
puppet.autonomous.request(NaoRestRequest())
puppet_master.autonomous.request(NaoRestRequest())

Puppeteering

Now that we have both Nao’s setup and in Rest position we can connect the puppet Nao to listen to the output of the puppet_master’s Motion Streaming component. This is a simple one-liner:

Code Block
languagepy
puppet.motion_streaming.connect(puppet_master.motion_streaming)

We can then send a request to the puppet_master to start the puppeteering and let the Nao say that the puppeteering has started. We will thus send two requests to the respective components (.streaming and .tts).

Code Block
languagepy
puppet_master.motion_streaming.request(StartStreaming(JOINTS))
puppet_master.tts.request(NaoqiTextToSpeechRequest("Start puppeteering", language="English", animated=True))

You can now start moving the puppet_master Nao and the puppet Nao should mirror its movements directly. To not let the puppeteering go on for ever, we will sleep for 30 seconds and then send a StopStreaming request to the puppet_master. Also, we will reset it’s joints' stiffness to 0.7 (such that we cannot manually move them anymore) and let the Nao say that we are done.

Code Block
languagepy
puppet_master.tts.request(NaoqiTextToSpeechRequest("We are done puppeteering", language="English", animated=True))
puppet_master.stiffness.request(Stiffness(0.7, joints=JOINTS))
puppet_master.motion_streaming.request(StopStreaming())

Finally, we let both Nao’s go to the Rest position again.

Code Block
languagepy
puppet.autonomous.request(NaoRestRequest())
puppet_master.autonomous.request(NaoRestRequest())

That was it! If you run the demo_puppeteering.py file you should be able to, for example, move the puppet_master Nao’s arms and see the puppet Nao mirror this movement.

The full code can be found at https://bitbucket.org/socialroboticshub/framework/src/master/sic_framework/tests/demo_puppeteering.py.