Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Задани на лабораторные работы. ПРК / Professional Microsoft Robotics Developer Studio

.pdf
Скачиваний:
126
Добавлен:
20.04.2015
Размер:
16.82 Mб
Скачать

www.it-ebooks.info

Chapter 16: Autonomous Robots

Wandering Using Sensors

You have seen a Wander behavior in Chapter 14. The behavior in this chapter is somewhat more complex and the robot can wander autonomously because the computer can be onboard.

To initiate wandering you click the Wander checkbox on the Form. Of course, if your robot is operating autonomously then there might not be a Form! To get around this problem, the setting of the Wander checkbox is saved in the config file when the service exits (or you can edit the config file manually). If the flag is already set when the service starts, it immediately goes into wander mode.

Handling the IR Sensors

In the sample code, the Stinger uses three IR sensors. These all operate independently, and because they are all separate services they can take some time to start up. In fact, the first update will not arrive until the range value changes, so you might have to wave your hand in front of the robot.

To avoid possibly making decisions before the data is available, the Wander behavior is started by the IR sensor handler only after data has been received from all three sensors. The code that does this is at the bottom of the ReplaceIRHandler (from the end of the previous section):

//Finally, if the timer is not going then start it now.

//This ensures that the timer does not start until IR data

//is arriving. Otherwise the Wander behavior might try to

//process IR values before they are valid and this would

//result in some strange behavior initially.

if (_state.WanderEnabled && !_timerRunning)

{

if (_state.IRLeft != 0 && _state.IRFront != 0 && _state.IRRight != 0)

{

//Indicate that the timer is active and call the Wander

//routine to kick it off immediately with the new IR

//data that has just arrived

_timerRunning = true; Wander(System.DateTime.Now);

}

}

The Wander method implements the Wander behavior. It relies on some constants defined at the top of the main service:

//Thresholds for the IR sensors

//NOTE: These values are in CENTIMETERS and depend on the config

//settings for the IR sensors being set to Metric. Also, the

//Stinger does not turn around its center -- the back end hangs out!

//This means that it really needs about 30cm clearance to avoid

//banging its backside on a wall as it turns. A value of 20 for

//the Front Threshold is probably too low, but in limited space

//you don’t want to set it too high. Bear in mind that the GP2D12

//can only measure down to 10cm and then it starts to go UP again! private const double FRONT_THRESHOLD = 20;

private const double LEFT_THRESHOLD = 30;

(continued)

703

www.it-ebooks.info

Part IV: Robotics Hardware

(continued)

private const double RIGHT_THRESHOLD = 30;

//Timer interval for the Wander behavior private const int WANDER_INTERVAL = 100;

//Number of timer “ticks” to execute respective behaviors

//Multiply these counters times the Wander Interval to get

//the amount of time spent in each behavior

private const int TURN_COUNT = 10; private const int VEER_COUNT = 10; private const int BACKUP_COUNT = 10;

//Motor power to use for various modes

//The Stinger power settings range from -100 to +100,

//but don’t include a sign here

//NOTE: In limited space, don’t set these higher than

//about 50. This little sucker is fast!

private const int DRIVE_POWER = 50; private const int TURN_POWER = 50; private const int VEER_POWER = 25; private const int BACKUP_POWER = 50;

The Wander behavior runs on a timer controlled by the WANDER_INTERVAL. It is a state machine that moves between states based on the values of the IR sensors. The COUNT values are used to ensure that the robot remains in a particular mode for a certain number of iterations. If you take a COUNT and multiply it by the WANDER_INTERVAL, you will get the elapsed time.

Defining Wander Modes

The various wander modes (or states) are defined in StingerDriveByWireTypes.cs as a public enum and the current mode is stored in the WanderMode field in the service state. Placing the wander mode in the service state enables it to be examined using a web browser. Using an enum declared with [DataContract]makes the values available outside the service and also stored symbolically in the saved state:

// Modes that the robot can be in while wandering [DataContract]

