My goal is to use a hardware differential drive on a simulated bot. Now the problem was I could not seem to connect the bot to the hardware drive I programmed in. As you can imagine it was a frustrating WEEK that I wasted trying to get it to work, however, thanks to the personal effort of Trevor Taylor, the author of
"Professional Microsoft Robotics Development Studio", I managed to figure out the problem.
Here are the forums I used:
Firstly, create the program that controls your robot. I called mine Actuator (my creative team is on holiday and I will have a better name soon), and all it has is the differential drive. So far, I have only imported RoboticsCommon.Proxy and the only namespace is:
using drive =
Microsoft.Robotics.Services.Drive.Proxy;
Then I created a perform method of type IEnumerator<ITask>, in which all actions can be spawned. Be careful, however, that you time the robots actions appropriately when calling the methods in this fashion. If you travel a long distance, make the timeout operation longer. I think it is more effective that actuators react based on sensor information, but the point of this blog is to get you to a certain point and let you figure out the rest.
private IEnumerator<ITask> perform()
{
//drive a set distance
SpawnIterator<double, double>
(2.0, 1.0, driveRobotDistance);
//wait
yield return Arbiter.Receive
(false, TimeoutPort(2000),
delegate(DateTime t) { });
//turn
SpawnIterator<double, double>
(90.0, 1.0, turnRobot);
//wait
yield return Arbiter.Receive
(false, TimeoutPort(2000),
delegate(DateTime t) { });
//drive again
SpawnIterator<double, double>
(2.0, 1.0, driveRobotDistance);
yield break;
}
private IEnumerator<ITask> driveRobotDistance
(double distance, double power)
{
drive.DriveDistanceRequest driveRequest =
new drive.DriveDistanceRequest
(distance, power);
yield return Arbiter.Choice
(
_drivePort.DriveDistance(driveRequest),
delegate
(DefaultUpdateResponseType response)
{
},
delegate(Fault fault)
{
LogError
(null,
"Unable to drive robot",
fault);
}
);
}
private IEnumerator<ITask> turnRobot
(double angle, double power)
{
drive.RotateDegreesRequest request =
new drive.RotateDegreesRequest
(angle, power);
yield return Arbiter.Choice(
_drivePort.RotateDegrees(request),
delegate
(DefaultUpdateResponseType response)
{
},
delegate(Fault fault)
{
LogError
(null,
"Unable to turn robot",
fault);
}
);
}
That's all there is to this drive. But the point remains that
in code some
physical differential drive is being told to drive
and we can see in what manner to make other physical entities work, as well as react.
Well, that's all there is on this side. Now we need to create an environment. Go to the visual simulation editor and create entities in the same manner as I describe in my post on how to create a custom simulation environment
[HERE]. There are a few changes though:
- Make sure that the lego has the Simulated differential drive contract (not actually a change, just a reminder. Don't try make it the physical drive.)
- (I left this out the last time - how embarrassing!) Make sure that you add wheels to the LegoNXTTribot. You must edit the Left and Right wheel's entity state and load a mesh:

Save the manifest, but make sure you know where the manifest is stored. Then load up the DSS Manifest Editor. This is the power of MRDS / MSRS. You have created a hardware project. You have created a simulated 'version' of the hardware's environment. Now to plug them into each other.
In the manifest editor, load the manifest of the simulation environment. It should look something like this:

What you should notice is that the simulated differential drive actually has an entity: the LegoNXTTribot. I am still not sure in what manner we can do this in code, but at least the entity is there, and we can modify it with the VSE.
Now drag and drop the Actuator file on top of the
simulated differential drive,
not the entity. This creates an instance of the Actuator for the
whole manifest. (To make sure it is not added to the entity, click the entity, it should not highlight any relationships). Then either: drag and drop the existing simulated differential drive on to the Actuator's DRIVE object, or you can just drag a simulated differential drive object from the services section and make sure it is the same one as previously loaded. It should look like this:

Then you can either save the manifest over the manifest for your Actuator application and run from code, or you can run the manifest from the editor by pressing F5. But that is the basics of loading a simulation environment and then plugging in your hardware devices. Happy Botting
©!