private static void PopulateBlueBalloon(XmlDocument xmlDoc, XmlNode parentNode, BlueBalloonConfig c)
        {
            // Create "BlueBalloon" node and append to parentNode
            XmlNode node = xmlDoc.CreateElement("BlueBalloon");

            parentNode.AppendChild(node);

            // Add attributes
            AddAttribute(xmlDoc, node, "id", c.id.ToString());
            AddOptionalAttribute(xmlDoc, node, "sensorBeamwidth_deg", c.sensorBeamwidth_deg);
            AddAttribute(xmlDoc, node, "teleportLoop", c.teleportLoop.ToString());

            // Add waypoints
            foreach (PrimitivePair <float, float> waypoint in c.waypoints_km)
            {
                XmlNode waypointNode = xmlDoc.CreateElement("Waypoint");
                node.AppendChild(waypointNode);
                AddAttribute(xmlDoc, waypointNode, "x_km", waypoint.first.ToString());
                AddAttribute(xmlDoc, waypointNode, "z_km", waypoint.second.ToString());
            }

            // Add perception override (if specified)
            AddPerceptionOverride(xmlDoc, node, c);
        }
        // Remote platform category parsing
        private static void ParseRemote(XmlNode node, SoaConfig soaConfig)
        {
            PlatformConfig newConfig = null; // Dummy value
            bool           newConfigValid;

            // Go through each child node
            foreach (XmlNode c in node.ChildNodes)
            {
                newConfigValid = true;

                try
                {
                    switch (c.Name)
                    {
                    case "HeavyUAV":
                    {
                        newConfig = new HeavyUAVConfig(
                            GetFloatAttribute(c, "x_km", 0),
                            GetFloatAttribute(c, "y_km", 0),
                            GetFloatAttribute(c, "z_km", 0),
                            GetIntAttribute(c, "id", -1),         // Default -1 means runtime determined id field
                            GetOptionalFloatAttribute(c, "sensorBeamwidth_deg"),
                            GetOptionalFloatAttribute(c, "commsRange_km"),
                            GetOptionalFloatAttribute(c, "fuelTankSize_s"),
                            GetOptionalIntAttribute(c, "numStorageSlots")
                            );
                    }
                    break;

                    case "SmallUAV":
                    {
                        newConfig = new SmallUAVConfig(
                            GetFloatAttribute(c, "x_km", 0),
                            GetFloatAttribute(c, "y_km", 0),
                            GetFloatAttribute(c, "z_km", 0),
                            GetIntAttribute(c, "id", -1),         // Default -1 means runtime determined id field
                            GetOptionalFloatAttribute(c, "sensorBeamwidth_deg"),
                            GetOptionalFloatAttribute(c, "commsRange_km"),
                            GetOptionalFloatAttribute(c, "fuelTankSize_s")
                            );
                    }
                    break;

                    case "BlueBalloon":
                    {
                        // Get list of waypoints
                        List <PrimitivePair <float, float> > waypoints_km = new List <PrimitivePair <float, float> >();
                        foreach (XmlNode g in c.ChildNodes)
                        {
                            switch (g.Name)
                            {
                            case "Waypoint":
                                waypoints_km.Add(new PrimitivePair <float, float>(GetFloatAttribute(g, "x_km", 0), GetFloatAttribute(g, "z_km", 0)));
                                break;
                            }
                        }

                        // Create a Blue Balloon config
                        newConfig = new BlueBalloonConfig(
                            GetIntAttribute(c, "id", -1),         // Default -1 means runtime determined id field
                            GetOptionalFloatAttribute(c, "sensorBeamwidth_deg"),
                            waypoints_km,
                            GetBooleanAttribute(c, "teleportLoop", true)
                            );
                    }
                    break;

                    default:
                        newConfigValid = false;
                        if (c.Name != "#comment")
                        {
                            Debug.LogWarning("SoaConfigXMLReader::ParseRemote(): Unrecognized node " + c.Name);
                        }
                        break;
                    }
                }
                catch (Exception)
                {
                    Debug.LogError("SoaConfigXMLReader::ParseRemote(): Error parsing " + c.Name);
                } // End try-catch

                // Handle and add the new config if it is valid
                if (newConfigValid)
                {
                    // Parse any sensor/classifier override modalities specified
                    foreach (XmlNode g in c.ChildNodes)
                    {
                        switch (g.Name)
                        {
                        case "Sensor":
                            newConfig.SetSensorModalities(ParseModalities(g));
                            break;

                        case "Classifier":
                            newConfig.SetClassifierModalities(ParseModalities(g));
                            break;
                        }
                    }

                    // Add to list of remote platforms
                    soaConfig.remotePlatforms.Add(newConfig);
                } // End if new config valid
            }     // End foreach
        }