public enum WanderModes

{

None,

DriveStraight,

VeerLeft,

VeerRight,

TurnLeft,

TurnRight, BackUp

}

The modes should not require much explanation (refer to Chapter 14 for more details). Initially, the robot is in the None mode and then immediately transitions to DriveStraight when wandering is enabled. VeerLeft and VeerRight are triggered if the rightor left-side IR sensor, respectively, sees an obstacle. BackUp is triggered if all of the IR sensors are blocked, but it does not occur very often because of the effects of the other modes. In fact, the robot performs a TurnLeft or TurnRight in preference to BackUp.

704

www.it-ebooks.info

Chapter 16: Autonomous Robots

The whole of the Wander method is shown in the following code. It is fairly long, but if you look at each of the Wander modes separately it is relatively easy to understand. There are many other ways that the behavior could be implemented, and this is not necessarily the best way:

//The Wander Behavior

//This is a State Machine that runs on a timer.

//It works reasonably well except for the Stinger’s fat

//backside which scrapes on the walls from time to time. void Wander(DateTime t)

{

// See if we should execute the Wander behavior if (_state.WanderEnabled)

{

switch (_state.WanderMode)

{

case WanderModes.DriveStraight:

//This code does not check for combinations of Left and Right

//which should be unnecessary as long as the Front is free if (_state.IRFront < FRONT_THRESHOLD)

{

//This presents a problem because the front threshold has

//been breached, so we need to take evasive action

if (_state.IRLeft < LEFT_THRESHOLD && _state.IRRight < RIGHT_THRESHOLD)

{

// If both sides are blocked, back up BackUp();

}

else

{

// Otherwise, turn towards the clearest direction if (_state.IRLeft < _state.IRRight)

TurnRight();

else

TurnLeft();

}

}

else if (_state.IRLeft < LEFT_THRESHOLD)

{

// Left side obstacle seen VeerRight();

}

else if (_state.IRRight < RIGHT_THRESHOLD)

{

// Right side obstacle VeerLeft();

}

break;

case WanderModes.None:

// No mode selected, so start driving DriveStraight();

break;

(continued)

705

www.it-ebooks.info

Part IV: Robotics Hardware

(continued)

case WanderModes.BackUp:

//Decrement the counter _state.WanderCounter--;

//If finished, try something else

//Otherwise just fall through and keep backing up if (_state.WanderCounter <= 0)

{

//Turn in the clearest direction.

//DON’T start driving ahead because that is

//where we just came from!

if (_state.IRLeft < _state.IRRight) TurnRight();

else

TurnLeft();

}

break;

case WanderModes.VeerLeft:

//If veering has cleared the corresponding side,

//then drive straight again.

//It makes sense to check here if the way

//is blocked first, and if so then continue

//turning but this time harder.

if (_state.IRFront < FRONT_THRESHOLD) TurnLeft();

else

{

if (_state.IRRight > RIGHT_THRESHOLD) DriveStraight();

}

break;

case WanderModes.VeerRight:

if (_state.IRFront < FRONT_THRESHOLD) TurnRight();

else

{

if (_state.IRLeft > LEFT_THRESHOLD) DriveStraight();

}

break;

case WanderModes.TurnLeft: _state.WanderCounter--;

if (_state.WanderCounter <= 0)

{

//If front is clear now, then drive ahead

//Otherwise keep turning left

if (_state.IRFront > FRONT_THRESHOLD) DriveStraight();

else

TurnLeft();

}

break;

706

www.it-ebooks.info

Chapter 16: Autonomous Robots

case WanderModes.TurnRight: _state.WanderCounter--;

if (_state.WanderCounter <= 0)

{

//If front is clear now, then drive ahead

//Otherwise keep turning right

if (_state.IRFront > FRONT_THRESHOLD) DriveStraight();

else

TurnRight();

}

break;

default:

Console.WriteLine(“Invalid Wander Mode!”); break;

}

}

// If the timer is still running, then kick it off again if (_timerRunning)

{

// Restart the timer Activate(Arbiter.Receive(

false, TimeoutPort(WANDER_INTERVAL), Wander)

);

}

}

