An important part of developing a smart robot application is creating the behavior of the robot. Typically, this behavior is created as a computer program that states what the robot should do at a certain moment. In industrial applications the behaviors may seem easy to program, but dealing with product variations and unexpected situations makes developing a correct program a hard nut to crack. At Smart Robotics an elegant framework for dealing with these issues has been developed: the ‚Application Decision Engine‘.
Robot program: Happy Flow
Let us take a palletizer robot – one of our robot applications – as an example. A palletizer robot picks up boxes from a predetermined position and stacks them on a pallet in a predetermined layout. The necessary behavior of the robot can be specified as follows: move to the pick location, grab the box, move to the place location, and place the box onto the pallet. Once the last action, e.g. place, is executed, the robot continues in an endless cycle, at least until the pallet is full.
This list of actions can be seen as a program the robot has to execute. Specifically, it is an imperative program: a list of commands the robot has to follow one by one. The commands or statements are executed in a loop until some criterion is met. Such imperative programs are quite similar to cooking recipes: ‘cut the vegetables, add them to the pot, stir until …’ etc. The robot will blindly follow any list of instructions it is given. As long as everything is as expected, the robot will successfully fulfill its task. We call this ‚happy flow‘.
Exceptions and implicit robot memory
Now imagine what would happen if the robot moves to the pick location to pick up a box, but the box is not yet there. It would continue to blindly follow commands: try to pick the box – which fails because the box is not there – move to the pallet, and place … nothing! To avoid this situation, a condition check could be added. For example: ‘if the box is at the pick location, pick it up, otherwise wait for the box to appear’. Now imagine a situation where the robot holds a box and moves to the pallet, but then accidentally drops the box. Another condition check could be added: ‘if the robot drops the box while moving to the place position, stop and give an error message’.
However, you can imagine that when more and more of these situations are discovered and added to the behavior, the program of the robot becomes cluttered with exceptions. Instead of a nice ‚move, pick, move, place‘-recipe, there is a whole bunch of ‘wait for’, ‘in this specific case do that’. This means the program grows in complexity, is harder to maintain and it becomes easier for mistakes to creep in.
Increasing complexity is not the only pitfall. Imagine the robot is stopped halfway when placing a box: the program shuts down while the robot is still holding the product. Once the robot is started again, it will begin at the top of the list of commands: move to the pick location, grab a box. However, it is already holding a box! The problem here is that the robot has an implicit memory. It remembers which command it is currently executing. That memory is erased when the application is restarted. It is like baking a cake, halfway forgetting that you were baking one, and starting all over while the other cake is still in the oven.
Reactive robot program: better decisions with a ‘decision tree’
Hence, a better way of programming robot behavior is needed. An important cause of the problems described above is the fact that the robot blindly follows commands, and as an exception checks conditions to make sure it is doing the right thing (e.g. ‘Am I still holding the box?’). But as said before, the exceptions often become the rule and clutter the program.
What if it is turned around? Instead of following a list of commands and sometimes check a condition, let the robot always check conditions and sometimes follow a list of commands. That probably sounds confusing, so consider the following example. In an imperative program, the robot’s first step would be to move to the pick position. However, now the question ‘is the robot holding a box?’ is asked. If ‘yes’, the robot can directly move to the pallet. If ‘no’, the robot moves to the pick position to grab one.
Imagine the robot continuously asks that questions and executes the corresponding command. If the robot begins without a box, it would move to the pick position and grab a box. If the question ‘is the robot holding a box?’ is then asked again, the answer would be ‘yes’. The robot would move to the pallet and place the box. If the question is then asked again, the answer would be ‘no’, and the robot would move to the pick location again, and so on. A working application with no more implicit memory has been created.
Now, there is no need for the robot to keep track of the command it is currently executing and what comes next. This means the program can be stopped and resumed at any time, and the robot would execute the correct command. In addition, if a box would be taken away from the robot when it is holding one, the robot would directly go back to grab a new one. The program is now way more reactive than the old imperative program.
Furthermore, adding exceptional cases becomes a lot easier. If it is desired that the robot waits until a box is available, simply add as extra condition; ‚is a box available?‘. Now, the program will start to look like this:
- Are we holding a box?
- yes: go to pallet and place.
- no: is a box available?
- yes: go to pick location and pick box.
- no: do nothing.
The program looks like a tree: starting at the root, a question is asked. Based on the answer, another question is asked or an action is executed, and so on. This type of program is called a ‚decision tree‘: the robot decides upon an action based on a series of questions. Adding more intelligence is as easy as adding another branch to the tree.
Application Decision Engine
The concept ‚decision tree‘ is certainly not new – it is in fact an extensively used classical machine learning tool. At Smart Robotics, we started using it for robot behaviors and found that it worked really well compared to imperative programming. Hence, Smart Robotics started to build a complete framework around it to make programming robot behaviors even easier. For example, it was discovered that many sub-behaviors could be re-used across applications, such as ‚if an error occurs, blink the red light and show an error message on the user interface‘. The framework therefore allows wrapping these sub-behaviors into small software modules that can be re-used. Furthermore, it contains a whole set of tools to assist the robot behavior programmer – from decision tree visualizations to condition consistency checkers. Because the framework allows writing and running applications using decision trees it was named it the ‚Application Decision Engine’ (ADE).
Even though the ADE is already widely used within Smart Robotics, it is still being actively developed and some great improvements are on the roadmap. A thing Smart Robotics is currently looking in to is accurately predicting future situations the robot might encounter. Based on these predictions, the robot can already compute what to do next even before it finishes the current task. For example, it could calculate how to go back to the pick location even before it finishes placing the box. This could greatly improve the robot’s reactivity and speed. Another development is a better integration between the ADE and the user interface, such that it becomes easier for a robot operator to identify a certain situation happened and what can be done to solve or improve the situation.
In the past years, the Application Decision Engine has proven great value to Smart Robotics and the continuous development of the ADE will be of great importance. It will help Smart Robotics to do what we enjoy most: making our smart robot solutions even smarter!