This guide will walk you through setting up the navel SDK and running your first scripts.
On the navel robot, run the following commands:
# Create a venv and activate it python3 -m venv .venv/ source .venv/bin/activate # Install the SDK and its dependencies: pip install navel
Before running any scripts, start bodyd and allow it to finish initializing.
To start getting familiar with programming using the SDK, try running the following script:
1import navel 2 3def main(): 4 with navel.Robot() as robot: 5 robot.rotate_arms(180,180) 6 robot.say("Hallo, welt!") 7 robot.rotate_arms(0,0) 8 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)
withblock 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”. But what if you’d like it to move its arms while speaking? It would seem that’s not possible – indeed, with our current set-up, 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 navel 2 3async def main(robot: navel.Robot): 4 robot.say("Hallo, welt!") 5 await robot.rotate_arms(180,180) 6 await robot.rotate_arms(0,0) 7 8if __name__ == "__main__": 9 navel.run(main)
- You may notice a couple of differences:
There’s now an
asynckeyword in front of our main function definition: this is necessary to allow us to take advantage of concurrent programming in the function body.
The function now takes an argument of type
navel.Robotinstead of creating it inside: this allows the navel library to do all the setup for concurrency for us.
There’s now an
awaitkeyword 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
navel.run(main): this takes care of all the boilerplate now that our function has become a coroutine.
This time, Navel should lift its arms while speaking.
A similar interface is available for most 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 putting an
await before the
robot.say command in line 4 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 navel 2 3async def main(robot: navel.Robot): 4found_person = False 5while not found_person: 6 found_person = await search(robot) 7 await robot.rotate_base(180) 8 9robot.say("Hallo!") 10 11async def search(robot: navel.Robot): 12 walk = robot.move_base(2, 0.1) 13 while not walk.done(): 14 data = await navel.next_frame() 15 if data.persons: 16 walk.cancel() 17 return True 18 return False 19 20if __name__ == "__main__": 21 navel.run(main)
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.
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).
And that’s the basics out of the way. For a full breakdown of everything the SDK has to offer, check out the examples and the API Documentation.