Notice that the last thing the Wander method does is start the timer again. The global flag _ timerRunning can be used to stop wandering by preventing the timer from being started again.

Running the Wander Code

To run this service on your desktop PC, you need to edit the config file to set the correct COM port for your Bluetooth connection. The config file you need to change is the one for the Serializer, not the one for theStingerDrive-By-Wireservice.ThefilenameisProMRDS\Config\Stinger.Serializer.config.xml.

When you have changed the value of the ComPort setting, you can run the service either by starting it in the debugger in Visual Studio or by running RunStinger.cmd, which is in the MRDS bin folder.

Eventually, the Form in Figure 16-8 should appear and you can manually drive the robot by using the arrow keys on the keyboard or clicking the direction buttons. Note that you have to click Stop if you use the buttons on the Form, but if you use the keyboard you can just release the key.

When you are satisfied that the robot is working and you can see that the IR sensor values are updating, you can click the Wander checkbox and let it go on its own. Make sure that you turn off wandering before you click Exit because the setting of the Wander flag is saved to the config file.

707

www.it-ebooks.info

Part IV: Robotics Hardware

Creating a CF Version of the Service

After you have the desktop version of the service working, you can progress to the CF version. (That’s the beauty of using Bluetooth on both the desktop and the PDA). To do this, you use DssNewService to make a CF service. This has already been done for you in the sample code, but the instructions are provided here for your reference.

You must have the full version of Visual Studio 2005 in order to create CF projects. The Express Edition of Visual C# will not work.

The steps to make a CF service from an existing desktop service are quite simple:

Open a MRDS Command Prompt window and change directory to where the service source code is located.

Enter the command dssnewservice/generatecfproject:existingservicename.csproj.

Some new files will be created with the same names as the old service files but with a prefix of “cf.”. For the preceding example, there will be a new project file called cf.existingservicename.csproj. Open your existing solution and add the new project to the solution so that you can easily edit both projects.

An alternative to converting the project is to create the CF project at the outset when you first create the new service. You can do this on the command line to DssNewService by using the /createcfproject command-line qualifier (abbreviated to /ccfp). However, it is more likely that you have existing projects you want to migrate.

Unfortunately, you are not finished yet. Several more steps are required:

1.

2.

3.

4.

5.

6.

Windows Forms under Windows XP or Vista are quite different from Forms under Windows Mobile or CE. Therefore, you have to delete the Windows Form from the new CF project and then create a new one from within the CF project.

Give the new Form the same name as the old one but with “cf.” in front of the name so that it will have a unique filename. Once the Form has been created, go into the code for the Form and remove the “cf.” prefix from the Form class name. This little trick is necessary so that the existing code in the service that references the Form will work for either the desktop or the CF versions.

Now you need to recreate the Form with exactly the same controls as the desktop version. Add the buttons, labels, and so on, as required and make sure that they have the same names as those in the desktop Form. Do this through the Design view on the CF Form.

Once you have added all of the UI controls, add the event handlers. For example, double-click a button to create the corresponding Click event. Do this for all the event handlers. Remember that the keyboard event handlers can be added through the Properties panel for the Form.

Copy the code from each of the event handlers in the desktop Form across to the corresponding handler in the CF Form. This is a tedious process, but it is the best way to guarantee that the handlers are registered properly. Simply copying all of the code from the desktop Form over to the CF Form does not create all of the necessary “connections.” (The event handlers are specified in the Form designer file, which is automatically generated. Although you can edit this if you know what you are doing, it is not advisable.)

Build your new CF project.

708

www.it-ebooks.info

Chapter 16: Autonomous Robots

Assuming that everything compiles OK, you should find DLLs in the MRDS bin\CF folder with the name of your service prefixed by “cf.”

