Multiple Robots

Interact with multiple robots at the same time.

By the end of this tutorial you will be able to:

  1. Extend your applications for use by a small fleet of robots
  2. Connect a single client application to multiple robots
  3. Simultaneously control the movements of several robots

A robot is essentially a set of 3D shapes (arms, legs, digits etc.) that can be moved with respect to each other by computer control.

The shapes are referred to as links, and adjacent links are connected by joints. Movement of the links is caused by actuators (typically motors) at the joints, and the range of movement is determined by the type of actuator and its placement on the joint. Not all robots conform to this ‘rigid body’ description, in the same way that not all animals are vertebrates, but it is a useful generalisation that applies to the majority of robots available today.

It is conventional to refer to different robot ‘form factors’ – humanoids, quadrupeds, drones etc. – when we want to convey the challenges of controlling a robot that are influenced by its structure; whether it has two legs rather than four, or wings rather than arms etc. However, in the same way that humans, dogs, and birds are all variations on the common ‘vertebrate’ theme, most robots available today are variations on the common ‘rigid body’ theme. As such, they can be described in terms of a common data structure known as the kinematic tree, which has branches that correspond roughly to the bones that make up a skeleton. The shapes of these trees differ between robots, but all robots have one.

Appreciating this is key to understanding how the BOW SDK allows applications developed for one robot to be ported to any other.

With the right software tools and mathematical models, the process of constructing a control system for a new robot can be largely automated. As long as the mathematics we use to estimate robot movements from their joint settings are formulated in terms of the abstract kinematic tree structure, rather than the particulars of a given robot, any control algorithms built using those mathematics will be agnostic to form factor and hardware arrangement. To this end, the only human intervention that’s really needed is a quick exercise in assigning generic labels (‘effector 1’, ‘effector 2’ etc.) to the links most commonly used as the targets for control, for example those corresponding to a robot’s hands/digits and feet.

In this tutorial we’ll develop a deeper sense of the hardware-agnostic design of the BOW SDK, by connecting to and controlling robots with different form factors simultaneously.

Take a look at the following to see what we're aiming for:

About the Application

The purpose of the application you will develop here is to enable users to simultaneously control the movements of several robots. The structure of the application is as follows:

Before we get stuck in:

If you are just browsing to get a sense of what's possible, take a look at the code online.

Running the Application

Navigate to the GettingStarted/MultipleRobots/Python folder in the SDK Tutorials repository:

cd SDK-Tutorials/GettingStarted/MultipleRobots/Python

Execute the example program:

python main.py

Investigation

Once running, the program will print a list of available robots in the Terminal window. Follow the prompts to select your two simulated robots. Once they have been selected, use the keyboard to control both robots simultaneously:

KeyAction
WMove Forward
ATurn Left
SMove Backward
DTurn Right
EStrafe Right
QStrafe Left

Let's take a closer look at the key parts of the code:

Instead of using quickconnect, which will automatically establish a connection to the first available robot, we need to set up the client manually in order to obtain the full list of available robots:

setup_result = bow_api.setup(app_name="Multiple Robots", verbose=True)
if not setup_result.Success:
    sys.exit(-1)

Next we validate the user login credentials:

login_result = bow_api.login_user("", "", True)
if login_result.Success:
    print("Logged in")
else:
    sys.exit(-1)

Now we can obtain the full list of robots on the local and remove servers:

get_robots_result = bow_api.get_robots(get_remote=True, get_system=False)
if not get_robots_result.localSearchError.Success:
   print(get_robots_result.localSearchError.Description)
if not get_robots_result.remoteSearchError.Success:
    print(get_robots_result.remoteSearchError.Description)
if len(get_robots_result.robots) == 0:
    print("No Robots found")
    bow_api.close_client_interface()
    sys.exit(-1)

Then we filter out only the available robots:

available_robots = [r for r in get_robots_result.robots if r.robot_state.available]

Now we can create the robot objects:

robots = [bow_api.Robot(available_robots[ridx]) for ridx in robot_indices]

The last set up step is to establish the connection and communication channels for each robot:

target_channels = ["vision", "motor"]
for robot in robots:
    result = robot.connect()
    if not result.Success:
        print("Could not connect with robot {}".format(robot.robot_details.robot_id))
        bow_api.close_client_interface()
        sys.exit(-1)
 
    for channel in target_channels:
        result = robot.open_channel(channel)
        if not result.Success:
            print("Failed to open " + channel + " channel: " + result.Description)
            bow_api.close_client_interface()
            sys.exit(-1)

The remainder of the code begins the familiar sampling loop, which now includes an inner loop for iterating over each of the connected robots.

To explore multi-robot concepts further, try connecting to different combinations of robots at the same time to explore their similarities and differences.

On this page