public ScenarioTestResult(ScenarioIntermediaryTestResult i, Scenario scenario, HelicopterBase helicopter,
                                  GameTime gameTime, TestScenarioEndTrigger endTrigger)
        {
            Autopilot = new AutopilotConfiguration
                            {
                                MaxHVelocity = helicopter.Autopilot.MaxHVelocity,
                                PIDSetup = helicopter.Autopilot.PIDSetup.Clone()
                            };

            AvgEstimatedPositionError = i.AccEstimatedPositionError/i.UpdateCount;
            AvgHeightAboveGround = i.AccHeightAboveGround/i.UpdateCount;
            AvgVelocity = i.AccVelocity/i.UpdateCount;
            Duration = gameTime.TotalGameTime - i.StartTime;
            EndTrigger = endTrigger;
            FlightLog = new List<HelicopterLogSnapshot>(helicopter.Log);
            MaxEstimatedPositionError = i.MaxEstimatedPositionError;
            MaxHeightAboveGround = i.MaxHeightAboveGround;
            MaxVelocity = i.MaxVelocity;
            MinEstimatedPositionError = i.MinEstimatedPositionError;
            MinHeightAboveGround = i.MinHeightAboveGround;
            Scenario = scenario;

            Sensors = new SensorSpecifications
                          {
                              AccelerometerStdDev = DefaultAutopilotConfiguration.AccelerometerStdDev,
                              GPSVelocityStdDev = DefaultAutopilotConfiguration.GPSVelocityStdDev,
                              GPSPositionStdDev = DefaultAutopilotConfiguration.GPSPositionStdDev
                          };
        }
        private static Scenario ParseScenario(XmlNode scenarioNode)
        {
            var scenario = new Scenario();
            scenario.Name = scenarioNode.GetAttribute("Name");
            scenario.BackgroundMusic = ParseBackgroundMusic(scenarioNode.SelectSingleNode("BackgroundMusic"));
            scenario.SceneElements = ParseSceneElements(scenarioNode.SelectSingleNode("Scene"));
            scenario.CameraType = ParseCameraType(scenarioNode.SelectSingleNode("CameraType"));
            scenario.Timeout = ParseTimeout(scenarioNode.SelectSingleNode("TimeoutSeconds"));

            XmlNode terrainInfoNode = scenarioNode.SelectSingleNode("Scene").SelectSingleNode("Terrain");
            if (terrainInfoNode != null)
                scenario.TerrainInfo = ParseTerrainInfo(terrainInfoNode);

            scenario.HelicopterScenarios = ParseHelicopterScenario(scenarioNode);
            return scenario;
        }
        private void NextTestScenario()
        {
            if (!IsTestMode)
                return;

            // Proceed to next test scenario since we have tested all velocities at the current test scenario
            _testScenarioIter.MoveNext();
            _scenario = _testScenarioIter.Current;

            // Start over on the set of maxHVelocities to test
            _testMaxHVelocityIter = _testConfiguration.MaxHVelocities.GetEnumerator();
            _testMaxHVelocityIter.MoveNext();

            if (_scenario != null)
                Debug.WriteLine("Progressing to next scenario " + _scenario.Name + " at maxHVelocity " +
                                _testMaxHVelocityIter.Current + ".");
            else
                Debug.WriteLine("Completed all test scenarios!");
        }
        private NavigationMap UpdateTerrain(Scenario scenario)
        {
            if (scenario.SceneElements.Contains("Terrain"))
            {
                // Build terrain and derive a heightmap from it
                TerrainInfo ti = scenario.TerrainInfo;
                _terrain.BuildTerrain(ti.Width, ti.MinHeight, ti.MaxHeight);
                _heightmap = new NavigationMap(HeightmapToValues(_terrain.Mesh.Heightmap));
            }
            else
            {
                // Assume flat ground if not using terrain
                _heightmap = new NavigationMap(new [,]
                                                   {
                                                       {0f, 0f,},
                                                       {0f, 0f,},
                                                   });
            }

            return _heightmap;
        }
        /// <summary>
        ///   Allows the game to perform any initialization it needs to before starting to run.
        ///   This is where it can query for any required services and load any non-graphic
        ///   related content.  Calling base.Initialize will enumerate through any components
        ///   and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            _basicEffect = CreateBasicEffect(this);

            #region Load scenario / test scenarios

            _testMaxHVelocityIter = _testConfiguration.MaxHVelocities.GetEnumerator();
            if (!_testMaxHVelocityIter.MoveNext())
                throw new Exception("No maxHVelocities defined in _testConfiguration.");

            _testScenarioIter = _testConfiguration.TestScenarios.GetEnumerator();

            if (IsTestMode)
                NextTestScenario();
            else
            {
                _testScenarioIter.MoveNext();
                _scenario = _testScenarioIter.Current;
            }

            if (_scenario == null)
                throw new Exception("Could not load scenario from XML.");

            #endregion

            #region Cameras

            // We must create a dummy camera target until the helicopter instance is created, to avoid exceptions
            var cameraOffset = new Vector3(0.0f, 0.5f, -0.5f);
            var startPos = _scenario.HelicopterScenarios[0].StartPosition + cameraOffset;
            _cockpitMesh = new SimpleModel("Models/apache-cockpit", this, this);
            InitCamera(MyCameraType, startPos + new Vector3(0, 0.5f, 4), new WorldDummy(Vector3.Zero));

            #endregion

            #region Sunlight, skydome, terrain and trees

            // Initialize skydome and sunlight parameters
            _skydome = new SkydomeComponent(this, this);
            _terrain = new TerrainComponent(this, this, _skydome.Parameters);

            UpdateTerrain(_scenario);
            

            // Initialize trees
            // TODO Forest component does not support dynamic loading/unloading of components yet
            if (_scenario.SceneElements.Contains("Forest"))
                _forest = new Forest(this, this, _terrain.Mesh, _skydome.Parameters);

            #endregion

            #region Misc components

            _fpsUtil = new FPS(this);
            _barrels = GetBarrels();
            _texturedGround = new FlatTexturedGround(this, this);

            _currentWaypoint = new WaypointMesh(this, this);
            _currentWaypoint.Position = new Vector3(0, 1, 0);


            #endregion

            #region Physics

            _terrainCollision = new TerrainCollision(this, this);

            // We implemented our own crash detection for whenever Jitter is disabled
            _terrainCollision.SetHeightValues(_heightmap.HeightValues);

            #endregion

            #region Helicopters

            
            // Initialize helicopter(s)
            InitHelicopters(_skydome.Parameters, _heightmap);
            Camera.LookAtTarget = _helicopter;
            _terrainCollision.Helicopter = _helicopter; // TODO Clean this up, non-intuitive usage
            _helicopter.Crashed += HelicopterCrashEventHandler;

            #endregion

            #region Test scenario results

            if (IsTestMode)
            {
                _testResults = new Dictionary<string, List<ScenarioTestResult>>();
            }

            #endregion


            // Add game components to the game loop
            AddGameComponents();

            Reset();

            base.Initialize();
        }