Deploying a Service to a PDA

Before you can use your PDA to run a MRDS service, you must ensure that it has the latest version of the V2.0 .NET Compact Framework installed, which was Service Pack 2 at the time of writing. You can download this runtime environment from the Microsoft website. Then you have to run the installer on your desktop PC and install the software to your PDA using ActiveSync.

Now that you have a CF service ready to run, you need to get it onto your PDA. The first step in deploying your service is to create a package. The DssDeploy tool is designed for this purpose.

Open a MRDS Command Prompt window and change directory to your service source folder. Assuming the manifest for your CF service is in the same directory and is called cf.service.manifest.xml, you can enter the following command:

dssdeploy /p /cf /m:cf.service.manifest.xml cfdeploy.exe

This command creates a CF package called cfdeploy.exe using the specified manifest. The /cf qualifier indicates that the package should be built for the CF environment.

Creating a CF Package

Continuing with the Stinger example, perform the following steps:

1.

2.

3.

4.

For the example service, a batch file called BuildStingerCFPackage.cmd is supplied in the source folder. This runs DssDeploy and creates an output file called StingerCF.exe. However, before running this, edit the config file ProMRDS\Config\StingerCF.Serializer.Config. xml to change the ComPort setting to the outgoing port number that you found when you paired your PDA with the Stinger robot.

Note carefully that this config file is called StingerCF and not Stinger. There are two versions. There is also a separate manifest called, appropriately, StingerCFDriveByWire. manifext.xml.

DssDeploy generates a self-expanding executable. You must copy this to your PDA and then execute it from the location where you want it to unpack itself. The package contains all of the files necessary to run the CF version of DssHost so that you can start a DSS node and run your service.

Microsoft suggests creating a folder called \Program Files\MRDS, so open File Explorer on your PDA and make a folder called MRDS under Program Files. Then copy your package into this folder using ActiveSync and run it from File Explorer on the PDA by tapping on it.

After a little while, you should see a bin directory. If you are using the example code from this chapter, there will also be a ProMRDS folder. In the process of deploying the package, all of the necessary executable files are copied from bin\CF on your desktop to the bin folder on your PDA. The manifest and config files, however, are left in ProMRDS\config. Note that none of the source code files are copied because these are not required to run the service.

709

www.it-ebooks.info

Part IV: Robotics Hardware

5. The cf.dsshost.exe program operates a little differently than the desktop version. It assumes that all manifest paths are relative to its own folder, not relative to the current directory when you execute the program. Therefore, it is easiest to place all of the manifests and config files directly into the bin folder alongside cf.dsshost.exe. You need to copy all of the files from ProMRDS\config to bin. These should include the following:

Stinger.Gp2d12Front.Config.xml

Stinger.Gp2d12Left.Config.xml

Stinger.Gp2d12Right.Config.xml

Stinger.Motor1.Config.xml

Stinger.Motor2.Config.xml

StingerCF.Serializer.Config.xml

StingerCFDriveByWire.config.xml

StingerCFDriveByWire.manifest.xml

Running the Service

Finally, you need to run your new service. You can open a command prompt on your PDA (if you installed the Power Toys) and then enter the appropriate commands. Alternatively, you can start the DSS node using a shortcut.

Because typing on the SIP (Software Input Panel) on a PDA is painful, you will find that it is best to create command procedures to do most tasks for you. Some useful procedures are supplied in the folder Chapter16\StingerDriveByWire\CF, which you will see on your PDA. Other general procedures are in ProMRDS\CF.

For example, you might want to create a command procedure called MRDS.cmd in the root directory on your PDA containing the following command:

cd “\Program Files\MRDS\bin”

Then you can simply type MRDS after opening a Command Prompt window to go to the correct directory. A copy of this file is included in the ProMRDS\CF folder.

In the bin folder, you can create a command procedure called RunStinger.cmd containing this command:

cf.DssHost.exe /p:50000 /t:50001 /m:StingerCFDriveByWire.manifest.xml

