unity/Assets/Scripts/Logic/InteractiveLogic.cs (211 lines of code) (raw):

using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using Google.Protobuf; using UnityEngine; // This is the main part of the standalone renderer. This script loads // the scene, sets up the server or the interactive mode. public class InteractiveLogic : MonoBehaviour { enum State { Init, MainLoop, Failed, Finished }; public enum Mode { Interactive, Server }; [SerializeField] public SceneManager scene_manager_ = null; [SerializeField] public RenderServer render_server_ = null; [SerializeField] public Recorder recorder_ = null; [SerializeField] [Flag] public Mode mode_ = Mode.Interactive; // The renderer components config file location. [SerializeField] [Flag] public string renderer_config_path_ = null; // The MuJoCo XML scene file location. [SerializeField] [Flag] public string model_xml_path_ = null; // The joint name to qpos index mapping file location. [SerializeField] [Flag] public string model_mapping_path_ = null; // The state data (qposes and images) location for interactive mode. [SerializeField] [Flag] public string model_state_path_ = null; // Assets basedir, used to resolve relative resource paths. [SerializeField] [Flag] public string asset_basedir_ = "."; // Process id of the parent process. Used to shutdown when parent is dead. [SerializeField] [Flag] public int parent_pid_ = -1; private State current_state_ = State.Init; private SceneInstance local_scene_instance_ = null; private List<Camera> scene_cameras_ = new List<Camera>(); private int current_camera_ = 0; private bool show_ui_ = true; private bool anchor_left_ = true; private string config_save_path_ = "config.json"; void Start() { Flags.InitFlags(this, "main"); renderer_config_path_ = ConfigUtils.ResolveFile(asset_basedir_, renderer_config_path_); model_mapping_path_ = ConfigUtils.ResolveFile(asset_basedir_, model_mapping_path_); model_state_path_ = ConfigUtils.ResolveFile(asset_basedir_, model_state_path_); config_save_path_ = string.Format("{0}.new", renderer_config_path_); } void Update() { switch (current_state_) { case State.Init: current_state_ = State.MainLoop; local_scene_instance_ = scene_manager_.CreateSceneInstance(); Orrb.RendererConfig renderer_config = LoadConfig(renderer_config_path_); // If the renderer config contains model and mapping paths, use them. if (renderer_config.ModelXmlPath.Length > 0) { model_xml_path_ = renderer_config.ModelXmlPath; } if (renderer_config.ModelMappingPath.Length > 0) { model_mapping_path_ = renderer_config.ModelMappingPath; } local_scene_instance_.Initialize(model_xml_path_, model_mapping_path_, asset_basedir_); foreach (Orrb.RendererComponent renderer_component in renderer_config.Components) { local_scene_instance_.GetComponentManager().AddComponent( renderer_component.Type, renderer_component.Name, renderer_component.Path, renderer_component.Config, mode_ == Mode.Server // Enable by default in server mode. ); } if (mode_ == Mode.Server) { // In server mode: resize the useless window, start the GRPC // server and turn on capture. Screen.SetResolution(50, 50, false); render_server_.Initialize(recorder_, local_scene_instance_); recorder_.Initialize(render_server_); } else { // In interactive mode: load state from files, set up active // cameras. local_scene_instance_.GetStateLoader().InitializeStateStream(model_state_path_); scene_cameras_ = local_scene_instance_.GetCameras(); ToggleCamera(current_camera_); } if (parent_pid_ != -1) { // If parent pid was provided start a parent watchdog coroutine. StartCoroutine(ParentProcessWatch()); } break; case State.MainLoop: default: if (mode_ == Mode.Server) { render_server_.ProcessRequests(); } else { local_scene_instance_.GetComponentManager().RunComponents(new RendererComponent.NullOutputContext()); } break; } } // This coroutine keeps track of the parent process. If the parent is // dead it will stop the standalone renderer. private IEnumerator ParentProcessWatch() { Process parent = null; try { parent = Process.GetProcessById(parent_pid_); } catch (Exception e) { Logger.Error("Exception geting parent process: {0}, {1}.", parent_pid_, e.Message); Application.Quit(); } if (parent == null) { Logger.Error("Parent process is null: {0}.", parent_pid_); Application.Quit(); } Logger.Info("Starting parent process watchdog: {0}.", parent_pid_); while (true) { yield return new WaitForSecondsRealtime(3); if (parent.HasExited) { Logger.Info("Parent has exited, quitting."); Application.Quit(); yield break; } } } private Orrb.RendererConfig LoadConfig(string path) { return Orrb.RendererConfig.Parser.ParseJson(File.ReadAllText(path)); } private static Orrb.RendererComponentConfig ParseConfig(string config) { return Orrb.RendererComponentConfig.Parser.ParseJson(config.Replace('\'', '"')); } // Loop through cameras, disable all but one selected. private void ToggleCamera(int new_camera) { foreach (Camera scene_camera in scene_cameras_) { scene_camera.enabled = false; } current_camera_ = new_camera; scene_cameras_[current_camera_].enabled = true; } // Make the previous camera active, in interactive mode. private void PreviousCamera() { if (scene_cameras_.Count == 0) { return; } current_camera_ = (current_camera_ + scene_cameras_.Count - 1) % scene_cameras_.Count; ToggleCamera(current_camera_); } // Make the next camera active, in interactive mode. private void NextCamera() { if (scene_cameras_.Count == 0) { return; } current_camera_ = (current_camera_ + 1) % scene_cameras_.Count; ToggleCamera(current_camera_); } void OnGUI() { if (current_state_ != State.MainLoop || mode_ == Mode.Server) { return; } GUI.skin.toggle.fontSize = 12; GUI.skin.label.fontSize = 12; local_scene_instance_.GetComponentManager().DrawSceneGUI(); local_scene_instance_.GetStateLoader().DrawSceneGUI(); GUILayout.BeginArea(new Rect(anchor_left_ ? 10 : Screen.width - 410, 10, 400, Screen.height - 20)); GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); if (!anchor_left_) { GUILayout.FlexibleSpace(); } if (GUILayout.Button(show_ui_ ? "-" : "+", GUILayout.Width(20))) { show_ui_ = !show_ui_; } if (GUILayout.Button(anchor_left_ ? ">" : "<", GUILayout.Width(20))) { anchor_left_ = !anchor_left_; } if (anchor_left_) { GUILayout.FlexibleSpace(); } GUILayout.EndHorizontal(); GUILayout.Space(3); if (show_ui_) { GUILayout.BeginHorizontal(); config_save_path_ = GUILayout.TextField(config_save_path_, GUILayout.Width(310)); if (GUILayout.Button("Save config", GUILayout.Width(80))) { Orrb.RendererConfig config = local_scene_instance_.GetComponentManager().GetConfig(); JsonFormatter formatter = new JsonFormatter(JsonFormatter.Settings.Default); File.WriteAllText(config_save_path_, formatter.Format(config)); } GUILayout.EndHorizontal(); GUILayout.Space(3); GUILayout.BeginHorizontal(); if (GUILayout.Button(" < ", GUILayout.Width(20))) { PreviousCamera(); } if (GUILayout.Button(" > ", GUILayout.Width(20))) { NextCamera(); } GUILayout.Space(10); GUILayout.Label(scene_cameras_.Count > current_camera_ ? scene_cameras_[current_camera_].name : "-", GUILayout.Width(300)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(3); local_scene_instance_.GetStateLoader().DrawEditorGUI(); GUILayout.Space(3); local_scene_instance_.GetComponentManager().DrawEditorGUI(); } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.EndArea(); } }