unity/Assets/Scripts/Components/CameraCalibrator.cs (157 lines of code) (raw):

using System; using System.IO; using UnityEngine; // The CameraCalibrator is a interactive mode component used to match the parameters // of the virtual cameras with their real world counterparts. When turned on the // calibrator allows to locally translate (camera dolly), rotate (euler) and modify // the field of view. If a real data set is loaded the camera overlay can be used to // visually align the two sources (sim and real). Finally the local transformations can // be colapsed and new position, rotation and fov values for the camera retreived. // // Configurable properties: // string camera_name - which camera does this calibrator modify, // vector3 local_position_delta - local translation to be applied, // quaternion local_rotation_delta - local rotation to be applied, // float fov_delta - field of view change to be applied. // // Read-only properties: // string mujoco_position - mujoco xml position vector as string, // string mujoco_rotation - mujoco xml rotation quaternion as string, // string mujoco_fov - mujoco xml fov as string, // string dactyl_camera_setup - full camera config in json. public class CameraCalibrator : RendererComponent { private Camera camera_ = null; private Vector3 original_position_ = Vector3.zero; private Quaternion original_rotation_ = Quaternion.identity; private float original_fov_ = 0.0f; private float dolly_x_ = 0.0f; private float dolly_y_ = 0.0f; private float dolly_z_ = 0.0f; private float euler_x_ = 0.0f; private float euler_y_ = 0.0f; private float euler_z_ = 0.0f; private float zoom_ = 0.0f; [SerializeField] [ConfigProperty] public string camera_name_ = ""; [SerializeField] [ConfigProperty] public Vector3 local_position_delta_ = Vector3.zero; [SerializeField] [ConfigProperty] public Quaternion local_rotation_delta_ = Quaternion.identity; [SerializeField] [ConfigProperty] public float fov_delta_ = 0.0f; // Cache the original position, rotation and fov. private void UpdateCamera() { Camera[] child_cameras = GetComponentsInChildren<Camera>(); foreach (Camera child_camera in child_cameras) { if (child_camera.name.Equals(camera_name_)) { camera_ = child_camera; original_fov_ = camera_.fieldOfView; original_rotation_ = camera_.transform.rotation; original_position_ = camera_.transform.position; } } } public override bool InitializeComponent(Orrb.RendererComponentConfig config) { camera_name_ = ConfigUtils.GetProperty("camera_name", config, camera_name_); UpdateCamera(); return UpdateComponent(config); } public override bool UpdateComponent(Orrb.RendererComponentConfig config) { string old_camera_name = camera_name_; ConfigUtils.GetProperties(this, config); if (!camera_name_.Equals(old_camera_name)) { UpdateCamera(); } return true; } public override bool RunComponent(RendererComponent.IOutputContext context) { if (camera_ != null) { // Apply the local transformations on top of the cached original position, // rotation and fov. Vector3 dolly = dolly_x_ * camera_.transform.right + dolly_y_ * camera_.transform.up + dolly_z_ * camera_.transform.forward; camera_.transform.position = original_position_ + local_position_delta_ + dolly; camera_.transform.rotation = original_rotation_ * local_rotation_delta_ * Quaternion.Euler( euler_x_, euler_y_, euler_z_); camera_.fieldOfView = original_fov_ + fov_delta_ + zoom_; } return true; } public override Orrb.RendererComponentConfig GetConfig() { Orrb.RendererComponentConfig config = base.GetConfig(); ConfigUtils.SetProperty("mujoco_position", config, GetCameraPositionString()); ConfigUtils.SetProperty("mujoco_rotation", config, GetCameraRotationString()); ConfigUtils.SetProperty("mujoco_fov", config, GetCameraFovString()); ConfigUtils.SetProperty("dactyl_camera_setup", config, GetDactylCameraSetupString()); return config; } private string GetCameraPositionString() { if (camera_ == null) { return ""; } return string.Format("{0} {1} {2}", camera_.transform.localPosition.x, camera_.transform.localPosition.y, camera_.transform.localPosition.z); } private string GetDactylCameraSetupString() { if (camera_ == null) { return ""; } Vector3 position = camera_.transform.localPosition; Quaternion old_rotation = camera_.transform.localRotation; camera_.transform.LookAt(camera_.transform.position + camera_.transform.TransformDirection(Vector3.back), camera_.transform.TransformDirection(Vector3.up)); Quaternion rotation = camera_.transform.localRotation; camera_.transform.localRotation = old_rotation; return string.Format("{{'name': '{0}', 'pos': [{1}, {2}, {3}], 'quat': [{4}, {5}, {6}, {7}], 'fovy': {8}}}", camera_.name, position.x, position.y, position.z, rotation.w, rotation.x, rotation.y, rotation.z, camera_.fieldOfView); } private string GetCameraRotationString() { if (camera_ == null) { return ""; } Quaternion old_rotation = camera_.transform.localRotation; camera_.transform.LookAt(camera_.transform.position + camera_.transform.TransformDirection(Vector3.back), camera_.transform.TransformDirection(Vector3.up)); Quaternion local_mujoco_rotation = camera_.transform.localRotation; camera_.transform.localRotation = old_rotation; return string.Format("{0} {1} {2} {3}", local_mujoco_rotation.w, local_mujoco_rotation.x, local_mujoco_rotation.y, local_mujoco_rotation.z); } private string GetCameraFovString() { if (camera_ == null) { return ""; } return string.Format("{0}", camera_.fieldOfView); } private void Colapse() { Vector3 dolly = dolly_x_ * camera_.transform.right + dolly_y_ * camera_.transform.up + dolly_z_ * camera_.transform.forward; local_position_delta_ += dolly; local_rotation_delta_ *= Quaternion.Euler(euler_x_, euler_y_, euler_z_); fov_delta_ += zoom_; dolly_x_ = dolly_y_ = dolly_z_ = euler_x_ = euler_y_ = euler_z_ = zoom_ = 0.0f; } private void Reset() { local_position_delta_ = Vector3.zero; local_rotation_delta_ = Quaternion.identity; fov_delta_ = 0.0f; dolly_x_ = dolly_y_ = dolly_z_ = euler_x_ = euler_y_ = euler_z_ = zoom_ = 0.0f; } public override void DrawEditorGUI() { GUILayout.BeginVertical(); RendererComponent.GUIField("camera_name", ref camera_name_); string label_text = GetCameraPositionString(); RendererComponent.GUIField("mujoco_position", ref label_text); label_text = GetCameraRotationString(); RendererComponent.GUIField("mujoco_rotation", ref label_text); label_text = GetCameraFovString(); RendererComponent.GUIField("mujoco_fov", ref label_text); RendererComponent.GUIHorizontalLine(1); RendererComponent.GUIVector3("local_position_delta", ref local_position_delta_); RendererComponent.GUIQuaternion("local_rotation_delta", ref local_rotation_delta_); RendererComponent.GUIHorizontalLine(1); RendererComponent.GUISlider("dolly_x", ref dolly_x_, -0.03f, 0.03f); RendererComponent.GUISlider("dolly_y", ref dolly_y_, -0.03f, 0.03f); RendererComponent.GUISlider("dolly_z", ref dolly_z_, -0.03f, 0.03f); RendererComponent.GUIHorizontalLine(1); RendererComponent.GUISlider("euler_x", ref euler_x_, -2.0f, 2.0f); RendererComponent.GUISlider("euler_y", ref euler_y_, -2.0f, 2.0f); RendererComponent.GUISlider("euler_z", ref euler_z_, -2.0f, 2.0f); RendererComponent.GUIHorizontalLine(1); RendererComponent.GUISlider("zoom", ref zoom_, -1f, 1f); RendererComponent.GUIHorizontalLine(1); GUILayout.BeginHorizontal(); if (RendererComponent.GUIButton("Colapse")) { Colapse(); } if (RendererComponent.GUIButton("Reset")) { Reset(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); } }