Notice that the manifest is in the current directory (which must be the bin folder). This batch file is also in the ProMRDS\CF folder for your convenience. Just copy it over to the bin folder on your PDA.

This will start a DSS node and run the service. Be patient. PDAs are not fast, and it will take a little while for DssHost to rebuild the contract directory cache. After a short delay, a new console window will appear and you will begin to see the output from DssHost as it loads the manifest.

Eventually, the Stinger Drive UI should appear. If you have properly paired your PDA with the Stinger robot as well as some other device(s), a window might appear asking you to select the correct Bluetooth

710

www.it-ebooks.info

Chapter 16: Autonomous Robots

device. Once you have done this, the robot will beep once to indicate that a connection has been established. The IR sensor values on the screen should update. If you notice that one of them is blank, wave your hand in front of the sensor. The sensors don’t send updates unless something happens. Now you can drive your robot around.

When you have finished, turn off the robot and click the Exit button. If DssHost does not shut down, try turning off Bluetooth as well. This is an issue that has not been resolved and it is why you might need to use Process Explorer to kill the process. (You can use the Remote Process Viewer if you have ActiveSync running on the PDA). Sometimes Process Explorer is unable to kill DssHost and you have no option but to do a warm restart.

Now you can mount your PDA on your Stinger and let it loose! A universal PDA mounting kit for a car dashboard can be used with appropriate modifications and a little bit of Blutac. Because the PDA has a user interface, there is no need to set it up to run your service automatically — you can start it manually.

Debugging a Service on a PDA

Before you can run a CF service in the debugger, you must deploy it to the PDA. The deployment step in the previous section copies over a lot of files that will not be copied by Visual Studio when you run the service in the debugger, so make sure that you have followed the instructions in the previous section first.

You must have Visual Studio 2005 Service Pack 1 or you might not be able to make a connection to your PDA. You must also have the latest version of ActiveSync on your desktop PC.

Debugging requires an active connection to the PDA. A little bit of “magic” happens in the background to enable you to view and control processes running on the PDA. The first step, however, is to verify that you can successfully connect to the PDA using Visual Studio. Then you can set the appropriate options for debugging on a PDA, and proceed to debug in the same way as you would with a desktop application. Apart from being a little slower, the process is really very simple when you have done it at least once before.

Testing the PDA Connection

You need to confirm that you can establish a connection to the PDA from inside Visual Studio. To test the connection, follow these steps:

1.

2.

3.

4.

5.

Place your PDA is in its docking station and plug it into your PC. Start ActiveSync if it does not launch automatically.

Click the cf.StingerDriveByWire project in the Visual Studio Solution Explorer panel to ensure that it is the currently selected project.

If you do not already have the Device toolbar displayed, then click View Toolbars Device. (Refer to Figure 16-10, which shows the Device toolbar at the left-hand side.).

In the Target Device drop-down list in the Device toolbar, select “Pocket PC 2003 Device.”

Click the “connect to device” icon just to the right of the device list. (It looks like a PDA with a power plug attached). A dialog box appears, and after a short period of time it should indicate that the connection was successful.

711

www.it-ebooks.info

Part IV: Robotics Hardware

6.

7.

Once the connection is established, you can click Target Remote Tools to run the various remote tools that are included with Visual Studio. (Refer to Figure 16-10 for a list of the available Remote Tools.) Help for the Remote Tools is included in Visual Studio help under Smart Devices.

Figure 16-10

You can configure the default device using the Device Options. Either click Tools Options and navigate to Devices or click the Device Options icon, which is in the Device toolbar just to the right of the “connect to device” icon. The Devices window of the Options dialog is shown in Figure 16-11.

Figure 16-11

Setting Up for Debugging

Once you have confirmed the connection to your PDA and finished playing around with the remote tools, you can set up for debugging:

1. In the Properties for the cf.StingerDriveByWire project, go to the Debug tab. Make sure that it is set as follows:

712