Getting Started

This guide will walk you through setting up the navel SDK and running your first scripts. The SDK provides functions for Python scripts, running on the robot, to interact with the robot’s system software.

Network setup

Generally, you will access the robot via its wifi connection. For your convenience, make sure your network configuration has

  • wifi client separation disabled, so you can access the browser interface from your PC;

  • the DHCP server set to always give the same IP to the robot.

Setup of the wifi connection is done via the Navel Control Studio browser interface in the System section.

Built-in examples

As a quick and convenient way to get started, the robot comes packaged with a few scripts that can be run directly from the navel control studio. They should show up as a list in the “scritps” section of the Overview page, and the associated files are located in ~/control-studio/scripts.

Working on the robot

There are multiple ways to edit and run Python files on the robot. Here, we will cover the most basic access via command line and give hints on how to setup alternatives. In order to connect to the robot, you usually need

  • its hostname or IP address. The hostname (in the form navel-5010001) is printed on the bottom label of the device. The IP address is allocated by the DHCP server in your network. You can look it up in Navel Control Studio;

  • login credentials, that is the username navel and the password that is printed on your manual;

  • an SSH client to establish the connection, e.g. PowerShell on Windows, OpenSSH on Linux or macOS, or another ssh client like Putty.

The following example shows how to establish a command line connection to the robot and uses that to edit and run a Python script. An introduction to command line use can be found here.


While the following snippet shows how to log in using a password, we strongly suggest you set up an authorized key on the robot to make logging in more secure and easier. You can learn more about ssh keys and how to set them up from this guide:

user@pc ~ $ ssh navel@navel-5010001
navel@navel-5010001's password:
     --- omitted lines ---
navel@navel-5010005 ~ $ cd control-studio/scripts
navel@navel-5010005 control-studio/scripts $ ls  README
navel@navel-5010005 control-studio/scripts $ nano
    This opens a command line editor. You can change the text that is being
    said and close it by pressing Ctrl+x, then y to save changes.
navel@navel-5010005 control-studio/scripts $ python3
    This makes the robot say the respective text, equivalent to pressing
    the play button in Navel Control Studio.
navel@navel-5010005 control-studio/scripts $ exit

You can also use this strategy to create new scripts, although you will need to press the refresh button in the scripts section for any new files to show up. And don’t worry about messing up the files in ~/control-studio/scripts, the original examples will always be available in a different directory: /usr/share/navel/examples/. This way, you can simply copy over the original files if anything goes wrong.


Connecting using a hostname may fail intermittently depending on your network configuration. Connecting via IP address is more reliable. Use it instead of the hostname, like ssh navel@ The current IP addresses of the robot are displayed in Navel Control Studio.


There may also be scripts in other folders than the main one mentioned here. Those won’t show up in the control studio UI, and should only be run through the command line. They also require some additional setup before running, which is explained later.

We recommend using VS Code’s remote editing functionality for more comfortable file editing and to get all the benefits of an IDE.

Another option is to run JupyterLab on the robot and use it to edit files via browser, although you will need to set up a virtual environment first.

Creating your own scripts

To start getting familiar with programming using the SDK, try creating a script with the following code:

 1import navel
 3def main():
 4    with navel.Robot() as robot:
 5        robot.rotate_arms(180,180)
 6        robot.say("Hello, world!")
 7        robot.rotate_arms(0,0)
 9if __name__ == "__main__":
10    main()

A few things are happening here:

  • We’re creating an instance of the Robot class (line 4), which handles sending commands to the robot

  • We’re sending commands to move the arms and say a sentence (lines 5-7)

  • Exiting the with block automatically takes care of cleaning up connections for us

When the script is run, Navel should lift its arms, celebrating that everything was set up correctly, and then say “Hello world”. If you’ve looked into the code for the example scripts, you may notice this is kind of a mix between and But what if you’d like it to move its arms while speaking? It would seem that’s not possible – indeed, with our current code, it isn’t.

In order to support multiple actions at once, the navel python library relies heavily on python’s asyncio lib. We can therefore change the above program to take advantage of this:

 1import asyncio
 3import navel
 5async def main():
 6    async with navel.Robot() as robot:
 7        robot.say("Hello, world!")
 8        await robot.rotate_arms(180, 180)
 9        await robot.rotate_arms(0, 0)
