VPL Lab 4 - Drive in a Square
Glossary Item Box
In this lab you will write code to drive a robot in a square using some of the advanced operations of the Generic Differential Drive.
This lab is provided in the language. You can find the project files for this lab at the following location under the Microsoft Robotics Developer Studio installation folder:
This lab teaches you how to:
- Step 1: Starting the Robot
- Step 2: Listening for Completion Notifications
- Step 3: Increment the Step counter
- Step 4: Implementing the Steps for the Square
- Step 5: Run the program
This lab is written for the iRobot Create, real or simulated, but any robot with a differential drive could be substituted. To use a different robot you need to change the manifest used by the Generic Differential Drive.
This lab requires Microsoft Robotics Developer Studio. It uses Microsoft Visual Programming Language (VPL).
Step 1: Starting the Robot
Open a new VPL diagram, or if you prefer you can open the supplied diagram and follow along in there.
The first task you need to do is to create a variable. A variable is a place in memory where you can store information and update it while your program is running. In this program, the variable is used to keep track of which operation to perform next as the robot drives around in a square. This is a very simple example of what is called a state machine where the current state is kept in a variable, and the robot performs different operations depending on the value of the state.
In the Edit menu, select the option Variables.... A dialog will appear. The Variables dialog in Figure 1 shows how it should look after finishing these steps:
- Click on the Add button which creates a new variable with the default name of Field;
- Enter a new name for the variable, Step;
- Select its data type as int (an integer is a whole number, i.e. no decimal places) because it is a counter that will be incremented after each step has been completed.
The variable name Step reflects the fact that the robot will go through a series of steps as it drives around the square. It is good practise to use meaningful names for all of the objects that you create in a VPL program.
Now that you have a variable, drag a Data activity to the diagram. It should have a value of zero (0) and type of int. Drag a Variable activity to the diagram and select Step from the dropdown list. Connect the Data block to the Variable block as shown in Figure 2 at the end of this section. This initializes the variable Step to zero when the program starts.
As you have seen in previous labs, your diagram should wait for you to press OK when the robot is ready. You need to drag a SimpleDialog to the diagram and add a Data block to pass it a message. (See Figure 2). This is important for safety reasons with a real robot, but also so that you have time to make sure the robot is connected before the program starts to send it commands. Even in simulation, it takes a little while for the simulator to start up so you should not fire off commands immediately.
The last block in the startup sequence is a GenericDifferentialDrive. You should be familiar with this from previous labs. Drag it from the Services panel to your diagram. Then in the Properties select the configuration option to "Use a manifest", and click on the Import button. Find the appropriate manifest for your robot. (If you are using the supplied diagram, it is already configured for the simulated Create).
Connect the output of the SimpleDialog to the input of the GenericDifferentialDrive and edit the data connection explicitly so that the Distance is 0.5, the Power is 0.5 and the DriveDistanceStage is DriveStage.InitialRequest. This will get the robot moving on the first leg of its "square dance".
Step 2: Listening for Completion Notifications
Drag another GenericDifferentialDrive to the diagram. A dialog will pop up. Make sure that you use the existing service and do not create a new one.
Add an If activity to the diagram. Make a connection from the round pin (the notification pin) on the GenericDifferentialDrive to the If block. Select the DriveDistance message type. In the If expression enter:
value.DriveDistanceStage = DriveStage.Completed
This test checks whether the drive has completed a DriveDistance operation. However, to drive in a square the robot also needs to rotate on the spot. Notice that the Else output is not used. This means that any other value of DriveDistanceStage will be ignored. Remember from the previous lab that there are notifications when an operation starts (DriveStage.Started), but these are not relevant here.
Add another If to the diagram. Create another connection from the notification pin on the GenericDifferentialDrive to the new If block, but this time select the RotateDegrees message type. In the In the If expression enter:
value.RotateDegreesStage = DriveStage.Completed
Combine the outputs of the two If blocks by adding a Merge block and connecting the If blocks to it. The code so far should look like Figure 3.
Step 3: Increment the Step counter
Every time that a notification arrives to say that a DriveDistance or RotateDegrees operation has completed, a message is sent from the Merge block. This can be used to increment the value of the variable called Step as shown in Figure 4 by using a Calculate activity and passing a Set message to a Variable activity.
Note that the Calculate activity in Figure 4 has been flipped so that the incoming message from the Merge connects on the right-hand side, not the left-hand side. You can change the orientation of the block using the pop-up context menu. Right-click on the Calculate block and select Flip Connections as shown in Figure 5. You can always tell which is the input pin and which is the output pin because they are displayed as arrows that indicate the direction of message flow. This is not an essential step, but it is a useful feature for simplifying the layout of diagrams.
Remember that Step is a state variable for this program. It controls which operation the robot performs next. So incrementing Step causes the robot to go through a sequence of operations, as shown in the next section.
Step 4: Implementing the Steps for the Square
Drag a Switch activity to the diagram. This functions like a series of If activities. (In some programming languages this is referred to as a "Case" statement -- it selects from one of several different cases). If you look at Figure 6 you will see that there are seven different values, and an Else. You can add the additional expressions to a Switch by clicking on the plus sign at the bottom-left of the block. Go ahead and do that now.
Connect the output of the Calculate block (the new incremented value of Step) to the input of the Switch. It should now be apparent how this works. The value of Step is set to zero during the initialization in Section 1, Figure 2. Each time that a completion message arrives, Step is increased by one so the Switch sends a message to the next output in the sequence. Eventually the value reaches 8 and the Else fires, which is the end of the program.
Now you need to attach the correct drive operations to each of the Switch outputs, and a SimpleDialog to the Else to display a message saying the program has finished.
The procedure is as follows:
- Insert a new GenericDifferentialDrive block;
- Connect the new GDD to the next Switch output;
- Select alternately the RotateDegrees or DriveDistance operations when you add the drive request.
For the RotateDegrees operations, set the Degrees parameter to 90. (Later you can try it with -90 instead and see what happens. You can also experiment with different angles.) For each of the DriveDistance operations set the Distance parameter to 0.5, which is half a meter or about one and a half feet.
Lastly, add a Simple Dialog to the diagram and connect it to the Else output of the Switch. Any value of Step that is greater than 7 (or less than 1) will cause the Else output to be triggered.
When you have finished, this part of the diagram should look like Figure 6.
Step 5: Run the program
Save the program and then run it. Remember that you must click on the OK button in the Alert dialog before the robot will start moving. When it has finished, did it drive in a square?
If you are using the simulator, the chances are very good that the robot will actually draw a square (although the accuracy still depends on which simulated robot you selected and the drive power). However, if you are using a real robot then it is very likely that the robot will not drive in a square. This happens because the DriveDistance and RotateDegrees operations are not guaranteed to perform their tasks precisely. Due to tolerances in the manufacturing of the drive, wheel slippage and many other factors it is quite possible that the robot will never draw a perfect square. This is a real-world problem, and one that roboticists spend a lot of time correcting.
Now you can experiment with the program. What would happen if you used different angles and/or different distances in the various drive operations? Try it out.
What if you wanted to draw a different pattern instead of a square? Consider adding or removing steps in the Switch. You should be able to configure the program to draw a variety of shapes provided you know some basic geometry. Finally, a use for that geometry you learnt in school!
VPL Examples - Drive In Triangle
The Drive In Triangle example in the VPL Examples shows you how to use the DriveDistance and RotateDegrees operations to make a robot drive in a pattern. It waits for each operation to complete before starting the next one. It uses a different approach from this lab and you should look at it as well.
VPL Hands On Labs: VPL Lab 5 - Exclusivity Test
VPL User Guide: Getting Started
© 2012 Microsoft Corporation. All Rights Reserved.