Microsoft Robotics Developer Studio
Simulation Tutorial 1 (C#) - Introduction to Visual Simulation Environment

The Microsoft Robotics Developer Studio (RDS)features a powerful Visual Simulation Environment that enables users to develop robots in a rich virtual environment with realistic physics and state of the art rendering. This tutorial teaches you how to start the simulation engine service and rendering window, then add a few movable objects in the virtual world.

Figure 1

Figure 1 - Simulation Visualizer

Figure 2

Figure 2 - Simulation Visualizer: Physics View

This tutorial is provided in the C# language. You can find the project files for this tutorial at the following location under the installation folder:

Sample location
 Samples\SimulationTutorials\Tutorial1

This tutorial teaches you how to:

Simulation Environment Overview

The Simulation Environment is composed of the following components:

  • The Simulation Engine Service - is responsible for rendering entities and progressing the simulation time for the physics engine. It tracks of the entire simulation world state and provides the service/distributed front end to the simulation.
  • The Managed Physics Engine Wrapper - abstracts the user from the low level physics engine API, provides a more concise, managed interface to the physics simulation.
  • The AGEIA™ PhysX™ Technology - enables hardware acceleration through the AGEIA™ PhysX™ processor (Available in PhysX™ Accelerator add-in cards for PCs).
  • Entities - represent hardware and physical objects in the simulation world. A number of entities come predefined with the RDS and enable users to quickly assemble them and build rich simulated robot platforms in various virtual environments.

You can choose to interact only with the managed physics engine API if you don't want any visualization. However, it is strongly recommended that you always use the simulation engine service and define custom entities that disable rendering. This greatly simplifies persistence of state, inspection and debugging of simulation code.

The rendering engine uses the programmable pipeline of graphics accelerator cards, conforming to Directx9 Pixel/Vertex Shader standards. In future tutorials we will talk how the Simulation Environment makes it easy to supply your own effects and have the engine manage loading, rendering, updates to effect state, etc.

Prerequisites

Hardware

A graphics accelerator card suitable for gaming, this includes most mid-range to high-end cards purchased within the last two years. The following link has a list of graphics cards we have tried:

http://channel9.msdn.com/wiki/default.aspx/Channel9.SimulationFAQ

Software

This tutorial is designed for use with Microsoft Visual C#. You can use:

  • Microsoft Visual C# Express Edition
  • Microsoft Visual Studio Standard, Professional, or Team Edition.

You will also need Microsoft Internet Explorer or another conventional web browser.

Getting Started

The service for this tutorial already exists and is available under your RDS installation directory. You will find it in the Samples\SimulationTutorials\Tutorial1 directory.

Begin by loading SimulationTutorial1.csproj (using Visual Studio).

After you have built the project you can run it from the DSS Command Prompt using the following command:

Console
 dsshost32 /port:50000 /manifest:"samples\config\SimulationTutorial1.manifest.xml"

By default, Microsoft Visual Studio is configured to start each sample automatically. You can review these settings from within Visual Studio. In the Solution Explorer, double-click Projects Properties folder. Click the Debug tab Start external program references dsshost32.exe, which you find in the bin subdirectory of the RDS installation folder (for example C:\Microsoft RDS\bin\dsshost32.exe). The command line arguments identify the HTTP port and TCP port for starting a node. The manifest parameter identifies which services start automatically. The working directory should be set to the RDS installation folder. Before running a sample, you must mark that project as the startup project (Project > Set as startup project menu command). You can then run the sample by pressing F5 or choosing the Debug > Start Debugging menu command.

Step 1: Load Required References

To run with simulation you must have references to the following DLLs, available in the RDS installation folder:

  • RoboticsCommon.DLL – Contains PhysicalModel namespace, with common type definitions for modeling physical robot properties.
  • PhysicsEngine.DLL – C++/CLI wrapper around native physics engine dll.
  • SimulationCommon.DLL – Common type definitions.
  • SimulationEngine.DLL – Rendering engine, simulation state management and service front end.
  • SimulationEngine.Proxy.DLL – Proxy for simulation engine state. Used only for loading engine as a partner.
Bb483077.hs-note(en-us,MSDN.10).gif

References should have the Copy Local property set to false.

Figure 3

Figure 3 - SimulationTutotial1 References

In the SimulationTutorial1.cs file, note the following using statements:

C#
 using Microsoft.Ccr.Core;
using Microsoft.Dss.Core;
using Microsoft.Dss.Core.Attributes;
using Microsoft.Dss.ServiceModel.Dssp;
using Microsoft.Dss.ServiceModel.DsspServiceBase;

using System;
using System.Collections.Generic;

using Microsoft.Robotics.Simulation;
using Microsoft.Robotics.Simulation.Engine;
using engineproxy = Microsoft.Robotics.Simulation.Engine.Proxy;
using Microsoft.Robotics.Simulation.Physics;
using Microsoft.Robotics.PhysicalModel;
using System.ComponentModel;

Step 2: Start the Simulation Engine

The simulation engine hosts the window that renders the simulation world. Since it is a regular service, you can use the Partner attributes to start it. Near the top of SimulationTutorial1.cs, you should see the following code:

C#
 [DisplayName("Simulation Tutorial 1")]
[Description("Simulation Tutorial 1 Service")]
[Contract(Contract.Identifier)]
public class SimulationTutorial1 : DsspServiceBase
{
    [Partner("Engine",
        Contract = engineproxy.Contract.Identifier,
        CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate)]
    private engineproxy.SimulationEnginePort _engineStub =
        new engineproxy.SimulationEnginePort();

    // Main service port
    [ServicePort("/SimulationTutorial1", AllowMultipleInstances=false)]
    private SimulationTutorial1Operations _mainPort =
        new SimulationTutorial1Operations();

    public SimulationTutorial1(DsspServiceCreationPort creationPort) :
            base(creationPort)
    {
    }

Notice the use of the Partner attribute's CreationPolicy.UseExistingOrCreate setting since this uses an existing instance of the simulation engine if one was started in the manifest. This proves useful later, when you want the simulation engine to use stored state to restore the state of a previously saved simulation. The _engineStub field is not used for any purpose other than partner loading. The tutorial instead uses a static reference to the engine port instance to directly post messages. This is an exception to the rule for service communication and is done here to achieve maximum performance.

Step 3: Add Entities to the Environment

In the Start method, call the SetupCamera and PopulateWorld methods which we will define in the next steps. SetupCamera orients the camera view in the simulator and PopulateWorld adds a couple of simple environment entities.

C#
 protected override void Start()
{
    base.Start();
    // Orient sim camera view point
    SetupCamera();
    // Add objects (entities) in our simulated world
    PopulateWorld();
}

Adding a camera view

Define the SetupCamera method as follows:

C#
 private void SetupCamera()
{
    // Set up initial view
    CameraView view = new CameraView();
    view.EyePosition = new Vector3(-1.65f, 1.63f, -0.29f);
    view.LookAtPoint = new Vector3(-0.68f, 1.38f, -0.18f);
    SimulationEngine.GlobalInstancePort.Update(view);
}

As you see, SetupCamera instantiates a new CameraView object, sets the proper position and orientation in the scene and posts it to the simulation engine as an Update message.

Adding a Sky

Begin by examining how you can add a sky to the physics world. In game terminology, this is called the sky box since it gives the illusion of a sky by using a "box" or hemi-sphere to wrap the visual world.

C#
 void AddSky()
{
    // Add a sky using a static texture. We will use the sky texture
    // to do per pixel lighting on each simulation visual entity
    SkyDomeEntity sky = new SkyDomeEntity("skydome.dds", "sky_diff.dds");
    SimulationEngine.GlobalInstancePort.Insert(sky);

    // Add a directional light to simulate the sun.
    LightSourceEntity sun = new LightSourceEntity();
    sun.State.Name = "Sun";
    sun.Type = LightSourceEntityType.Directional;
    sun.Color = new Vector4(0.8f, 0.8f, 0.8f, 1);
    sun.Direction = new Vector3(0.5f, -.75f, 0.5f);
    SimulationEngine.GlobalInstancePort.Insert(sun);
}

The SkyEntity class takes two file names as parameters:

  • A texture file used as the sky bitmap. Use high resolution images for detailed skies.
  • A simplified version of the first texture in cube map form (cube maps are 6 textures, like a cube with its sides unfolded), which is used for per-pixel lighting effects.

The simulation engine produces high quality lighting effects by sampling the sky cube map texture and adding the light component to other light sources for each pixel being rendered in the world.

The LightEntity class is used to simulate light sources (explained in more detail in simulation tutorial 5), used here to simulate the sun in an outdoor scene.

Adding a Ground Plane

Now let's examine how you can add a ground plane to the physics world. It's a good idea to add a ground before any other object; otherwise, assuming gravity is enabled, any other entity we add will fall to the virtual abyss.

C#
 void AddGround()
{
    // create a large horizontal plane, at zero elevation.
    HeightFieldEntity ground = new HeightFieldEntity(
        "simple ground", // name
        "03RamieSc.dds", // texture image
        new MaterialProperties("ground",
            0.2f, // restitution
            0.5f, // dynamic friction
            0.5f) // static friction
        );
    SimulationEngine.GlobalInstancePort.Insert(ground);
}

A ground entity normally uses the HeightFieldEntity predefine, which expects an array of height samples. The example above uses a constructor that creates a flat plane, which is a common use of height fields. There are two things that are important to remember for almost all entities:

  • You set the material properties specifying friction and restitution. The physics engine supports advanced friction models (anisotropic, special cased tire force functions for wheels) but in most cases, use static and dynamic friction coefficients.
  • You add the entity to the simulation by calling the asynchronous Insert method on the simulation engine port (in turn, it posts the entity as an Insert message).

Adding a Simple, Movable Object

Next, add a simple entity (which has just a single shape). The geometry of the shape you add is used for both physics simulation and visualization. The simulation engine renders the physical shape by default if no detailed file mesh is supplied. This enables quick prototyping and does not affect the simulation fidelity unless you rely on advanced entities like simulated vision.

C#
 void AddBox(Vector3 position)
{
    Vector3 dimensions =
        new Vector3(0.2f, 0.2f, 0.2f); // meters

    // create simple movable entity, with a single shape
    SingleShapeEntity box = new SingleShapeEntity(
        new BoxShape(
            new BoxShapeProperties(
            100, // mass in kilograms.
            new Pose(), // relative pose
            dimensions)), // dimensions
        position);

    // mass or density can be specified.  No need to specify both
    box.State.MassDensity.Mass = 0;

    // Name the entity. All entities must have unique names
    box.State.Name = "box";

    // Insert entity in simulation.
    SimulationEngine.GlobalInstancePort.Insert(box);
}

The pre-defined entity, SingleShapeEntity, is a good starting point for adding objects to the simulation world. It assumes the entity is described by a single shape. Based on that assumption, SingleShapeEntity takes care of rendering the object and adding it to the physics simulation. You must specify the shape properties using one of the pre-defined shapes or one that derives from the Shape class defined in SimulationCommon.dll.

Some things to pay particular attention to include:

  • Shapes that have no mass or density specified will be static. They can not be moved and are assumed to have infinite mass.
  • Shapes are used to describe the entity to the physics engine. Rendering is decoupled from the physics geometry if a file-based mesh is supplied. More on that later.
  • The Pose class describes the position and orientation of an entity or shape. For shapes, it describes the relative position of the shape within an entity. Assume the entity center is (0,0,0) in entity coordinates, unless the center of mass parameter is set in the entity state.
  • All entities must have a unique name. In these tutorials, names are not qualified to make them unique since the total number of entities being added is known. But in large-scale simulations, always ensure no name conflicts occur. Duplicates are not allowed because entity discovery is done by name.

Adding a Mesh-Based, Textured Entity

The simulation engine makes it very easy to use detailed, photo-realistic visuals to represent entities in the world. All you have to supply is a file-based DirectX mesh file and (optionally) a pixel + vertex shader effect. You can supply a list of meshes for each physical shape in the entity. The engine takes care of rendering the meshes using the updated physics simulation properties for its shape (so the mesh will always be oriented and positioned properly). This makes it literally a "one line" for someone to start using nice visuals in the simulation. In the example below, a standard Directx9 mesh file is used and a 1.0 sphere is used to represent it to physics.

C#
 void AddTexturedSphere(Vector3 position)
{
    SingleShapeEntity entity = new SingleShapeEntity(
        new SphereShape(
            new SphereShapeProperties(10, // mass in kg
            new Pose(), // pose of shape within entity
            1)), //default radius
        position);

    entity.State.Assets.Mesh = "earth.obj";
    entity.SphereShape.SphereState.Material = new MaterialProperties("sphereMaterial", 0.5f, 0.4f, 0.5f);

    // Name the entity
    entity.State.Name = "detailed sphere";

    // Insert entity in simulation.
    SimulationEngine.GlobalInstancePort.Insert(entity);
}

Key points to focus on when using entities with file based mesh files:

  • All file paths specified in the Assets member of an entity state are assumed to reside in the store\Media directory. Only the filename is used, path will be ignored. This means you must copy all media, including textures referenced by the mesh file, to the store\Media directory.
  • When using a mesh, you can use advanced entities such as the TriangleMeshEnvironmentEntity or SimplifiedConvexMeshEnvironmentEntity to properly calculate physics shapes. More details on this in upcoming tutorials. Alternately, you can use a collection of simple shapes to approximate a complex mesh.

Step 4: Run the Tutorial

With the SimulationTutorial1.csproj loaded, compile and run. The visualization window should open, displaying a screen similar to the screenshots in the start of this tutorial.

Use the controls below to move around the simple world. Please refer to the simulation editor help file for more details. Be aware that the camera can go under the ground plane, which can be confusing.

Keyboard Controls

  • F1 - Hides help text.
  • F2 - Toggles display/rendering of the physics primitive visualization. Useful for debugging your physics geometry.
  • Camera Movement:

    • A - Strafe Left (lateral move left)
    • D - Strafe Right (lateral move right)
    • W - Move Forward
    • S - Move Backward
    • Q - Move Up on the Y-axis (vertically)
    • E - Move Down in the Y-axis (vertically)

Mouse Controls

Moving your mouse tilts and pans the camera perspective.

Xbox360 GamePad Controls

The left thumb stick controls the camera position. The right thumb stick tilts and pans the camera perspective.

Summary

 

 

© 2008 Microsoft Corporation. All Rights Reserved.

Page view tracker