Skip to content

Worked Examples

Here you'll find example implementations for tasks presented on previous pages, along with explanations of the core concepts.

The corresponding .mirocode programs are available to download directly from Blackboard — look under 'Learning resources for MiRo labs'.

Getting Started with MiRoCloud

1. Clapper control (hitting the cans)

Here, claps are used to control the duration of each of the MiRo's actions in sequence, which should result in MiRo driving into a stack of cans. The key idea is to time the claps just at the right moments. This is an example of a program which has a simple and linear flow, with each block being executed after the next one.

Clapper control code

It's useful to note the interplay between the blocks here, as this is something you'll be using a lot in the future. There are both Discrete and Continuous Action blocks in this program (remember the difference? If not, you can look it up here).

The Start Moving block is a discrete action block. You can think of it as toggling a switch that changes MiRo's state from not moving to moving. However, this block doesn't specify the duration of the action, so another type of block is required for this to actually work. Another way of thinking about it is in terms of blocking and non-blocking calls (yes, blocking blocks... the terminology can be confusing).

Question 1

Create a simple program that only has two blocks: Program Start, followed by Start Moving Forwards.
What do you see when you run it and why?

On the other hand, the Wait for clap and Wait for X seconds are both continuous action blocks. Incidentally, both of them are also blocking, which means they prevent execution of the code further down until they complete their own execution.

Combining the effects these two block types provide, it should then be clear how each action in this program is generated. In the snippet below, MiRo starts moving forward and will continue moving forward up until it hears a clap (plus additional 0.3 seconds).

Forwards until clap

Note

Start Moving is also a good example of a block that permits changing the values inside it.
By clicking on the drop-down menu it is possible to change the direction of movement, as well as the speed.

Now, let's run the program.
Time your claps correctly to make MiRo topple the can stack!

Example 1 complete

2. Watch the Edge (sonar)

Here, MiRo starts by lowering its head and using the sonar in the nose to measure the distance to the surface of the table. MiRo should then start going forward until it detects the edge of the table, upon which it should stop.

The key idea is that MiRo's sonar readings remain relatively constant as it moves across the table, when away from the edges. However, when MiRo approaches an edge, the sonar readings will significantly increase, triggering a conditional response.

In this example you can see how to use variables, loops and functions to help make the program shorter and clearer.

Disable the Cliff Reflex

You will need to disable the built-in cliff reflex to ensure that's it's actually your code that's stopping the MiRo (see below).

Watch the edge sonar

The first thing to note is the assignment of a value to a variable called dist, which indicates distance to the surface of the table. The Sonar Range is a conditional block, meaning it plugs into other blocks that receive a value (look for connectors on the side).

Check data types

When connecting different blocks together, keep in mind the values that one block is producing and the other block is expecting. Incompatible data types are a common source of error.

A tooltip for this block is displayed on the image below, specifying what sort of output this block produces.

Question 2

Can you remember how to show the tooltip for a given block?

Distance_to_table

If you're writing the code from scratch, you have to create the corresponding variable first using the Variables group on the left panel.
Click on variables, and then on create_variable

The next piece of code worth mentioning is the Repeat While loop.
This type of loop keeps spinning until the criteria no longer returns True, which in this case means that the dist is more than or equal to half a meter.
loop
The block inside the loop represents a call to a function called sonar_edge, defined as follows
function
The gear icon at the top allows to add inputs to the function, something that will be covered later on. The next symbol — a question mark — allows to add a description to the function. This text is then displayed as a function tooltip, but otherwise has no bearing on its functionality. The last bit at the top is the name of the function, which has to be unique. This type of function doesn't return an output on its own, but there's another type of block for a function which does return output.

Inside the function, you might notice a customised Python print command being used instead of the regular Print String block. The purpose of this is to simply make the output prettier by printing only two decimal digits in the sonar range value. The second line is where the dist gets updated with the most current reading obtained from the sonar. Finally, the last line in this function simply blocks execution for 0.1 second, inhibiting the rate of sensor updates and the rate at which messages are printed to the terminal.

Finally, let's run the program and see if MiRo stops at the edge:

Example 2 complete

It does indeed!

3. Emergency lights

Here, MiRo simulates an emergency vehicle by spinning in place and cycling through a sequence of blue and red LED lights, repeated five times.

Emergency_lights

First, let's look in more detail at the first loop in this program, as it contains something that has not yet been covered — lists.
lists

A variable called touch is created before the loop, and is assigned the output from All Body Touch sensors block. This block returns the state of the body touch sensors, as a list of 14 Boolean values (True/False). Each sensor reports True when a touch is being detected and False otherwise.
Inside the Repeat While loop, this list is scanned to check if any value is True, returning the index of the first True value (which could be an integer from 1 to 14), or 0 in case none were found.

A note on indices

Indexing in MiRoCode starts from 1, while in Python indexing starts from 0.

By default, none of the sensors are touched, and so the condition is evaluated to True. This keeps the loop spinning until one of the sensors detect a touch.

Similarly to the previous program, the touch variable is also updated inside the loop every 0.1 second.

Question 3

The touch variable has two identical assignments both before and inside the loop, which at a glance might seem redundant.
Would you be able to explain why is it important to have both of them?

Hopefully, everything else in this program should be clear by now.
Below a snapshot of the running program showing the LED panel:

Example 3 complete

4. Friendly MiRo

Here, a pat on the head triggers a friendly response from MiRo, expressed through 'cosmetic' joint movements and LEDs. After a 5-second duration, MiRo reverts to its default state.

Emergency_lights

The two functions — default and happy — define all the 'cosmetic' joint positions and LED colours for the two corresponsing states of MiRo.

Similar to the second example, the functions are introduced to make the code cleaner and more readable.

Question 4

In how many ways can MiRo express itself?
Count including all the degrees of freedom, as well as other modalities (sound, lights, etc.)

Now let's conclude examples from the first tutorial with the Friendly MiRo:

Example 4 complete