예제 #1
0
        public static void StartAsync(SimulationModel simulation)
        {
            Debug.Assert(Instance.CurrentSimulation == null);

            Instance.Actions.Enqueue(() =>
            {
                using (var db = DatabaseManager.Open())
                {
                    AssetBundle textureBundle = null;
                    AssetBundle mapBundle     = null;
                    try
                    {
                        if (Config.Headless && (simulation.Headless.HasValue && !simulation.Headless.Value))
                        {
                            throw new Exception("Simulator is configured to run in headless mode, only headless simulations are allowed");
                        }

                        simulation.Status = "Starting";
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                        Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.PROGRESS);

                        Instance.SimConfig = new SimulationConfig()
                        {
                            Name           = simulation.Name,
                            Clusters       = db.Single <ClusterModel>(simulation.Cluster).Ips.Split(',').Where(c => c != "127.0.0.1").ToArray(),
                            ClusterName    = db.Single <ClusterModel>(simulation.Cluster).Name,
                            ApiOnly        = simulation.ApiOnly.GetValueOrDefault(),
                            Headless       = simulation.Headless.GetValueOrDefault(),
                            Interactive    = simulation.Interactive.GetValueOrDefault(),
                            TimeOfDay      = simulation.TimeOfDay.GetValueOrDefault(new DateTime(1980, 3, 24, 12, 0, 0)),
                            Rain           = simulation.Rain.GetValueOrDefault(),
                            Fog            = simulation.Fog.GetValueOrDefault(),
                            Wetness        = simulation.Wetness.GetValueOrDefault(),
                            Cloudiness     = simulation.Cloudiness.GetValueOrDefault(),
                            UseTraffic     = simulation.UseTraffic.GetValueOrDefault(),
                            UsePedestrians = simulation.UsePedestrians.GetValueOrDefault(),
                            Seed           = simulation.Seed,
                        };

                        if (simulation.Vehicles == null || simulation.Vehicles.Length == 0 || simulation.ApiOnly.GetValueOrDefault())
                        {
                            Instance.SimConfig.Agents = Array.Empty <AgentConfig>();
                        }
                        else
                        {
                            Instance.SimConfig.Agents = simulation.Vehicles.Select(v =>
                            {
                                var vehicle = db.SingleOrDefault <VehicleModel>(v.Vehicle);

                                var config = new AgentConfig()
                                {
                                    Name        = vehicle.Name,
                                    Url         = vehicle.Url,
                                    AssetBundle = vehicle.LocalPath,
                                    Connection  = v.Connection,
                                    Sensors     = vehicle.Sensors,
                                };

                                if (!string.IsNullOrEmpty(vehicle.BridgeType))
                                {
                                    config.Bridge = Config.Bridges.Find(bridge => bridge.Name == vehicle.BridgeType);
                                    if (config.Bridge == null)
                                    {
                                        throw new Exception($"Bridge {vehicle.BridgeType} not found");
                                    }
                                }

                                return(config);
                            }).ToArray();
                        }

                        // load environment
                        if (Instance.SimConfig.ApiOnly)
                        {
                            var api  = Instantiate(Instance.ApiManagerPrefab);
                            api.name = "ApiManager";

                            Instance.CurrentSimulation = simulation;

                            // ready to go!
                            Instance.CurrentSimulation.Status = "Running";
                            NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);

                            Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.READY);
                        }
                        else
                        {
                            var mapModel      = db.Single <MapModel>(simulation.Map);
                            var mapBundlePath = mapModel.LocalPath;
                            mapBundle         = null;
                            textureBundle     = null;

                            ZipFile zip = new ZipFile(mapBundlePath);
                            {
                                string manfile;
                                ZipEntry entry = zip.GetEntry("manifest");
                                using (var ms = zip.GetInputStream(entry))
                                {
                                    int streamSize = (int)entry.Size;
                                    byte[] buffer  = new byte[streamSize];
                                    streamSize     = ms.Read(buffer, 0, streamSize);
                                    manfile        = Encoding.UTF8.GetString(buffer);
                                }

                                Manifest manifest = new Deserializer().Deserialize <Manifest>(manfile);

                                if (manifest.bundleFormat != BundleConfig.MapBundleFormatVersion)
                                {
                                    zip.Close();

                                    // TODO: proper exception
                                    throw new ZipException("BundleFormat version mismatch");
                                }

                                if (zip.FindEntry($"{manifest.bundleGuid}_environment_textures", false) != -1)
                                {
                                    var texStream = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_environment_textures"));
                                    textureBundle = AssetBundle.LoadFromStream(texStream, 0, 1 << 20);
                                }

                                string platform = SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows ? "windows" : "linux";
                                var mapStream   = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_environment_main_{platform}"));
                                mapBundle       = AssetBundle.LoadFromStream(mapStream, 0, 1 << 20);

                                if (mapBundle == null)
                                {
                                    throw new Exception($"Failed to load environment from '{mapModel.Name}' asset bundle");
                                }

                                textureBundle?.LoadAllAssets();

                                var scenes = mapBundle.GetAllScenePaths();
                                if (scenes.Length != 1)
                                {
                                    throw new Exception($"Unsupported environment in '{mapModel.Name}' asset bundle, only 1 scene expected");
                                }

                                var sceneName = Path.GetFileNameWithoutExtension(scenes[0]);
                                Instance.SimConfig.MapName = sceneName;
                                Instance.SimConfig.MapUrl  = mapModel.Url;

                                var isMasterSimulation = Instance.SimConfig.Clusters.Length > 0;
                                var loader             =
                                    SceneManager.LoadSceneAsync(sceneName,
                                                                isMasterSimulation? LoadSceneMode.Additive : LoadSceneMode.Single);
                                loader.completed += op =>
                                {
                                    if (op.isDone)
                                    {
                                        if (isMasterSimulation)
                                        {
                                            SceneManager.SetActiveScene(SceneManager.GetSceneByName(sceneName));
                                        }
                                        textureBundle?.Unload(false);
                                        mapBundle.Unload(false);
                                        zip.Close();
                                        SetupScene(simulation);
                                    }
                                };
                            }
                        }
                    }
                    catch (ZipException ex)
                    {
                        Debug.Log($"Failed to start '{simulation.Name}' simulation");
                        Debug.LogException(ex);

                        // NOTE: In case of failure we have to update Simulation state
                        simulation.Status = "Invalid";
                        simulation.Error  = "Out of date Map AssetBundle. Please check content website for updated bundle or rebuild the bundle.";
                        db.Update(simulation);

                        if (SceneManager.GetActiveScene().name != Instance.LoaderScene)
                        {
                            SceneManager.LoadScene(Instance.LoaderScene);
                        }

                        textureBundle?.Unload(false);
                        mapBundle?.Unload(false);
                        AssetBundle.UnloadAllAssetBundles(true);
                        Instance.CurrentSimulation = null;

                        // TODO: take ex.Message and append it to response here
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                    }
                    catch (Exception ex)
                    {
                        Debug.Log($"Failed to start '{simulation.Name}' simulation");
                        Debug.LogException(ex);

                        // NOTE: In case of failure we have to update Simulation state
                        simulation.Status = "Invalid";
                        simulation.Error  = ex.Message;
                        db.Update(simulation);

                        if (SceneManager.GetActiveScene().name != Instance.LoaderScene)
                        {
                            SceneManager.LoadScene(Instance.LoaderScene);
                        }

                        textureBundle?.Unload(false);
                        mapBundle?.Unload(false);
                        AssetBundle.UnloadAllAssetBundles(true);
                        Instance.CurrentSimulation = null;

                        // TODO: take ex.Message and append it to response here
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                    }
                }
            });
        }
