Задани на лабораторные работы. ПРК / Professional Microsoft Robotics Developer Studio
.pdf
www.it-ebooks.info
Chapter 14: Remotely Controlling a Mobile Robot
The LEGO NXT V2 services will not generate red error messages if the LEGO NXT is not turned on. Instead, it simply waits for a connection.
If you made any typing errors when you created the manifest, then red error messages will also appear in the Command Prompt window from the Manifest Loader. You will also see errors appear if you turn off the LEGO NXT before shutting down the service.
Assuming that you did everything correctly, a Dashboard window will appear, as well as a LEGO NXT Brick window. You will have to enter the COM port number again. This happens because you have copied the original manifest into a different folder, but you did not copy the config files. Look in the ProMRDS\Config folder now and you will see a set of config files.
If you continue to run the Tribot from this batch command file, then this will not be a problem. However, if you start your Tribot by running the original manifest, you will have two sets of config files and things can very rapidly get confusing. This is why it is a good idea to place all of your manifests together in a single Config directory.
In the Dashboard, enter localhost for the machine name and click Connect. (The machine name will change to the actual computer name.) Double-click the LEGO drive in the service list to select it, and then click the Drive button. You can now drive the robot around. When you drag the mouse on the “trackball” (just above the Stop button), the Tribot should drive around. Try it out.
The port you use in the Dashboard should be 50001, which is the TCP port. Remember that two ports are specified on the command line. If you mistakenly enter 50000, you will be waiting a long time because there won’t be any response.
At this stage you will probably want to click File
Save Settings to remember your remote node, the window position, and so on. When you get tired of playing with the Tribot, press Ctrl+C in the Command Prompt window. Note that closing the Dashboard window does not terminate DssHost.
Using a Joystick or Gamepad
Driving a robot using the “trackball” in the Dashboard is a little tricky. It is much easier to use a control that is designed specifically for the purpose. If you have a joystick or an Xbox 360 GamePad, then you can use that to drive the robot. The only requirement is that the controller must be supported by DirectX. Simply plug in the joystick or gamepad and run a robot manifest that includes the Dashboard.
The example in Figure 14-17 shows a Logitech Attack 3 USB joystick being used to drive a LEGO NXT Tribot using the Simple Dashboard.
623
www.it-ebooks.info
Part IV: Robotics Hardware
Figure 14-17
If you look carefully at the dialog, you will notice that there is an “x” for the leftmost button in the row of “o” symbols. This indicates that the trigger button on the joystick is depressed (and none of the other buttons on the joystick are currently pressed). You can use the trigger so that the robot will only move when the trigger is depressed and the joystick is off-center. Some of the other buttons also have functions, but they are not described here — look in the code for the Dashboard.
If you have an Xbox 360 USB GamePad and a joystick, then it will appear in the drop-down list for Direct Input Devices. Simply select it instead of your joystick. You can use the left-hand thumbstick to drive the robot.
Creating a Shortcut to Run Your Robot
Although the dsshost command is now safely embedded in a command procedure, you can’t doubleclick the command procedure in Windows Explorer to run the program. If you watch the screen carefully, you will see a DOS Command Prompt window appear and then quickly disappear again.
The problem is that the environment for running DSS has not been set up. This is easily fixed by a small modification to the command file. Edit RunLego.cmd by adding the two extra lines shown here:
@ECHO ON
REM Run a LEGO NXT Tribot
REM Type Ctrl-C in this window when you want to stop the program. setlocal
call “%~dp0sdkenv.cmd”
dsshost -port:50000 -tcpport:50001 -manifest:”ProMRDS/Config/MyTribot.manifest.xml”
624
www.it-ebooks.info
Chapter 14: Remotely Controlling a Mobile Robot
The purpose of these extra commands is to run sdkenv.cmd, which sets up the MRDS environment. This creates the necessary environment variables. When you open an MRDS Command Prompt window from the Start menu, these variables are already defined.
From Windows Explorer, double-click RunLego.cmd. This should start the program just as if you had run it from an MRDS command prompt.
Taking this one step further, right-click RunLego.cmd in Windows Explorer and click Create Shortcut from the pop-up menu. This will create a shortcut called Shortcut to RunLego.cmd. You can rename this to whatever you like. For example, you might call it just RunLego. If you right-click this shortcut and then click Properties, you can change the icon. A batch file does not contain any icons, but you can select from the default set of icons in Shell32.DLL.
Finally, you can copy or move the shortcut anywhere you like, such as onto your Desktop. This gives you immediate access to the LEGO NXT Tribot right next to all your other important business applications (see Figure 14-18).
Obviously, you can create other command procedures and icons this way for the Boe-Bot or for the LEGO NXT V2 services. Even more complex command procedures can be used to select among a variety of robots.
Figure 14-18
Making a Robot Dance
Now that you have your robot working, it would be good to make it do something on its own without requiring a human to drive it around. The first step is to get it to perform some pre-programmed tasks, which might be referred to as a behavior.
The code for the final version of this example is available in the ProMRDS\Chapter14\Dance directory once you have installed the sample software from the book’s website (www.proMRDS.com or www.wrox
.com). You do not have to type in all of the code.
The initial example aims to get the robot to drive around the sides of a square. This might sound like a very simple task, but it actually introduces some real-world problems. How can you determine how far the robot has driven or how far it has turned? The simplest approach is to use timers. For example, you can run the robot for a short period of time and measure how far it travels. If you do this for several
625
www.it-ebooks.info
Part IV: Robotics Hardware
different time periods, you can plot a graph of distance versus time. This is a very scientific approach. (See the example with the Hemisson robot in Chapter 17.)
The steps that follow do not assume that you are experienced in MRDS. If you have followed through the chapters on simulation you will have created a new service before. Therefore, this chapter repeats all of the steps but with a little less explanation.
Building a New Service
This section contains instructions for building a new service from scratch. The completed service, with several additional features, is available in the ProMRDS\Chapter14\Dance folder.
An extra service called SynchronizedDance was added late in the development of this book. This service controls multiple robots and makes them all perform the same dance. It is not discussed here.
Create a new directory called ProMRDS\Dance and then create a new service as per the commands below. Once the service has been created, open the solution called Dance.sln. To open this in Visual Studio, you can either type the filename at the command prompt as in the following example, or doubleclick it in Windows Explorer:
C:\Microsoft Robotics Studio (1.5)>cd ProMRDS C:\Microsoft Robotics Studio (1.5)\ProMRDS>mkdir Dance C:\Microsoft Robotics Studio (1.5)\ProMRDS>cd Dance
C:\Microsoft Robotics Studio (1.5)\ProMRDS\Dance>dssnewservice /service:”Dance”
/namespace:”ProMRDS.Robotics.Dance” /year:”2007” /month:”10”
C:\Microsoft Robotics Studio (1.5)\ProMRDS\Dance>cd Dance C:\Microsoft Robotics Studio (1.5)\ProMRDS\Dance\Dance>Dance.sln
If you are using Visual Studio Express Edition and you have multiple languages installed, make sure that you select C# in the Choose Application dialog, as shown in Figure 14-19.
Figure 14-19
Open Dance.cs and add the following using statement at the bottom of the list:
using drive = Microsoft.Robotics.Services.Drive.Proxy;
In order to actually use the drive proxy, you must also add a reference to the appropriate DLL, which in this case is RoboticsCommon.Proxy. You can right-click the Solution Explorer panel and then click Add Reference. Alternatively, click Project
Add Reference. It might take a little while to display the list of DLLs, so be patient. Set the Local Copy and Specific Version properties on the Reference to false.
626
www.it-ebooks.info
Chapter 14: Remotely Controlling a Mobile Robot
Scroll down in the code to just below the main port declaration and insert a drive partner as shown here:
[ServicePort(“/dance”, AllowMultipleInstances=false)] private DanceOperations _mainPort = new DanceOperations();
#region partners
[Partner(“Drive”, Contract = drive.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExisting)]
drive.DriveOperations _drivePort = new drive.DriveOperations(); #endregion
It is a good idea to use regions in the code so that you can collapse sections of code to make it easier to find your way around. It also helps to make the code self-documenting.
This code sets up a generic differential drive partner, which means that you can connect to a specific type of robot at runtime by specifying the appropriate contract in the manifest. Notice that the CreationPolicy is set to UseExisting. This causes the Dance service to wait until the partner becomes available. It would not make sense to create a new instance of the drive partner because there is no way to tell which of the many different robot drive services should be used. It is the responsibility of the Manifest Loader to associate a real differential drive with the generic one at runtime.
Add some constants at the top of the class definition as shown:
public class DanceService : DsspServiceBase
{
#region constants
// Constants for motor speeds and timing
const int repeatCount = 2; |
// Number of times to repeat dance |
const float driveSpeed = 0.5f; |
// Speed driving forward |
const float rotateSpeed = 0.25f; |
// Speed during rotation |
const int driveTime = 1200; |
// Time to drive forward (millisec) |
const int rotateTime = 920; |
// Time to rotate |
const int settlingTime = 500; |
// Time to wait after each move |
#endregion |
|
The purpose of these constants should be obvious from their names and the comments. Basically, the robot will drive around the sides of a square by driving forward for a certain amount of time, turning for a different amount of time, and repeating this three times. An overall repeatCount enables the entire “square dance” to be repeated.
Because some robots are quite primitive, using timers to control motions is the only option that you have. More expensive robots have wheel encoders that can be used to monitor how much the wheels have turned. The LEGO NXT motors do actually have encoders, but they are not used in this example. This is discussed later.
The numbers listed in the preceding code were determined by trial an error. They are not exact, so the robot will not necessarily traverse a perfect square. They also depend on whether you have fresh batteries in the robot because motor speed can decrease considerably as the battery voltage drops.
The settlingTime is a period of time between moves to enable the robot to settle down. Robots cannot instantaneously change speed and/or direction. Without this settling period, driving forward and turning tend to blend into one another, reducing accuracy.
627
www.it-ebooks.info
Part IV: Robotics Hardware
Go to the bottom of the class now and add the following method called Behavior:
#region behavior
// Iterator to execute the Behavior IEnumerator<ITask> Behavior()
{
//Wait for the Lego NXT to initialize, otherwise it will
//miss the initial command
yield return Arbiter.Receive( false, TimeoutPort(10000),
delegate(DateTime timeout) { });
LogInfo(LogGroups.Console, “Starting now ...”);
// Make sure that the drive is enabled first! _drivePort.EnableDrive(true);
for (int times = 0; times < repeatCount; times++)
{
// Drive along the four sides of a square for (int side = 0; side < 4; side++)
{
LogInfo(LogGroups.Console, “Side “ + side);
// Start driving and then wait for a while _drivePort.SetDrivePower(driveSpeed, driveSpeed); yield return Arbiter.Receive(
false,
TimeoutPort(driveTime), delegate(DateTime timeout) { });
//Stop the motors and wait for robot to settle _drivePort.SetDrivePower(0, 0);
yield return Arbiter.Receive( false, TimeoutPort(settlingTime), delegate(DateTime timeout) { });
//Now turn left and wait for a different amount of time _drivePort.SetDrivePower(-rotateSpeed, rotateSpeed); yield return Arbiter.Receive(
false,
TimeoutPort(rotateTime), delegate(DateTime timeout) { });
//Stop the motors and wait for robot to settle
_drivePort.SetDrivePower(0, 0); yield return Arbiter.Receive(
false,
TimeoutPort(settlingTime), delegate(DateTime timeout) { });
}
}
628
www.it-ebooks.info
Chapter 14: Remotely Controlling a Mobile Robot
// And finally make sure that the robot is stopped! _drivePort.SetDrivePower(0, 0);
LogInfo(LogGroups.Console, “Finished”);
}
#endregion
The Behavior method is an iterator. It periodically yields control of the running thread using yield return. When an Arbiter.Receive has received a message, the CCR resumes execution of the task at the point where it yielded. This means that the code is executed sequentially, but not necessarily by the same thread.
The first step is to wait for 10 seconds (10,000 milliseconds). This ensures that the partner service has started. It is not a reliable or efficient way to wait for a partner, but it is used here for simplicity.
Notice the calls to LogInfo(LogGroups.Console, “...”) in the code, which are there for debugging and to monitor progress. Various logging methods are available for use with DSS, including LogError, LogWarning, LogInfo, and LogVerbose. In this case, the output will be sent to the console (the MRDS Command Prompt window) just as if you had used Console.WriteLine(”...”). If you omit
the LogGroups.Console parameter, then the output is sent to the log, not the console. Either way, the output appears in the Console Output web page.
The drive must be enabled before it will respond to any other commands.
Next are two nested loops. The outermost loop simply repeats the “dance” pattern, while the innermost loop executes the four sides of the square that make up the basic behavior. The code consists of a series of calls to SetDrivePower followed by a wait.
Speed versus Power
In MRDS, there are two ways to make a robot move — by setting its speed or the power to the motors. However, some service implementations don’t distinguish between these two methods.
Power normally ranges from 0 to 1. If the power is negative, then the motor runs backwards.
Speed, conversely, is set in meters/second, so it must be calculated based on the radius of the wheels and knowledge of the relationship between the RPM (revolutions per minute) of the wheels and the applied power. This information is rarely available.
SetDriveSpeed does not work with the LEGO NXT in V1.5, so you must use SetDrivePower. You can waste a lot of time wondering why your robot is not moving if you try to use SetDriveSpeed. For the Boe-Bot, the SetDriveSpeed handler simply passes the values across to SetDrivePower, which is not correct but at least the robot moves.
629
www.it-ebooks.info
Part IV: Robotics Hardware
The last piece of code you need to add is to execute the Behavior from the Start method:
protected override void Start()
{
base.Start();
// Add service specific initialization here. SpawnIterator(Behavior);
}
Try building the service to ensure that you have not made any mistakes. There is no point in running it yet because it needs a drive service for a robot as a partner.
Partnering with a Robot Using a Manifest
You now have a service that can control a robot, but you need to associate it with an actual robot so that it can run.
Open Dance.manifest.xml, which DssNewService created for you. You should see it in the Solution Explorer panel in Visual Studio and you can open it from there. Visual Studio understands XML and will color-code it for you. Add a new Service Record just above the existing Service Record for the Dance service:
<!-- Use a Simulated robot --> <ServiceRecordType>
<dssp:Contract>http://schemas.tempuri.org/2006/06/simulationtutorial2.html </dssp:Contract>
</ServiceRecordType>
Notice that the additional service is Simulation Tutorial 2 that comes with MRDS. This creates two robots: a Pioneer 3DX and a LEGO NXT Tribot. Save the manifest. (A complete copy of the manifest is supplied as ProMRDS\Config\Dance.SimTut2.manifest.xml.)
You can now run this new service by simply starting the Dance program in the debugger in Visual Studio.
After the simulator starts, there is a short delay and then the Pioneer robot will start doing the “dance.” Figure 14-20 shows the Pioneer partway through its behavior. The LEGO NXT Tribot (in the foreground) will not move.
630
www.it-ebooks.info
Chapter 14: Remotely Controlling a Mobile Robot
Figure 14-20
When the Pioneer robot has finished, the MRDS window will look like Figure 14-21. Notice the status messages as it progresses through each side of the square; they include a timestamp and the name of the service. Dance, dance, dance!
Figure 14-21
You might be wondering why the Pioneer robot did the dance when this chapter has been dealing with LEGO NXT robots. The reason is that Simulation Tutorial 2 creates the Pioneer robot first. Because the
631
www.it-ebooks.info
Part IV: Robotics Hardware
Pioneer has a differential drive, the Dance service immediately partners with it. It is possible to enumerate the available services and select the LEGO service, but that’s far too complicated for this simple example. Look in the code of the Dashboard for details about how to list the available services.
If you only want to play with the LEGO NXT simulation, then you can use a saved simulation state and start up the necessary simulation services by running the manifest from the book’s website. Located in ProMRDS\Config\Dance.Simulation.manifest.xml, this manifest is an example of how to use saved simulator state, a topic that is not covered in this part of the book.
Using the LEGO NXT Tribot
Now it is time to switch to a real robot so you can see the power of MRDS. The same code you have just used in the simulator will work on a LEGO NXT Tribot.
Go back to the Dance.manifest.xml in Visual Studio and either remove the service record for Simulation Tutorial 2 or comment it out. In its place, insert the code for the LEGO NXT V2, which is highlighted in the following manifest listing. (The complete manifest is supplied with the name Dance
.LegoV2.manifest.xml if you want to check your work.) The simulated robot has been commented out in the following code:
<?xml version=”1.0” ?> <Manifest
xmlns=”http://schemas.microsoft.com/xw/2004/10/manifest.html”
xmlns:dssp=”http://schemas.microsoft.com/xw/2004/10/dssp.html”
>
<CreateServiceList>
<!-- Create a new Lego NXT service --> <ServiceRecordType>
<dssp:Contract>http://schemas.microsoft.com/robotics/2007/07/lego/
nxt/brick.html</dssp:Contract>
<dssp:PartnerList> <dssp:Partner>
<dssp:Contract>http://schemas.microsoft.com/robotics/2007/07/
lego/nxt/brick.html</dssp:Contract>
<dssp:Service>legov2.nxt.brick.config.xml</dssp:Service> <dssp:PartnerList /> <dssp:Name>dssp:StateService</dssp:Name>
</dssp:Partner> </dssp:PartnerList> <Name>Brick</Name>
</ServiceRecordType> <ServiceRecordType>
<dssp:Contract>http://schemas.microsoft.com/robotics/2007/07/lego/
nxt/drive.html</dssp:Contract>
<dssp:PartnerList> <dssp:Partner>
<dssp:Contract>http://schemas.microsoft.com/robotics/2007/07/
lego/nxt/drive.html</dssp:Contract>
<dssp:Service>legov2.nxt.drive.config.xml</dssp:Service> <dssp:PartnerList /> <dssp:Name>dssp:StateService</dssp:Name>
632