11if __name__ == "__main__":

You may notice a couple of differences:

  • There’s now an async keyword in front of our main function and our with statement: this is necessary to allow us to take advantage of concurrent programming in the function body.

  • There’s now an await keyword in front of the arm movements, so that we wait for the movement to be done before continuing.

  • We changed how the function is run, from a simple main() to this is again necessary for us to use concurrency.


If you’re running this example in a Jupyter notebook instead of a standalone python script, you will need to change line 12 from to await main(). This is because Jupyter runs its own async context in the background, which would conflict with the one we’re trying to create. Keep this in mind whenever you see in this documentation.

This time, Navel should lift its arms while speaking. A similar interface is available for most robot functions, so that you can either run them directly and do something else while they run, or await them and wait for them to be finished. Go ahead, try changing line 7 to await robot.say instead and see what happens. There’s also much more you can do, such as assigning the result of a function to a variable and awaiting it later, cancelling it, or simply checking if it’s done. Under the hood, all async functions in the Robot class return an asyncio Task, so anything you can do with them is supported.

Let’s see an example using slightly more complex logic:

 1import asyncio
 3import navel
 5async def main():
 6    async with navel.Robot() as robot:
 7        found_person = False
 8        while not found_person:
 9            found_person = await search(robot)
10            await robot.rotate_base(180)
12        robot.say("Hello!")
14async def search(robot: navel.Robot):
15    walk = robot.move_base(1, 0.1)
16    while not walk.done():
17        data = await robot.next_frame()
18        if data.persons:
19            walk.cancel()
20            return True
21    return False
23if __name__ == "__main__":


This script will try to move the robot so before running it, make sure there’s enough empty space around and change the parameters to move_base if necessary.

With this program, navel should move back and forth until it sees a person. When a person is seen, we cancel the motion and say hello. You may notice our search function takes an argument of type navel.Robot instead of creating it inside, which is passed on from main. This is a useful pattern for more complex applications, since we’ll likely need the reference to the robot in a lot of places. Notice also how walk.done() is used to wait for an action to be done while doing something else (in this case looking for people).

Running the other examples

Before running the more complex examples, a little bit of setup is needed. We’ll use the chat directory to explain the process.

Firstly, the required files may not be in ~/control-studio/scripts if you only recently updated your robot. If that is the case, you’ll need to copy them from /usr/share/navel/examples/.

In order to run the example, you will need to install dependencies that are not included in the default system-wide python installation, and may also need to set some environment variables. We recommend using virtual environments (further reading) to manage extra dependencies.

Setting up your virtual environment

When connected to the robot via ssh, run the following commands to set up a virtual environment:

# Create a virtual environment and activate it
python3 -m venv venv/
source venv/bin/activate

# Navigate to the example directory
cd control-studio/scripts/chat

# Install the script dependencies
pip install -r requirements.txt


This process will create a virtual environment in your home folder. This makes it convenient to run new scripts, but opens you up to potential versioning issues if your scripts depend on many different libraries. Instead, you may prefer to have a separate virtual environment for each script/project. If you’d like to do this, simply create the virtual env in the chat directory (or any other directory you prefer) instead.

If you’d like to use JupyterLab for editing, this is when you should install it.

Running the script

Since the virtual environment should already be activated from the previous step, you should be able to simply use python3 to run the script. However, you will quickly notice that there is some additional setup needed before the script works correctly. Namely, there are some environment variables that need to be set. The specifics of this are described at the top of the file, which will be the case for any examples that require additional setup before being run.

As a final note, you may not want to activate the virtual environment manually every time you need to run a different script. In that case, you could also:

  1. run your Python file like this: venv/bin/python

  2. add a shebang to the top of your file to run that file within a certain venv: #!/home/navel/venv/bin/python and make it executable with chmod g+x This will also work for scripts in the control-studio/scripts directory, allowing you to run them via Control Studio if you prefer.

  3. modify your .bashrc to always change into a virtual environment on login:

    if (tty -s); then
        source ~/venv/bin/activate

    (only if you’ve chosen to use one virtual environment for all scripts)

And that’s the basics out of the way. For a full breakdown of everything the SDK has to offer, check out the API Documentation.