예제 #2
0
        public static void StartAsync(SimulationModel simulation)
        {
            Debug.Assert(Instance.CurrentSimulation == null);

            Instance.Actions.Enqueue(() =>
            {
                using (var db = DatabaseManager.Open())
                {
                    AssetBundle mapBundle = null;
                    try
                    {
                        if (Config.Headless && (simulation.Headless.HasValue && !simulation.Headless.Value))
                        {
                            throw new Exception("Simulator is configured to run in headless mode, only headless simulations are allowed");
                        }

                        simulation.Status = "Starting";
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                        Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.PROGRESS);

                        Instance.SimConfig = new SimulationConfig()
                        {
                            Name           = simulation.Name,
                            Clusters       = db.Single <ClusterModel>(simulation.Cluster).Ips.Split(',').Where(c => c != "127.0.0.1").ToArray(),
                            ClusterName    = db.Single <ClusterModel>(simulation.Cluster).Name,
                            ApiOnly        = simulation.ApiOnly.GetValueOrDefault(),
                            Headless       = simulation.Headless.GetValueOrDefault(),
                            Interactive    = simulation.Interactive.GetValueOrDefault(),
                            TimeOfDay      = simulation.TimeOfDay.GetValueOrDefault(DateTime.MinValue.AddHours(12)),
                            Rain           = simulation.Rain.GetValueOrDefault(),
                            Fog            = simulation.Fog.GetValueOrDefault(),
                            Wetness        = simulation.Wetness.GetValueOrDefault(),
                            Cloudiness     = simulation.Cloudiness.GetValueOrDefault(),
                            UseTraffic     = simulation.UseTraffic.GetValueOrDefault(),
                            UsePedestrians = simulation.UsePedestrians.GetValueOrDefault(),
                            Seed           = simulation.Seed,
                        };

                        if (simulation.Vehicles == null || simulation.Vehicles.Length == 0 || simulation.ApiOnly.GetValueOrDefault())
                        {
                            Instance.SimConfig.Agents = Array.Empty <AgentConfig>();
                        }
                        else
                        {
                            Instance.SimConfig.Agents = simulation.Vehicles.Select(v =>
                            {
                                var vehicle = db.SingleOrDefault <VehicleModel>(v.Vehicle);

                                var config = new AgentConfig()
                                {
                                    Name        = vehicle.Name,
                                    AssetBundle = vehicle.LocalPath,
                                    Connection  = v.Connection,
                                    Sensors     = vehicle.Sensors,
                                };

                                if (!string.IsNullOrEmpty(vehicle.BridgeType))
                                {
                                    config.Bridge = Config.Bridges.Find(bridge => bridge.Name == vehicle.BridgeType);
                                    if (config.Bridge == null)
                                    {
                                        throw new Exception($"Bridge {vehicle.BridgeType} not found");
                                    }
                                }

                                return(config);
                            }).ToArray();
                        }

                        // load environment
                        if (Instance.SimConfig.ApiOnly)
                        {
                            var api  = Instantiate(Instance.ApiManagerPrefab);
                            api.name = "ApiManager";

                            Instance.CurrentSimulation = simulation;

                            // ready to go!
                            Instance.CurrentSimulation.Status = "Running";
                            NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);

                            Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.READY);
                        }
                        else
                        {
                            var mapModel      = db.Single <MapModel>(simulation.Map);
                            var mapBundlePath = mapModel.LocalPath;

                            // TODO: make this async
                            mapBundle = AssetBundle.LoadFromFile(mapBundlePath);
                            if (mapBundle == null)
                            {
                                throw new Exception($"Failed to load environment from '{mapModel.Name}' asset bundle");
                            }

                            var scenes = mapBundle.GetAllScenePaths();
                            if (scenes.Length != 1)
                            {
                                throw new Exception($"Unsupported environment in '{mapModel.Name}' asset bundle, only 1 scene expected");
                            }

                            var sceneName = Path.GetFileNameWithoutExtension(scenes[0]);
                            Instance.SimConfig.MapName = sceneName;

                            var loader        = SceneManager.LoadSceneAsync(sceneName);
                            loader.completed += op =>
                            {
                                if (op.isDone)
                                {
                                    mapBundle.Unload(false);
                                    SetupScene(simulation);
                                }
                            };
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.Log($"Failed to start '{simulation.Name}' simulation");
                        Debug.LogException(ex);

                        // NOTE: In case of failure we have to update Simulation state
                        simulation.Status = "Invalid";
                        db.Update(simulation);

                        if (SceneManager.GetActiveScene().name != Instance.LoaderScene)
                        {
                            SceneManager.LoadScene(Instance.LoaderScene);
                        }
                        mapBundle?.Unload(false);
                        AssetBundle.UnloadAllAssetBundles(true);
                        Instance.CurrentSimulation = null;

                        // TODO: take ex.Message and append it to response here
                        NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner);
                    }
                }
            });
        }