6 Conclusion

6 Conclusion

Phew… you made it… Well done:-)

Over the last few weeks, you’ve had a whirlwind tour of how we can use the Python programming language to program a simple simulated robot. You’ve launched a virtual computing environment using Docker or Compute Home, and used Jupyter notebooks as a medium for executing code you’ve been provided with, as well as writing your own code, and hopefully taking a few notes along the way.

Write down a brief summary here recapping what you learned over the course of the robotics block practical activities. Then read through my summary and come back to add any more things that come to mind that we perhaps both missed…

So what did you come up with?

For starters, you’ve seen how a sequential programming approach can be used to sequence robot behaviours and automate particular tasks, both within a simulated robot environment and in the notebook’s own Python environment. You’ve also seen how we can use ‘code’ to ‘program’ the creation of different sorts of diagrams, including block diagrams and sequence diagrams.

Within a sequential program, you’ve seen how different forms of control flow statement can be used to modify the way in which control passes from one statement to another. On the one hand, branching conditional statements, such as if and if...else... constructions allow us to make ‘one-shot’ decisions at a particular step. On the other hand, for loops allow us to iterate over multiple enumerated items and while loops allow us to repeatedly step through the same series of actions whilst some condition holds true. If we ever need to modify the control flow behaviour as we pass through a loop, the continue statement lets us jump back to the top of the loop before we would normally do so, and the break statement lets us escape from it early.

As well as repeating code sequences within a loop, you also learned how we can ‘package’ code within functions, passing values into the code block via function arguments. One special class of functions comprises the magics we can create within an IPython environment to automate particular tasks that perhaps sit outside the actual programs we want to write. You also saw how we could draw on third-party Python packages in our own programs, from the pandas package for working with tabular datasets, to the seaborn or plotly packages for plotting rich scientific charts and data visualisations. As well as creating rich visualisations, you also saw how we could create interactive end-user applications using the ipywidgets interact tools that could automatically generate interactive controls from the data type of arguments passed to appropriately decorated functions.

On the particular topic of robot programming, you saw how our simulated robot could be programmed to perform particular tasks ‘blindly’ such as driving forwards for a particular amount of time, but that far more robust or resilient behaviours could be achieved by making use of sensors. In the simulated environment, you particularly focused on simple reflective light sensors, that allowed us to detect visual features in the robot’s environment, such as the edge of line. (You also saw how we could use the pixelated image array that implemented a simple light sensor as a simple, low-resolution camera.) As well as the light sensor, a simulated ultrasonic sensor allowed the robot to detect obstacles at a distance, and the simulated gyroscope (often referred to as a gyro) allowed the robot to keep track of which direction it was heading in. The robot could also maintain a sense of its location using odometry provided by simulated rotation or position sensors on the motors.

When it came to actually programming the robot, you hopefully learned that sometimes quite simple programmed behaviours could result in complex emergent behaviours, from the light-seeking and avoiding behaviour of Braitenberg vehicles to the hopefully lightning-speed line-following circumnavigation of the simulated racetrack you achieved in the RoboLab Grand Prix Challenge!

As well as sequential programs, you also saw how we could use rule-based systems to create rich programs that react to particular events, from the simple conversational agent originally implemented many decades ago in the form of Eliza, to more elaborate rule-based systems created using the durable-rules framework.

You then learned how we could use simple neural networks to perform a range of classification tasks. MLPs, which is to say, multi-layer perceptrons, can be quite quick to train, but may struggle when it comes to all but the simplest or most well-behaved classification tasks. If you worked through the optional materials, you will also have seen how CNNs, or convolutional neural networks, offer far more robust behaviour, particularly when it comes to image-based recognition tasks. However, they are far more expensive to train in many senses of the word – in terms of training data required, computational effort and time. Trying to make sense of how neural networks actually perform their classification tasks is a significant challenge, but you saw how certain visualisation techniques could be used to help us peer inside the ‘mind’ of a neural network.

Finally, you saw how we could start to consider the robot+Python notebook computational environment as a multi-agent system, in which we programmed the robot and Python agents separately, and then created a simple message-passing protocol to allow them to communicate. Just as complex emergent behaviours can arise from multiple interacting rules in a rule-based system, or the combined behaviour of the weighted connections between neural network neurons, so too might we create complex behaviours from the combined behaviour of agents in a simple multi-agent system.

You have been exposed to a lot of code in this block, and you are not expected to be able to create such code for yourself. At times, you may have wondered why so much code was presented: the reason was to show you on the one hand that there was no magic (other than IPython magic!), and on the other hand to make you realise just how much faffing around is sometimes required, particularly when it comes to working with data. At other times, you may have struggled to make sense of the code, and how it actually worked. That’s completely fine. A major aim of the block was not to turn you into demon programmers, but to help you see how computational problem solving works: by breaking tasks down into ever smaller subtasks until, eventually, we can see how to solve the subtask with a line or two of code. And also that, even by programming very simple behaviours, quite complex, emergent behaviours can result.

So give yourself a pat on the back, and grab a quick cup of your favourite hot drink, or a long glass of your favourite cold drink; and as you savour it for a while, reflect on just how much you’ve covered over the last eight weeks.

Jot down a few notes here to reflect on what you enjoyed, what you learned, what you found particularly challenging studying this block and what surprised you. Are there any things you could have done differently that would have made it easier or more rewarding?

So with the practical material for the block now completed, it’ll be time to finish off that TMA…