From e73f5c559221891384a23aa9dd63cd693577362e Mon Sep 17 00:00:00 2001 From: Kenneth Yang Date: Wed, 27 Mar 2024 12:54:49 -0700 Subject: [PATCH 1/7] Commented out SceneData, upgraded Rider, downloaded EphysLinkModels --- Assets/Editor/ModelsManager.cs | 41 +++++ Assets/Editor/ModelsManager.cs.meta | 11 ++ Assets/Scripts/EphysLink/EphysLinkModels.cs | 70 ++++++++ .../Scripts/EphysLink/EphysLinkModels.cs.meta | 11 ++ Assets/Scripts/Pinpoint/JSON/SceneData.cs | 152 +++++++++--------- Packages/manifest.json | 2 +- Packages/packages-lock.json | 2 +- 7 files changed, 211 insertions(+), 78 deletions(-) create mode 100644 Assets/Editor/ModelsManager.cs create mode 100644 Assets/Editor/ModelsManager.cs.meta create mode 100644 Assets/Scripts/EphysLink/EphysLinkModels.cs create mode 100644 Assets/Scripts/EphysLink/EphysLinkModels.cs.meta diff --git a/Assets/Editor/ModelsManager.cs b/Assets/Editor/ModelsManager.cs new file mode 100644 index 00000000..f9e396d7 --- /dev/null +++ b/Assets/Editor/ModelsManager.cs @@ -0,0 +1,41 @@ +using System.IO; +using System.Net; +using UnityEditor; +using UnityEngine; + +namespace Editor +{ + public static class ModelsManager + { + [MenuItem("Tools/Update Schemas")] + public static void UpdateSchemas() + { + var webClient = new WebClient(); + webClient.DownloadFile( + "https://raw.githubusercontent.com/VirtualBrainLab/vbl-aquarium/main/models/csharp/EphysLinkModels.cs", + "Assets/Scripts/EphysLink/EphysLinkModels.cs"); + + Debug.Log("Schemas updated successfully!"); + } + + private static void GetSchemas(string srcURL, string outFile) + { + + if (!Directory.Exists(outFile)) + { + Directory.CreateDirectory(outFile); + } + + string[] files = Directory.GetFiles(srcURL, "*.cs"); + + foreach (string file in files) + { + string fileName = Path.GetFileName(file); + string destFilePath = Path.Combine(outFile, fileName); + File.Copy(file, destFilePath, true); + } + + AssetDatabase.Refresh(); + } + } +} \ No newline at end of file diff --git a/Assets/Editor/ModelsManager.cs.meta b/Assets/Editor/ModelsManager.cs.meta new file mode 100644 index 00000000..50d9373c --- /dev/null +++ b/Assets/Editor/ModelsManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b46513fbabf35e34ca320b4cff1cca1c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/EphysLink/EphysLinkModels.cs b/Assets/Scripts/EphysLink/EphysLinkModels.cs new file mode 100644 index 00000000..80d56537 --- /dev/null +++ b/Assets/Scripts/EphysLink/EphysLinkModels.cs @@ -0,0 +1,70 @@ +using UnityEngine; + +public struct AngularResponse +{ + public Vector3 Angles; + public string Error; +} + +public struct BooleanStateResponse +{ + public bool State; + public string Error; +} + +public struct CanWriteRequest +{ + public string ManipulatorId; + public bool CanWrite; + public float Hours; +} + +public struct DriveToDepthRequest +{ + public string ManipulatorId; + public float Depth; + public float Speed; +} + +public struct DriveToDepthResponse +{ + public float Depth; + public string Error; +} + + +public struct GetManipulatorsResponse +{ + public string[] Manipulators; + public int NumAxes; + public Vector4 Dimensions; + public string Error; +} + + +public struct GotoPositionRequest +{ + public string ManipulatorId; + public Vector4 Position; + public float Speed; +} + +public struct InsideBrainRequest +{ + public string ManipulatorId; + public bool Inside; +} + + +public struct PositionalResponse +{ + public Vector4 Position; + public string Error; +} + +public struct ShankCountResponse +{ + public int ShankCount; + public string Error; +} + diff --git a/Assets/Scripts/EphysLink/EphysLinkModels.cs.meta b/Assets/Scripts/EphysLink/EphysLinkModels.cs.meta new file mode 100644 index 00000000..b5fde171 --- /dev/null +++ b/Assets/Scripts/EphysLink/EphysLinkModels.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 611420d9ab36933479b7fcc8050ee2e3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Pinpoint/JSON/SceneData.cs b/Assets/Scripts/Pinpoint/JSON/SceneData.cs index 74919782..609f4e22 100644 --- a/Assets/Scripts/Pinpoint/JSON/SceneData.cs +++ b/Assets/Scripts/Pinpoint/JSON/SceneData.cs @@ -12,82 +12,82 @@ public struct SceneData public string Settings; - public static SceneData ToSceneData(string atlasName, string transformName, - RigData[] rigDatas, - ProbeData[] probeDatas, - CraniotomyData[] craniotomyDatas, - string settings) - { - SceneData sceneData = new SceneData(); - sceneData.AtlasName = atlasName; - sceneData.TransformName = transformName; - sceneData.Settings = settings; - - sceneData.Data = new string[rigDatas.Length + probeDatas.Length]; - int di = 0; - - foreach (RigData rigData in rigDatas) - { - SceneDataStorage temp = new SceneDataStorage(); - temp.Type = SceneDataType.Rig; - temp.Data = JsonUtility.ToJson(rigData); - sceneData.Data[di++] = JsonUtility.ToJson(temp); - } - - foreach (ProbeData probeData in probeDatas) - { - SceneDataStorage temp = new SceneDataStorage(); - temp.Type = SceneDataType.Probe; - temp.Data = JsonUtility.ToJson(probeData); - sceneData.Data[di++] = JsonUtility.ToJson(temp); - } - - foreach (CraniotomyData craniotomyData in craniotomyDatas) - { - SceneDataStorage temp = new SceneDataStorage(); - temp.Type = SceneDataType.Craniotomy; - temp.Data = JsonUtility.ToJson(craniotomyData); - sceneData.Data[di++] = JsonUtility.ToJson(temp); - } - - return sceneData; - } - - public static (string atlasName, string transformName, - RigData[] rigDatas, - ProbeData[] probeDatas, - CraniotomyData[] craniotomyDatas) FromSceneData(string sceneDataJSON) - { - SceneData sceneData = JsonUtility.FromJson(sceneDataJSON); - string atlasName = sceneData.AtlasName; - string transformName = sceneData.TransformName; - - List rigDatas = new List(); - List probeDatas = new List(); - List craniotomyDatas = new(); - - foreach (string data in sceneData.Data) - { - SceneDataStorage temp = JsonUtility.FromJson(data); - switch (temp.Type) - { - case SceneDataType.Probe: - probeDatas.Add(JsonUtility.FromJson(temp.Data)); - break; - case SceneDataType.Rig: - rigDatas.Add(JsonUtility.FromJson(temp.Data)); - break; - case SceneDataType.Craniotomy: - craniotomyDatas.Add(JsonUtility.FromJson(temp.Data)); - break; - } - } - - return (atlasName, transformName, - rigDatas.ToArray(), - probeDatas.ToArray(), - craniotomyDatas.ToArray()); - } + // public static SceneData ToSceneData(string atlasName, string transformName, + // RigData[] rigDatas, + // ProbeData[] probeDatas, + // CraniotomyData[] craniotomyDatas, + // string settings) + // { + // SceneData sceneData = new SceneData(); + // sceneData.AtlasName = atlasName; + // sceneData.TransformName = transformName; + // sceneData.Settings = settings; + // + // sceneData.Data = new string[rigDatas.Length + probeDatas.Length]; + // int di = 0; + // + // foreach (RigData rigData in rigDatas) + // { + // SceneDataStorage temp = new SceneDataStorage(); + // temp.Type = SceneDataType.Rig; + // temp.Data = JsonUtility.ToJson(rigData); + // sceneData.Data[di++] = JsonUtility.ToJson(temp); + // } + // + // foreach (ProbeData probeData in probeDatas) + // { + // SceneDataStorage temp = new SceneDataStorage(); + // temp.Type = SceneDataType.Probe; + // temp.Data = JsonUtility.ToJson(probeData); + // sceneData.Data[di++] = JsonUtility.ToJson(temp); + // } + // + // foreach (CraniotomyData craniotomyData in craniotomyDatas) + // { + // SceneDataStorage temp = new SceneDataStorage(); + // temp.Type = SceneDataType.Craniotomy; + // temp.Data = JsonUtility.ToJson(craniotomyData); + // sceneData.Data[di++] = JsonUtility.ToJson(temp); + // } + // + // return sceneData; + // } + + // public static (string atlasName, string transformName, + // RigData[] rigDatas, + // ProbeData[] probeDatas, + // CraniotomyData[] craniotomyDatas) FromSceneData(string sceneDataJSON) + // { + // SceneData sceneData = JsonUtility.FromJson(sceneDataJSON); + // string atlasName = sceneData.AtlasName; + // string transformName = sceneData.TransformName; + // + // List rigDatas = new List(); + // List probeDatas = new List(); + // List craniotomyDatas = new(); + // + // foreach (string data in sceneData.Data) + // { + // SceneDataStorage temp = JsonUtility.FromJson(data); + // switch (temp.Type) + // { + // case SceneDataType.Probe: + // probeDatas.Add(JsonUtility.FromJson(temp.Data)); + // break; + // case SceneDataType.Rig: + // rigDatas.Add(JsonUtility.FromJson(temp.Data)); + // break; + // case SceneDataType.Craniotomy: + // craniotomyDatas.Add(JsonUtility.FromJson(temp.Data)); + // break; + // } + // } + // + // return (atlasName, transformName, + // rigDatas.ToArray(), + // probeDatas.ToArray(), + // craniotomyDatas.ToArray()); + // } public override string ToString() { diff --git a/Packages/manifest.json b/Packages/manifest.json index b39703c8..d9a91b8b 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -3,7 +3,7 @@ "com.unity.addressables": "1.21.19", "com.unity.ai.navigation": "1.1.5", "com.unity.animation.rigging": "1.2.1", - "com.unity.ide.rider": "3.0.27", + "com.unity.ide.rider": "3.0.28", "com.unity.ide.visualstudio": "2.0.22", "com.unity.ide.vscode": "1.2.5", "com.unity.inputsystem": "1.7.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index e7fee04d..3b1e254f 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -58,7 +58,7 @@ "url": "https://packages.unity.com" }, "com.unity.ide.rider": { - "version": "3.0.27", + "version": "3.0.28", "depth": 0, "source": "registry", "dependencies": { From 7a873725ddf96f772a192f647282253613a950a1 Mon Sep 17 00:00:00 2001 From: Kenneth Yang Date: Wed, 27 Mar 2024 14:02:34 -0700 Subject: [PATCH 2/7] GetManipulators --- Assets/Editor/ModelsManager.cs | 1 + .../Scripts/EphysLink/CommunicationManager.cs | 27 +++++++++++++------ .../Probes/ManipulatorBehaviorController.cs | 8 +++--- .../UI/EphysLinkSettings/EphysLinkSettings.cs | 8 +++--- Assets/Tests/CommunicationManagerTests.cs | 4 +-- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Assets/Editor/ModelsManager.cs b/Assets/Editor/ModelsManager.cs index f9e396d7..4b62a62d 100644 --- a/Assets/Editor/ModelsManager.cs +++ b/Assets/Editor/ModelsManager.cs @@ -11,6 +11,7 @@ public static class ModelsManager public static void UpdateSchemas() { var webClient = new WebClient(); + webClient.DownloadFile( "https://raw.githubusercontent.com/VirtualBrainLab/vbl-aquarium/main/models/csharp/EphysLinkModels.cs", "Assets/Scripts/EphysLink/EphysLinkModels.cs"); diff --git a/Assets/Scripts/EphysLink/CommunicationManager.cs b/Assets/Scripts/EphysLink/CommunicationManager.cs index d6c4ed4d..35dac5cc 100644 --- a/Assets/Scripts/EphysLink/CommunicationManager.cs +++ b/Assets/Scripts/EphysLink/CommunicationManager.cs @@ -40,8 +40,14 @@ public class CommunicationManager : MonoBehaviour private void Awake() { - if (Instance != null) Debug.LogError("Make sure there is only one CommunicationManager in the scene!"); - Instance = this; + if (Instance == null) + { + Instance = this; + DontDestroyOnLoad(this); + } else if (Instance != this) + { + Destroy(this); + } } #endregion @@ -209,19 +215,19 @@ private void GetVersion(Action onSuccessCallback, Action onErrorCallback /// /// Callback function to handle incoming manipulator ID's /// Callback function to handle errors - public void GetManipulators(Action onSuccessCallback, + public void GetManipulators(Action onSuccessCallback, Action onErrorCallback = null) { _connectionManager.Socket.ExpectAcknowledgement(data => { if (DataKnownAndNotEmpty(data)) { - var parsedData = GetManipulatorsCallbackParameters.FromJson(data); - if (parsedData.error == "") - onSuccessCallback?.Invoke(parsedData.manipulators, parsedData.num_axes, - parsedData.dimensions); + var parsedData = ParseJson(data); + + if (parsedData.Error == "") + onSuccessCallback?.Invoke(parsedData); else - onErrorCallback?.Invoke(parsedData.error); + onErrorCallback?.Invoke(parsedData.Error); } else { @@ -541,6 +547,11 @@ private static bool DataKnownAndNotEmpty(string data) { return data is not ("" or UNKOWN_EVENT); } + + private static T ParseJson(string json) + { + return JsonUtility.FromJson(json); + } #endregion } diff --git a/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs b/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs index 49123910..38aaee01 100644 --- a/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs +++ b/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs @@ -149,15 +149,15 @@ private void OnDisable() public void Initialize(string manipulatorID, bool calibrated) { - CommunicationManager.Instance.GetManipulators((ids, numAxes, dimensions) => + CommunicationManager.Instance.GetManipulators((reponse) => { // Shortcut exit if we have an invalid manipulator ID - if (!ids.Contains(manipulatorID)) return; + if (!reponse.Manipulators.Contains(manipulatorID)) return; // Set manipulator ID, number of axes, and dimensions ManipulatorID = manipulatorID; - NumAxes = numAxes; - Dimensions = new Vector3(dimensions[0], dimensions[1], dimensions[2]); + NumAxes = reponse.NumAxes; + Dimensions = reponse.Dimensions; // Update transform and space UpdateSpaceAndTransform(); diff --git a/Assets/Scripts/Pinpoint/UI/EphysLinkSettings/EphysLinkSettings.cs b/Assets/Scripts/Pinpoint/UI/EphysLinkSettings/EphysLinkSettings.cs index ad773098..31ac1bf8 100644 --- a/Assets/Scripts/Pinpoint/UI/EphysLinkSettings/EphysLinkSettings.cs +++ b/Assets/Scripts/Pinpoint/UI/EphysLinkSettings/EphysLinkSettings.cs @@ -106,13 +106,13 @@ private void UpdateManipulatorPanels() if (CommunicationManager.Instance.IsConnected) { - CommunicationManager.Instance.GetManipulators((availableIDs, numAxes, _) => + CommunicationManager.Instance.GetManipulators((response) => { // Keep track of handled manipulator panels var handledManipulatorIds = new HashSet(); // Add any new manipulators in scene to list - foreach (var manipulatorID in availableIDs) + foreach (var manipulatorID in response.Manipulators) { // Create new manipulator connection settings panel if the manipulator is new if (!_manipulatorIdToManipulatorConnectionSettingsPanel.ContainsKey(manipulatorID)) @@ -125,7 +125,7 @@ private void UpdateManipulatorPanels() .GetComponent(); // Set manipulator id - manipulatorConnectionSettingsPanel.Initialize(this, manipulatorID, numAxes); + manipulatorConnectionSettingsPanel.Initialize(this, manipulatorID, response.NumAxes); // Add to dictionary _manipulatorIdToManipulatorConnectionSettingsPanel.Add(manipulatorID, @@ -146,7 +146,7 @@ private void UpdateManipulatorPanels() } // Reorder panels to match order of availableIds - foreach (var manipulatorId in availableIDs) + foreach (var manipulatorId in response.Manipulators) _manipulatorIdToManipulatorConnectionSettingsPanel[manipulatorId].gameObject.transform .SetAsLastSibling(); }); diff --git a/Assets/Tests/CommunicationManagerTests.cs b/Assets/Tests/CommunicationManagerTests.cs index 51f34eb0..dcfd275c 100644 --- a/Assets/Tests/CommunicationManagerTests.cs +++ b/Assets/Tests/CommunicationManagerTests.cs @@ -49,9 +49,9 @@ public IEnumerator Setup() var state = State.None; _communicationManager.GetManipulators( - (returnedManipulators, _, _) => + (response) => { - _manipulators = returnedManipulators; + _manipulators = response.Manipulators; state = State.Success; }, returnedError => state = State.Failed); From f8bb7426ca97493c1e80342cb7e5a26e2d9e9b78 Mon Sep 17 00:00:00 2001 From: Kenneth Yang Date: Wed, 27 Mar 2024 14:04:14 -0700 Subject: [PATCH 3/7] GetPos --- Assets/Scripts/EphysLink/CommunicationManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Assets/Scripts/EphysLink/CommunicationManager.cs b/Assets/Scripts/EphysLink/CommunicationManager.cs index 35dac5cc..8369f0eb 100644 --- a/Assets/Scripts/EphysLink/CommunicationManager.cs +++ b/Assets/Scripts/EphysLink/CommunicationManager.cs @@ -285,19 +285,19 @@ public void GetPos(string manipulatorId, Action onSuccessCallback, { if (DataKnownAndNotEmpty(data)) { - var parsedData = PositionalCallbackParameters.FromJson(data); - if (parsedData.error == "") + var parsedData = ParseJson(data); + + if (parsedData.Error == "") try { - onSuccessCallback?.Invoke(new Vector4(parsedData.position[0], parsedData.position[1], - parsedData.position[2], parsedData.position[3])); + onSuccessCallback?.Invoke(parsedData.Position); } catch (Exception e) { onErrorCallback?.Invoke(e.ToString()); } else - onErrorCallback?.Invoke(parsedData.error); + onErrorCallback?.Invoke(parsedData.Error); } else { From 95e72538f8cb1d1c914dc9662d0277c78a44d4bb Mon Sep 17 00:00:00 2001 From: Kenneth Yang Date: Wed, 27 Mar 2024 14:44:08 -0700 Subject: [PATCH 4/7] Parse input data --- .../Scripts/EphysLink/CommunicationManager.cs | 144 +++++++----------- Pinpoint.sln.DotSettings | 1 + 2 files changed, 58 insertions(+), 87 deletions(-) diff --git a/Assets/Scripts/EphysLink/CommunicationManager.cs b/Assets/Scripts/EphysLink/CommunicationManager.cs index 8369f0eb..3791319e 100644 --- a/Assets/Scripts/EphysLink/CommunicationManager.cs +++ b/Assets/Scripts/EphysLink/CommunicationManager.cs @@ -22,7 +22,7 @@ public class CommunicationManager : MonoBehaviour private static readonly int[] EPHYS_LINK_MIN_VERSION = { 1, 2, 8 }; - public static readonly string EPHYS_LINK_MIN_VERSION_STRING = "≥ v" + string.Join(".", EPHYS_LINK_MIN_VERSION); + public static readonly string EPHYS_LINK_MIN_VERSION_STRING = $"≥ v{string.Join(".", EPHYS_LINK_MIN_VERSION)}"; private const string UNKOWN_EVENT = "UNKNOWN_EVENT"; @@ -44,7 +44,8 @@ private void Awake() { Instance = this; DontDestroyOnLoad(this); - } else if (Instance != this) + } + else if (Instance != this) { Destroy(this); } @@ -57,7 +58,8 @@ private void Awake() public void ServerSettingsLoaded() { // Automatically connect if the server credentials are possible - if (!IsConnected && Settings.EphysLinkServerIp != "" && Settings.EphysLinkServerPort >= 1025) + if (!IsConnected && !string.IsNullOrEmpty(Settings.EphysLinkServerIp) && + Settings.EphysLinkServerPort >= 1025) ConnectToServer(Settings.EphysLinkServerIp, Settings.EphysLinkServerPort, () => { // Verify Ephys Link version @@ -89,13 +91,13 @@ public void ConnectToServer(string ip, int port, Action onConnected = null, try { // Create a new socket - _connectionManager = new SocketManager(new Uri("http://" + ip + ":" + port), options); + _connectionManager = new SocketManager(new Uri($"http://{ip}:{port}"), options); _socket = _connectionManager.Socket; // On successful connection _socket.Once("connect", () => { - Debug.Log("Connected to WebSocket server at " + ip + ":" + port); + Debug.Log($"Connected to WebSocket server at {ip}:{port}"); IsConnected = true; // Save settings @@ -109,7 +111,7 @@ public void ConnectToServer(string ip, int port, Action onConnected = null, _socket.Once("error", () => { var connectionErrorMessage = - "Error connecting to server at " + ip + ":" + port + ". Check server for details."; + $"Error connecting to server at {ip}:{port}. Check server for details."; Debug.LogWarning(connectionErrorMessage); IsConnected = false; _connectionManager.Close(); @@ -121,7 +123,7 @@ public void ConnectToServer(string ip, int port, Action onConnected = null, // On timeout _socket.Once("connect_timeout", () => { - var connectionTimeoutMessage = "Connection to server at " + ip + ":" + port + " timed out"; + var connectionTimeoutMessage = "Connection to server at {ip}:{port} timed out"; Debug.LogWarning(connectionTimeoutMessage); IsConnected = false; _connectionManager.Close(); @@ -134,7 +136,7 @@ public void ConnectToServer(string ip, int port, Action onConnected = null, { // On socket generation error var connectionErrorMessage = - "Error connecting to server at " + ip + ":" + port + ". Check server for details."; + "Error connecting to server at {ip}:{port}. Check server for details."; Debug.LogWarning(connectionErrorMessage); Debug.LogWarning("Exception: " + e); IsConnected = false; @@ -223,15 +225,15 @@ public void GetManipulators(Action onSuccessCallback, if (DataKnownAndNotEmpty(data)) { var parsedData = ParseJson(data); - - if (parsedData.Error == "") + + if (string.IsNullOrEmpty(parsedData.Error)) onSuccessCallback?.Invoke(parsedData); else onErrorCallback?.Invoke(parsedData.Error); } else { - onErrorCallback?.Invoke("get_manipulators invalid response: " + data); + onErrorCallback?.Invoke($"get_manipulators invalid response: {data}"); } }).Emit("get_manipulators"); } @@ -247,10 +249,10 @@ public void RegisterManipulator(string manipulatorId, Action onSuccessCallback = { _connectionManager.Socket.ExpectAcknowledgement(error => { - if (error == "") + if (string.IsNullOrEmpty(error)) onSuccessCallback?.Invoke(); else - onErrorCallback?.Invoke("register_manipulators invalid response: " + error); + onErrorCallback?.Invoke($"register_manipulators invalid response: {error}"); }).Emit("register_manipulator", manipulatorId); } @@ -265,10 +267,10 @@ public void UnregisterManipulator(string manipulatorId, Action onSuccessCallback { _connectionManager.Socket.ExpectAcknowledgement(error => { - if (error == "") + if (string.IsNullOrEmpty(error)) onSuccessCallback?.Invoke(); else - onErrorCallback?.Invoke("unregister_manipulator invalid response: " + error); + onErrorCallback?.Invoke($"unregister_manipulator invalid response: {error}"); }).Emit("unregister_manipulator", manipulatorId); } @@ -286,22 +288,15 @@ public void GetPos(string manipulatorId, Action onSuccessCallback, if (DataKnownAndNotEmpty(data)) { var parsedData = ParseJson(data); - - if (parsedData.Error == "") - try - { - onSuccessCallback?.Invoke(parsedData.Position); - } - catch (Exception e) - { - onErrorCallback?.Invoke(e.ToString()); - } + + if (string.IsNullOrEmpty(parsedData.Error)) + onSuccessCallback?.Invoke(parsedData.Position); else onErrorCallback?.Invoke(parsedData.Error); } else { - onErrorCallback?.Invoke("get_pos invalid response: " + data); + onErrorCallback?.Invoke($"get_pos invalid response: {data}"); } }).Emit("get_pos", manipulatorId); } @@ -319,23 +314,15 @@ public void GetAngles(string manipulatorId, Action onSuccessCallback, { if (DataKnownAndNotEmpty(data)) { - var parsedData = AngularCallbackParameters.FromJson(data); - if (parsedData.error == "") - try - { - onSuccessCallback?.Invoke(new Vector3(parsedData.angles[0], parsedData.angles[1], - parsedData.angles[2])); - } - catch (Exception e) - { - onErrorCallback?.Invoke(e.ToString()); - } + var parsedData = ParseJson(data); + if (string.IsNullOrEmpty(parsedData.Error)) + onSuccessCallback?.Invoke(parsedData.Angles); else - onErrorCallback?.Invoke(parsedData.error); + onErrorCallback?.Invoke(parsedData.Error); } else { - onErrorCallback?.Invoke("get_angles invalid response: " + data); + onErrorCallback?.Invoke($"get_angles invalid response: {data}"); } }).Emit("get_angles", manipulatorId); } @@ -347,22 +334,15 @@ public void GetShankCount(string manipulatorId, Action onSuccessCallback, { if (DataKnownAndNotEmpty(data)) { - var parsedData = ShankCountCallbackParameters.FromJson(data); - if (parsedData.error == "") - try - { - onSuccessCallback?.Invoke(parsedData.shank_count); - } - catch (Exception e) - { - onErrorCallback?.Invoke(e.ToString()); - } + var parsedData = ParseJson(data); + if (string.IsNullOrEmpty(parsedData.Error)) + onSuccessCallback?.Invoke(parsedData.ShankCount); else - onErrorCallback?.Invoke(parsedData.error); + onErrorCallback?.Invoke(parsedData.Error); } else { - onErrorCallback?.Invoke("get_shank_count invalid response: " + data); + onErrorCallback?.Invoke($"get_shank_count invalid response: {data}"); } }).Emit("get_shank_count", manipulatorId); } @@ -383,23 +363,15 @@ public void GotoPos(string manipulatorId, Vector4 pos, float speed, Action(data); + if (string.IsNullOrEmpty(parsedData.Error)) + onSuccessCallback?.Invoke(parsedData.Position); else - onErrorCallback?.Invoke(parsedData.error); + onErrorCallback?.Invoke(parsedData.Error); } else { - onErrorCallback?.Invoke("goto_pos invalid response: " + data); + onErrorCallback?.Invoke($"goto_pos invalid response: {data}"); } }).Emit("goto_pos", new GotoPositionInputDataFormat(manipulatorId, pos, speed).ToJson()); } @@ -419,18 +391,11 @@ public void DriveToDepth(string manipulatorId, float depth, float speed, Action< { if (DataKnownAndNotEmpty(data)) { - var parsedData = DriveToDepthCallbackParameters.FromJson(data); - if (parsedData.error == "") - try - { - onSuccessCallback?.Invoke(parsedData.depth); - } - catch (Exception e) - { - onErrorCallback?.Invoke(e.ToString()); - } + var parsedData = ParseJson(data); + if (string.IsNullOrEmpty(parsedData.Error)) + onSuccessCallback?.Invoke(parsedData.Depth); else - onErrorCallback?.Invoke(parsedData.error); + onErrorCallback?.Invoke(parsedData.Error); } else { @@ -453,15 +418,15 @@ public void SetInsideBrain(string manipulatorId, bool inside, Action onSuc { if (DataKnownAndNotEmpty(data)) { - var parsedData = StateCallbackParameters.FromJson(data); - if (parsedData.error == "") - onSuccessCallback?.Invoke(parsedData.state); + var parsedData = ParseJson(data); + if (string.IsNullOrEmpty(parsedData.Error)) + onSuccessCallback?.Invoke(parsedData.State); else - onErrorCallback?.Invoke(parsedData.error); + onErrorCallback?.Invoke(parsedData.Error); } else { - onErrorCallback?.Invoke("set_inside_brain invalid response: " + data); + onErrorCallback?.Invoke($"set_inside_brain invalid response: {data}"); } }).Emit("set_inside_brain", new InsideBrainInputDataFormat(manipulatorId, inside).ToJson()); } @@ -517,15 +482,15 @@ public void SetCanWrite(string manipulatorId, bool canWrite, float hours, Action { if (DataKnownAndNotEmpty(data)) { - var parsedData = StateCallbackParameters.FromJson(data); - if (parsedData.error == "") - onSuccessCallback?.Invoke(parsedData.state); + var parsedData = ParseJson(data); + if (string.IsNullOrEmpty(parsedData.Error)) + onSuccessCallback?.Invoke(parsedData.State); else - onErrorCallback?.Invoke(parsedData.error); + onErrorCallback?.Invoke(parsedData.Error); } else { - onErrorCallback?.Invoke("set_can_write invalid response: " + data); + onErrorCallback?.Invoke($"set_can_write invalid response: {data}"); } }).Emit("set_can_write", new CanWriteInputDataFormat(manipulatorId, canWrite, hours).ToJson()); } @@ -545,14 +510,19 @@ public void Stop(Action callback) private static bool DataKnownAndNotEmpty(string data) { - return data is not ("" or UNKOWN_EVENT); + return !string.IsNullOrEmpty(data) && !data.Equals(UNKOWN_EVENT); } - + private static T ParseJson(string json) { return JsonUtility.FromJson(json); } + private string ToJson(T data) + { + return JsonUtility.ToJson(data); + } + #endregion } } \ No newline at end of file diff --git a/Pinpoint.sln.DotSettings b/Pinpoint.sln.DotSettings index 4b4b12fb..94874ce6 100644 --- a/Pinpoint.sln.DotSettings +++ b/Pinpoint.sln.DotSettings @@ -74,4 +74,5 @@ True True True + True \ No newline at end of file From 3dcf0e2e87681d1c05ac68a6ba1711c78127e42f Mon Sep 17 00:00:00 2001 From: Kenneth Yang Date: Wed, 27 Mar 2024 15:04:26 -0700 Subject: [PATCH 5/7] GotoPos --- .../Scripts/EphysLink/CommunicationManager.cs | 8 +- .../Probes/ManipulatorBehaviorController.cs | 15 +++- .../UI/EphysCopilot/DrivePanelHandler.cs | 8 +- .../InsertionSelectionPanelHandler.cs | 74 +++++++++++-------- Assets/Tests/CommunicationManagerTests.cs | 25 +++++-- 5 files changed, 83 insertions(+), 47 deletions(-) diff --git a/Assets/Scripts/EphysLink/CommunicationManager.cs b/Assets/Scripts/EphysLink/CommunicationManager.cs index 3791319e..03c3747d 100644 --- a/Assets/Scripts/EphysLink/CommunicationManager.cs +++ b/Assets/Scripts/EphysLink/CommunicationManager.cs @@ -351,12 +351,10 @@ public void GetShankCount(string manipulatorId, Action onSuccessCallback, /// Request a manipulator be moved to a specific position. /// /// Position is defined by a Vector4 - /// ID of the manipulator to be moved - /// Position in mm of the manipulator - /// How fast to move the manipulator (in mm/s) + /// Goto position request object /// Callback function to handle successful manipulator movement /// Callback function to handle errors - public void GotoPos(string manipulatorId, Vector4 pos, float speed, Action onSuccessCallback, + public void GotoPos(GotoPositionRequest request, Action onSuccessCallback, Action onErrorCallback = null) { _connectionManager.Socket.ExpectAcknowledgement(data => @@ -373,7 +371,7 @@ public void GotoPos(string manipulatorId, Vector4 pos, float speed, Action diff --git a/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs b/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs index 38aaee01..7827020f 100644 --- a/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs +++ b/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs @@ -305,7 +305,11 @@ public void MoveByWorldSpaceDelta(Vector4 worldSpaceDelta, Action onSucces CommunicationManager.Instance.SetCanWrite(ManipulatorID, true, 1, b => { if (!b) return; - CommunicationManager.Instance.GotoPos(ManipulatorID, targetPosition, AUTOMATIC_MOVEMENT_SPEED, + CommunicationManager.Instance.GotoPos( + new GotoPositionRequest + { + ManipulatorId = ManipulatorID, Position = targetPosition, Speed = AUTOMATIC_MOVEMENT_SPEED + }, newPos => { // Process depth movement @@ -334,7 +338,12 @@ public void MoveBackToZeroCoordinate(Action onSuccessCallback, Action { if (!b) return; - CommunicationManager.Instance.GotoPos(ManipulatorID, ZeroCoordinateOffset, AUTOMATIC_MOVEMENT_SPEED, + CommunicationManager.Instance.GotoPos(new GotoPositionRequest + { + ManipulatorId = ManipulatorID, + Position = ZeroCoordinateOffset, + Speed = AUTOMATIC_MOVEMENT_SPEED + }, pos => { CommunicationManager.Instance.SetCanWrite(ManipulatorID, false, 0, _ => onSuccessCallback(pos), @@ -444,7 +453,7 @@ private void EchoPosition(Vector4 pos) // Set probe position (change axes to match probe) var transformedApmldv = BrainAtlasManager.World2T_Vector(zeroCoordinateAdjustedWorldPosition); - + // Split between 3 and 4 axis assignments if (CoordinateTransform.Prefix == "3lhm") _probeController.SetProbePosition(transformedApmldv); diff --git a/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs b/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs index e78083e4..f365861f 100644 --- a/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs +++ b/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs @@ -585,8 +585,12 @@ public void Exit() // Drive to outside position if (position.y < _outsidePosition.y) - CommunicationManager.Instance.GotoPos(_manipulatorId, _outsidePosition, - _outsideDriveSpeed, _ => CompleteOutside(), Debug.LogError); + CommunicationManager.Instance.GotoPos(new GotoPositionRequest + { + ManipulatorId = _manipulatorId, + Position = _outsidePosition, + Speed = _outsideDriveSpeed + }, _ => CompleteOutside(), Debug.LogError); // Drive to outside depth if DV movement is unavailable else if (position.w > _outsideDepth) CommunicationManager.Instance.DriveToDepth(_manipulatorId, _outsideDepth, diff --git a/Assets/Scripts/Pinpoint/UI/EphysCopilot/InsertionSelectionPanelHandler.cs b/Assets/Scripts/Pinpoint/UI/EphysCopilot/InsertionSelectionPanelHandler.cs index 14631bdf..ca7b1a53 100644 --- a/Assets/Scripts/Pinpoint/UI/EphysCopilot/InsertionSelectionPanelHandler.cs +++ b/Assets/Scripts/Pinpoint/UI/EphysCopilot/InsertionSelectionPanelHandler.cs @@ -394,46 +394,56 @@ private void MoveToTargetInsertion() canWrite => { if (canWrite) - CommunicationManager.Instance.GotoPos(ProbeManager.ManipulatorBehaviorController.ManipulatorID, - dvPosition, - ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED, _ => - { - CommunicationManager.Instance.GotoPos( - ProbeManager.ManipulatorBehaviorController.ManipulatorID, apPosition, - ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED, _ => + CommunicationManager.Instance.GotoPos(new GotoPositionRequest + { + ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, + Position = dvPosition, + Speed = ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED + }, _ => + { + CommunicationManager.Instance.GotoPos( + new GotoPositionRequest + { + ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, + Position = apPosition, + Speed = ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED + }, _ => + { + CommunicationManager.Instance.GotoPos(new GotoPositionRequest { - CommunicationManager.Instance.GotoPos( - ProbeManager.ManipulatorBehaviorController.ManipulatorID, mlPosition, - ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED, _ => - { - CommunicationManager.Instance.SetCanWrite( - ProbeManager.ManipulatorBehaviorController.ManipulatorID, false, - 1, _ => - { - // Hide lines - _lineGameObjects.ap.SetActive(false); - _lineGameObjects.ml.SetActive(false); - _lineGameObjects.dv.SetActive(false); - - // Complete movement - EndMovement(); - _moveButton.interactable = false; - }, Debug.LogError); - }, error => + ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, + Position = mlPosition, + Speed = ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED + }, _ => + { + CommunicationManager.Instance.SetCanWrite( + ProbeManager.ManipulatorBehaviorController.ManipulatorID, false, + 1, _ => { - Debug.LogError(error); + // Hide lines + _lineGameObjects.ap.SetActive(false); + _lineGameObjects.ml.SetActive(false); + _lineGameObjects.dv.SetActive(false); + + // Complete movement EndMovement(); - }); + _moveButton.interactable = false; + }, Debug.LogError); }, error => { Debug.LogError(error); EndMovement(); }); - }, error => - { - Debug.LogError(error); - EndMovement(); - }); + }, error => + { + Debug.LogError(error); + EndMovement(); + }); + }, error => + { + Debug.LogError(error); + EndMovement(); + }); }, Debug.LogError); return; diff --git a/Assets/Tests/CommunicationManagerTests.cs b/Assets/Tests/CommunicationManagerTests.cs index dcfd275c..b08454fd 100644 --- a/Assets/Tests/CommunicationManagerTests.cs +++ b/Assets/Tests/CommunicationManagerTests.cs @@ -1,6 +1,6 @@ using System.Collections; -using NUnit.Framework; using EphysLink; +using NUnit.Framework; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.TestTools; @@ -49,7 +49,7 @@ public IEnumerator Setup() var state = State.None; _communicationManager.GetManipulators( - (response) => + response => { _manipulators = response.Manipulators; state = State.Success; @@ -133,8 +133,18 @@ public IEnumerator TestCalibrateAndMovement() _communicationManager.RegisterManipulator(id, () => _communicationManager.SetCanWrite(id, true, 1, _ => _communicationManager.Calibrate(id, () => - _communicationManager.GotoPos((string)id, new Vector4(0, 0, 0, 0), 5000, - _ => _communicationManager.GotoPos((string)id, new Vector4(10000, 10000, 10000, 10000), 5000, + _communicationManager.GotoPos(new GotoPositionRequest + { + ManipulatorId = id, + Position = Vector4.zero, + Speed = 5000 + }, + _ => _communicationManager.GotoPos(new GotoPositionRequest + { + ManipulatorId = id, + Position = Vector4.one * 10000, + Speed = 5000 + }, _ => state = State.Success, _ => state = State.Failed5), _ => state = State.Failed4), _ => state = State.Failed3), _ => state = State.Failed2), _ => state = State.Failed); @@ -204,7 +214,12 @@ public IEnumerator TestStop() _communicationManager.RegisterManipulator(id, () => _communicationManager.SetCanWrite(id, true, 1, _ => _communicationManager.BypassCalibration(id, () => { - _communicationManager.GotoPos((string)id, Vector4.zero, 5000, _ => state = State.Failed4, + _communicationManager.GotoPos(new GotoPositionRequest + { + ManipulatorId = id, + Position = Vector4.zero, + Speed = 5000 + }, _ => state = State.Failed4, _ => state = State.Failed4); _communicationManager.Stop(_ => state = State.Success); }, _ => state = State.Failed3), _ => state = State.Failed2), _ => state = State.Failed); From 64e0bc8baa6f383754088dfe987c01f320b93db5 Mon Sep 17 00:00:00 2001 From: Kenneth Yang Date: Wed, 27 Mar 2024 15:14:15 -0700 Subject: [PATCH 6/7] DriveToDepth --- .../Scripts/EphysLink/CommunicationManager.cs | 10 +- .../Probes/ManipulatorBehaviorController.cs | 9 +- .../UI/EphysCopilot/DrivePanelHandler.cs | 68 +++-- Assets/Tests/CommunicationManagerTests.cs | 234 ------------------ .../Tests/CommunicationManagerTests.cs.meta | 11 - 5 files changed, 58 insertions(+), 274 deletions(-) delete mode 100644 Assets/Tests/CommunicationManagerTests.cs delete mode 100644 Assets/Tests/CommunicationManagerTests.cs.meta diff --git a/Assets/Scripts/EphysLink/CommunicationManager.cs b/Assets/Scripts/EphysLink/CommunicationManager.cs index 03c3747d..b4970928 100644 --- a/Assets/Scripts/EphysLink/CommunicationManager.cs +++ b/Assets/Scripts/EphysLink/CommunicationManager.cs @@ -377,12 +377,10 @@ public void GotoPos(GotoPositionRequest request, Action onSuccessCallba /// /// Request a manipulator drive down to a specific depth. /// - /// ID of the manipulator to move - /// Depth in mm of the manipulator (in needle coordinates) - /// How fast to drive the manipulator (in mm/s) + /// Drive to depth request /// Callback function to handle successful manipulator movement /// Callback function to handle errors - public void DriveToDepth(string manipulatorId, float depth, float speed, Action onSuccessCallback, + public void DriveToDepth(DriveToDepthRequest request, Action onSuccessCallback, Action onErrorCallback) { _connectionManager.Socket.ExpectAcknowledgement(data => @@ -397,9 +395,9 @@ public void DriveToDepth(string manipulatorId, float depth, float speed, Action< } else { - onErrorCallback?.Invoke("drive_to_depth invalid response: " + data); + onErrorCallback?.Invoke($"drive_to_depth invalid response: {data}"); } - }).Emit("drive_to_depth", new DriveToDepthInputDataFormat(manipulatorId, depth, speed).ToJson()); + }).Emit("drive_to_depth", ToJson(request)); } /// diff --git a/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs b/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs index 7827020f..ce9d07bc 100644 --- a/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs +++ b/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs @@ -149,7 +149,7 @@ private void OnDisable() public void Initialize(string manipulatorID, bool calibrated) { - CommunicationManager.Instance.GetManipulators((reponse) => + CommunicationManager.Instance.GetManipulators(reponse => { // Shortcut exit if we have an invalid manipulator ID if (!reponse.Manipulators.Contains(manipulatorID)) return; @@ -316,7 +316,12 @@ public void MoveByWorldSpaceDelta(Vector4 worldSpaceDelta, Action onSucces var targetDepth = newPos.w + manipulatorSpaceDepth; // Move the manipulator CommunicationManager.Instance.DriveToDepth( - ManipulatorID, targetDepth, AUTOMATIC_MOVEMENT_SPEED, + new DriveToDepthRequest + { + ManipulatorId = ManipulatorID, + Depth = targetDepth, + Speed = AUTOMATIC_MOVEMENT_SPEED + }, _ => { CommunicationManager.Instance.SetCanWrite(ManipulatorID, false, 0, diff --git a/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs b/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs index f365861f..b3162ca5 100644 --- a/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs +++ b/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs @@ -425,8 +425,12 @@ public void Drive() // Drive to near target depth if (position.w < _nearTargetDepth) - CommunicationManager.Instance.DriveToDepth(_manipulatorId, _nearTargetDepth, - _targetDriveSpeed, _ => CompleteAndAdvance(), Debug.LogError); + CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _nearTargetDepth, + Speed = _targetDriveSpeed + }, _ => CompleteAndAdvance(), Debug.LogError); else // Already closer than near target depth, so continue CompleteAndAdvance(); @@ -442,8 +446,12 @@ public void Drive() // Drive to past target depth if (position.w < _pastTargetDepth) - CommunicationManager.Instance.DriveToDepth(_manipulatorId, _pastTargetDepth, - _nearTargetDriveSpeed, _ => CompleteAndAdvance(), Debug.LogError); + CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _pastTargetDepth, + Speed = _nearTargetDriveSpeed + }, _ => CompleteAndAdvance(), Debug.LogError); else // Already further than past target depth, so continue CompleteAndAdvance(); @@ -458,8 +466,12 @@ public void Drive() // Drive to target and complete movement CommunicationManager.Instance.DriveToDepth( - _manipulatorId, _targetDepth, - _nearTargetDriveSpeed, _ => + new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _targetDepth, + Speed = _nearTargetDriveSpeed + }, _ => { CommunicationManager.Instance.SetCanWrite(_manipulatorId, false, 0, _ => @@ -532,8 +544,12 @@ public void Exit() // Drive to near target depth if (_nearTargetDepth > _duraDepth && position.w > _nearTargetDepth) - CommunicationManager.Instance.DriveToDepth(_manipulatorId, _nearTargetDepth, - _nearTargetExitSpeed, _ => CompleteAndAdvance(), Debug.LogError); + CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _nearTargetDepth, + Speed = _nearTargetExitSpeed + }, _ => CompleteAndAdvance(), Debug.LogError); else // Dura depth is within near target distance, so continue CompleteAndAdvance(); @@ -548,9 +564,12 @@ public void Exit() // Drive to dura depth (set speed based on dura depth and near target depth) if (position.w > _duraDepth) - CommunicationManager.Instance.DriveToDepth(_manipulatorId, _duraDepth, - position.w > _nearTargetDepth ? _nearTargetExitSpeed : _exitDriveSpeed, - _ => CompleteAndAdvance(), Debug.LogError); + CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _duraDepth, + Speed = position.w > _nearTargetDepth ? _nearTargetExitSpeed : _exitDriveSpeed + }, _ => CompleteAndAdvance(), Debug.LogError); else // Already at dura depth, so continue CompleteAndAdvance(); @@ -565,9 +584,12 @@ public void Exit() // Drive to dura margin depth if (position.w > _exitMarginDepth) - CommunicationManager.Instance.DriveToDepth(_manipulatorId, _exitMarginDepth, - position.w > _nearTargetDepth ? _nearTargetExitSpeed : _exitDriveSpeed, - _ => CompleteAndAdvance(), Debug.LogError); + CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _exitMarginDepth, + Speed = position.w > _nearTargetDepth ? _nearTargetExitSpeed : _exitDriveSpeed + }, _ => CompleteAndAdvance(), Debug.LogError); else // Already at dura margin depth, so continue CompleteAndAdvance(); @@ -586,15 +608,19 @@ public void Exit() // Drive to outside position if (position.y < _outsidePosition.y) CommunicationManager.Instance.GotoPos(new GotoPositionRequest - { - ManipulatorId = _manipulatorId, - Position = _outsidePosition, - Speed = _outsideDriveSpeed - }, _ => CompleteOutside(), Debug.LogError); + { + ManipulatorId = _manipulatorId, + Position = _outsidePosition, + Speed = _outsideDriveSpeed + }, _ => CompleteOutside(), Debug.LogError); // Drive to outside depth if DV movement is unavailable else if (position.w > _outsideDepth) - CommunicationManager.Instance.DriveToDepth(_manipulatorId, _outsideDepth, - _outsideDriveSpeed, _ => CompleteOutside(), Debug.LogError); + CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _outsideDepth, + Speed = _outsideDriveSpeed + }, _ => CompleteOutside(), Debug.LogError); else // Already outside, so complete CompleteOutside(); diff --git a/Assets/Tests/CommunicationManagerTests.cs b/Assets/Tests/CommunicationManagerTests.cs deleted file mode 100644 index b08454fd..00000000 --- a/Assets/Tests/CommunicationManagerTests.cs +++ /dev/null @@ -1,234 +0,0 @@ -using System.Collections; -using EphysLink; -using NUnit.Framework; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEngine.TestTools; - -namespace Tests -{ - public class CommunicationManagerTests - { - #region Variables - - private CommunicationManager _communicationManager; - private string[] _manipulators; - - private enum State - { - None, - Success, - Failed, - Failed2, - Failed3, - Failed4, - Failed5 - } - - #endregion - - - #region Setup and Teardown - - /// - /// Setup each test. - /// Ensures a connection to the server and gets the manipulators. - /// - /// - [UnitySetUp] - public IEnumerator Setup() - { - SceneManager.LoadScene("Scenes/TrajectoryPlanner"); - yield return null; - - // Connect to server - _communicationManager = GameObject.Find("EphysLink").GetComponent(); - yield return new WaitUntil(() => _communicationManager.IsConnected); - - // Get manipulators - var state = State.None; - - _communicationManager.GetManipulators( - response => - { - _manipulators = response.Manipulators; - state = State.Success; - }, - returnedError => state = State.Failed); - - yield return new WaitWhile(() => state == State.None); - - if (state == State.Success) yield break; - TearDown(); - Assert.Fail("Could not get manipulators"); - } - - /// - /// Disconnect from server after each test - /// - [TearDown] - public void TearDown() - { - _communicationManager.DisconnectFromServer(); - } - - #endregion - - #region Tests - - /// - /// Register and then unregister each manipulator - /// - /// - [UnityTest] - public IEnumerator TestRegisterAndUnregister() - { - foreach (var id in _manipulators) - { - var state = State.None; - - _communicationManager.RegisterManipulator(id, - () => _communicationManager.UnregisterManipulator(id, () => state = State.Success, - _ => state = State.Failed2), - _ => state = State.Failed); - - yield return new WaitWhile(() => state == State.None); - Assert.That(state, Is.EqualTo(State.Success)); - } - } - - /// - /// Register -> Bypass calibration -> Get position - /// - /// - [UnityTest] - public IEnumerator TestGetPos() - { - foreach (var id in _manipulators) - { - var state = State.None; - - _communicationManager.RegisterManipulator(id, () => _communicationManager.BypassCalibration(id, () => - _communicationManager.GetPos(id, - _ => state = State.Success, - _ => state = State.Failed3), _ => state = State.Failed2), - _ => state = State.Failed); - - - yield return new WaitWhile(() => state == State.None); - Assert.That(state, Is.EqualTo(State.Success)); - } - } - - /// - /// Register -> Set Can Write -> Calibrate -> Goto position -> Return to home position - /// - /// - [UnityTest] - public IEnumerator TestCalibrateAndMovement() - { - foreach (var id in _manipulators) - { - var state = State.None; - - _communicationManager.RegisterManipulator(id, () => _communicationManager.SetCanWrite(id, true, 1, _ => - _communicationManager.Calibrate(id, () => - _communicationManager.GotoPos(new GotoPositionRequest - { - ManipulatorId = id, - Position = Vector4.zero, - Speed = 5000 - }, - _ => _communicationManager.GotoPos(new GotoPositionRequest - { - ManipulatorId = id, - Position = Vector4.one * 10000, - Speed = 5000 - }, - _ => state = State.Success, _ => state = State.Failed5), - _ => state = State.Failed4), _ => state = State.Failed3), - _ => state = State.Failed2), _ => state = State.Failed); - - yield return new WaitWhile(() => state == State.None); - Assert.That(state, Is.EqualTo(State.Success)); - } - } - - /// - /// Register -> Set Can Write -> Bypass Calibration -> Drive to depth -> Return to home position - /// - /// - [UnityTest] - public IEnumerator TestDriveToDepth() - { - foreach (var id in _manipulators) - { - var state = State.None; - - _communicationManager.RegisterManipulator(id, - () => _communicationManager.SetCanWrite(id, true, 1, - _ => _communicationManager.BypassCalibration(id, - () => _communicationManager.DriveToDepth(id, 0, 5000, - _ => _communicationManager.DriveToDepth(id, 10000, 5000, _ => state = State.Success, - _ => state = State.Failed5), _ => state = State.Failed4), - _ => state = State.Failed3), _ => state = State.Failed2), - _ => state = State.Failed); - - yield return new WaitWhile(() => state == State.None); - Assert.That(state, Is.EqualTo(State.Success)); - } - } - - /// - /// Register -> Bypass Calibration -> Set inside brain state - /// - /// - [UnityTest] - public IEnumerator TestSetInsideBrain() - { - foreach (var id in _manipulators) - { - var state = State.None; - - _communicationManager.RegisterManipulator(id, - () => _communicationManager.BypassCalibration(id, () => _communicationManager.SetInsideBrain(id, - true, _ => state = State.Success, - _ => state = State.Failed3), _ => state = State.Failed2), _ => state = State.Failed); - - yield return new WaitWhile(() => state == State.None); - Assert.That(state, Is.EqualTo(State.Success)); - } - } - - /// - /// Register -> Set Can Write -> Bypass Calibration -> Goto position -> Stop - /// - /// - [UnityTest] - public IEnumerator TestStop() - { - foreach (var id in _manipulators) - { - var state = State.None; - - _communicationManager.RegisterManipulator(id, () => _communicationManager.SetCanWrite(id, true, 1, _ => - _communicationManager.BypassCalibration(id, () => - { - _communicationManager.GotoPos(new GotoPositionRequest - { - ManipulatorId = id, - Position = Vector4.zero, - Speed = 5000 - }, _ => state = State.Failed4, - _ => state = State.Failed4); - _communicationManager.Stop(_ => state = State.Success); - }, _ => state = State.Failed3), _ => state = State.Failed2), _ => state = State.Failed); - - yield return new WaitWhile(() => state == State.None); - Assert.That(state, Is.EqualTo(State.Success)); - } - } - - #endregion - } -} \ No newline at end of file diff --git a/Assets/Tests/CommunicationManagerTests.cs.meta b/Assets/Tests/CommunicationManagerTests.cs.meta deleted file mode 100644 index a105bf5a..00000000 --- a/Assets/Tests/CommunicationManagerTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 41f828f7fc4d4b940aca50e298285dcd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: From 1a80861fe8fa76840bffc66b21ba0ad3ee2cfd27 Mon Sep 17 00:00:00 2001 From: Kenneth Yang Date: Wed, 27 Mar 2024 16:07:14 -0700 Subject: [PATCH 7/7] SetInsideBrain and SetCanWrite --- .../Scripts/EphysLink/CommunicationManager.cs | 15 +- Assets/Scripts/EphysLink/EphysLinkModels.cs | 65 +++++ .../Probes/ManipulatorBehaviorController.cs | 56 +++-- .../UI/EphysCopilot/DrivePanelHandler.cs | 232 ++++++++++-------- .../InsertionSelectionPanelHandler.cs | 98 ++++---- 5 files changed, 294 insertions(+), 172 deletions(-) diff --git a/Assets/Scripts/EphysLink/CommunicationManager.cs b/Assets/Scripts/EphysLink/CommunicationManager.cs index b4970928..261514f6 100644 --- a/Assets/Scripts/EphysLink/CommunicationManager.cs +++ b/Assets/Scripts/EphysLink/CommunicationManager.cs @@ -403,11 +403,10 @@ public void DriveToDepth(DriveToDepthRequest request, Action onSuccessCal /// /// Set the inside brain state of a manipulator. /// - /// ID of the manipulator to set the state of - /// State to set to + /// /// Callback function to handle setting inside_brain state successfully /// Callback function to handle errors - public void SetInsideBrain(string manipulatorId, bool inside, Action onSuccessCallback, + public void SetInsideBrain(InsideBrainRequest request, Action onSuccessCallback, Action onErrorCallback = null) { _connectionManager.Socket.ExpectAcknowledgement(data => @@ -424,7 +423,7 @@ public void SetInsideBrain(string manipulatorId, bool inside, Action onSuc { onErrorCallback?.Invoke($"set_inside_brain invalid response: {data}"); } - }).Emit("set_inside_brain", new InsideBrainInputDataFormat(manipulatorId, inside).ToJson()); + }).Emit("set_inside_brain", ToJson(request)); } /// @@ -466,12 +465,10 @@ public void BypassCalibration(string manipulatorId, Action onSuccessCallback, /// /// Request a write lease for a manipulator. /// - /// ID of the manipulator to allow writing - /// Write state to set the manipulator to - /// How many hours a manipulator may have a write lease + /// /// Callback function to handle successfully setting can_write state /// Callback function to handle errors - public void SetCanWrite(string manipulatorId, bool canWrite, float hours, Action onSuccessCallback, + public void SetCanWrite(CanWriteRequest request, Action onSuccessCallback, Action onErrorCallback = null) { _connectionManager.Socket.ExpectAcknowledgement(data => @@ -488,7 +485,7 @@ public void SetCanWrite(string manipulatorId, bool canWrite, float hours, Action { onErrorCallback?.Invoke($"set_can_write invalid response: {data}"); } - }).Emit("set_can_write", new CanWriteInputDataFormat(manipulatorId, canWrite, hours).ToJson()); + }).Emit("set_can_write", ToJson(request)); } /// diff --git a/Assets/Scripts/EphysLink/EphysLinkModels.cs b/Assets/Scripts/EphysLink/EphysLinkModels.cs index 80d56537..fb0e1c79 100644 --- a/Assets/Scripts/EphysLink/EphysLinkModels.cs +++ b/Assets/Scripts/EphysLink/EphysLinkModels.cs @@ -4,12 +4,24 @@ public struct AngularResponse { public Vector3 Angles; public string Error; + + public AngularResponse(Vector3 angles, string error) + { + Angles = angles; + Error = error; + } } public struct BooleanStateResponse { public bool State; public string Error; + + public BooleanStateResponse(bool state, string error) + { + State = state; + Error = error; + } } public struct CanWriteRequest @@ -17,6 +29,13 @@ public struct CanWriteRequest public string ManipulatorId; public bool CanWrite; public float Hours; + + public CanWriteRequest(string manipulatorId, bool canWrite, float hours) + { + ManipulatorId = manipulatorId; + CanWrite = canWrite; + Hours = hours; + } } public struct DriveToDepthRequest @@ -24,12 +43,25 @@ public struct DriveToDepthRequest public string ManipulatorId; public float Depth; public float Speed; + + public DriveToDepthRequest(string manipulatorId, float depth, float speed) + { + ManipulatorId = manipulatorId; + Depth = depth; + Speed = speed; + } } public struct DriveToDepthResponse { public float Depth; public string Error; + + public DriveToDepthResponse(float depth, string error) + { + Depth = depth; + Error = error; + } } @@ -39,6 +71,14 @@ public struct GetManipulatorsResponse public int NumAxes; public Vector4 Dimensions; public string Error; + + public GetManipulatorsResponse(string[] manipulators, int numAxes, Vector4 dimensions, string error) + { + Manipulators = manipulators; + NumAxes = numAxes; + Dimensions = dimensions; + Error = error; + } } @@ -47,12 +87,25 @@ public struct GotoPositionRequest public string ManipulatorId; public Vector4 Position; public float Speed; + + public GotoPositionRequest(string manipulatorId, Vector4 position, float speed) + { + ManipulatorId = manipulatorId; + Position = position; + Speed = speed; + } } public struct InsideBrainRequest { public string ManipulatorId; public bool Inside; + + public InsideBrainRequest(string manipulatorId, bool inside) + { + ManipulatorId = manipulatorId; + Inside = inside; + } } @@ -60,11 +113,23 @@ public struct PositionalResponse { public Vector4 Position; public string Error; + + public PositionalResponse(Vector4 position, string error) + { + Position = position; + Error = error; + } } public struct ShankCountResponse { public int ShankCount; public string Error; + + public ShankCountResponse(int shankCount, string error) + { + ShankCount = shankCount; + Error = error; + } } diff --git a/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs b/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs index ce9d07bc..c720c518 100644 --- a/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs +++ b/Assets/Scripts/Pinpoint/Probes/ManipulatorBehaviorController.cs @@ -169,16 +169,24 @@ public void Initialize(string manipulatorID, bool calibrated) // Bypass calibration and start echoing CommunicationManager.Instance.BypassCalibration(manipulatorID, StartEchoing); else - CommunicationManager.Instance.SetCanWrite(manipulatorID, true, 1, - _ => - { - CommunicationManager.Instance.Calibrate(manipulatorID, - () => + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = manipulatorID, + CanWrite = true, + Hours = 1 + }, _ => + { + CommunicationManager.Instance.Calibrate(manipulatorID, + () => + { + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest { - CommunicationManager.Instance.SetCanWrite(manipulatorID, false, 0, - _ => StartEchoing()); - }); - }); + ManipulatorId = manipulatorID, + CanWrite = false, + Hours = 0 + }, _ => StartEchoing()); + }); + }); return; void StartEchoing() @@ -302,7 +310,12 @@ public void MoveByWorldSpaceDelta(Vector4 worldSpaceDelta, Action onSucces var targetPosition = pos + new Vector4(manipulatorTransformDelta.x, manipulatorTransformDelta.y, manipulatorTransformDelta.z); // Move manipulator - CommunicationManager.Instance.SetCanWrite(ManipulatorID, true, 1, b => + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = ManipulatorID, + CanWrite = true, + Hours = 1 + }, b => { if (!b) return; CommunicationManager.Instance.GotoPos( @@ -324,8 +337,12 @@ public void MoveByWorldSpaceDelta(Vector4 worldSpaceDelta, Action onSucces }, _ => { - CommunicationManager.Instance.SetCanWrite(ManipulatorID, false, 0, - onSuccessCallback, onErrorCallback); + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = ManipulatorID, + CanWrite = false, + Hours = 0 + }, onSuccessCallback, onErrorCallback); }, onErrorCallback); }, onErrorCallback); }, onErrorCallback); @@ -340,7 +357,12 @@ public void MoveByWorldSpaceDelta(Vector4 worldSpaceDelta, Action onSucces public void MoveBackToZeroCoordinate(Action onSuccessCallback, Action onErrorCallBack) { // Send move command - CommunicationManager.Instance.SetCanWrite(ManipulatorID, true, 1, b => + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = ManipulatorID, + CanWrite = true, + Hours = 1 + }, b => { if (!b) return; CommunicationManager.Instance.GotoPos(new GotoPositionRequest @@ -351,8 +373,12 @@ public void MoveBackToZeroCoordinate(Action onSuccessCallback, Action { - CommunicationManager.Instance.SetCanWrite(ManipulatorID, false, 0, _ => onSuccessCallback(pos), - onErrorCallBack); + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = ManipulatorID, + CanWrite = false, + Hours = 0 + }, _ => onSuccessCallback(pos), onErrorCallBack); }, onErrorCallBack); }, onErrorCallBack); } diff --git a/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs b/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs index b3162ca5..7b526865 100644 --- a/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs +++ b/Assets/Scripts/Pinpoint/UI/EphysCopilot/DrivePanelHandler.cs @@ -406,116 +406,127 @@ public void Drive() // Increment state _driveStateManager.DriveIncrement(); - CommunicationManager.Instance.SetCanWrite(_manipulatorId, true, 1, - canWrite => + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = _manipulatorId, + CanWrite = true, + Hours = 1 + }, canWrite => + { + if (!canWrite) return; + + // Do something based on current state + switch (_driveStateManager.State) { - if (!canWrite) return; - - // Do something based on current state - switch (_driveStateManager.State) - { - case DriveState.DrivingToNearTarget: - // Update status text - _statusText.text = "Driving to " + _drivePastTargetDistance * 1000f + - " µm past target..."; - - // Replace drive buttons with stop - _driveGroup.SetActive(false); - _stopButton.SetActive(true); - - // Drive to near target depth - if (position.w < _nearTargetDepth) - CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest - { - ManipulatorId = _manipulatorId, - Depth = _nearTargetDepth, - Speed = _targetDriveSpeed - }, _ => CompleteAndAdvance(), Debug.LogError); - else - // Already closer than near target depth, so continue - CompleteAndAdvance(); - break; - case DriveState.DrivingToPastTarget: - // Update status text - _statusText.text = "Driving to " + _drivePastTargetDistance * 1000f + - " µm past target..."; - - // Replace drive buttons with stop - _driveGroup.SetActive(false); - _stopButton.SetActive(true); - - // Drive to past target depth - if (position.w < _pastTargetDepth) - CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest - { - ManipulatorId = _manipulatorId, - Depth = _pastTargetDepth, - Speed = _nearTargetDriveSpeed - }, _ => CompleteAndAdvance(), Debug.LogError); - else - // Already further than past target depth, so continue - CompleteAndAdvance(); - break; - case DriveState.ReturningToTarget: - // Update status text - _statusText.text = "Returning to target..."; - - // Replace drive buttons with stop - _driveGroup.SetActive(false); - _stopButton.SetActive(true); - - // Drive to target and complete movement - CommunicationManager.Instance.DriveToDepth( - new DriveToDepthRequest + case DriveState.DrivingToNearTarget: + // Update status text + _statusText.text = "Driving to " + _drivePastTargetDistance * 1000f + + " µm past target..."; + + // Replace drive buttons with stop + _driveGroup.SetActive(false); + _stopButton.SetActive(true); + + // Drive to near target depth + if (position.w < _nearTargetDepth) + CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _nearTargetDepth, + Speed = _targetDriveSpeed + }, _ => CompleteAndAdvance(), Debug.LogError); + else + // Already closer than near target depth, so continue + CompleteAndAdvance(); + break; + case DriveState.DrivingToPastTarget: + // Update status text + _statusText.text = "Driving to " + _drivePastTargetDistance * 1000f + + " µm past target..."; + + // Replace drive buttons with stop + _driveGroup.SetActive(false); + _stopButton.SetActive(true); + + // Drive to past target depth + if (position.w < _pastTargetDepth) + CommunicationManager.Instance.DriveToDepth(new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _pastTargetDepth, + Speed = _nearTargetDriveSpeed + }, _ => CompleteAndAdvance(), Debug.LogError); + else + // Already further than past target depth, so continue + CompleteAndAdvance(); + break; + case DriveState.ReturningToTarget: + // Update status text + _statusText.text = "Returning to target..."; + + // Replace drive buttons with stop + _driveGroup.SetActive(false); + _stopButton.SetActive(true); + + // Drive to target and complete movement + CommunicationManager.Instance.DriveToDepth( + new DriveToDepthRequest + { + ManipulatorId = _manipulatorId, + Depth = _targetDepth, + Speed = _nearTargetDriveSpeed + }, _ => + { + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest { ManipulatorId = _manipulatorId, - Depth = _targetDepth, - Speed = _nearTargetDriveSpeed + CanWrite = false, + Hours = 0 }, _ => { - CommunicationManager.Instance.SetCanWrite(_manipulatorId, false, 0, - _ => - { - _driveStateManager.CompleteMovement(); - - // Complete driving - _statusText.text = "Drive complete"; - _stopButton.SetActive(false); - - // Enable return to surface button - _driveGroup.SetActive(true); - _driveButton.interactable = false; - _exitButton.SetActive(true); - }); - }, Debug.LogError); - break; - case DriveState.Outside: - case DriveState.ExitingToOutside: - case DriveState.AtExitMargin: - case DriveState.ExitingToMargin: - case DriveState.AtDura: - case DriveState.ExitingToDura: - case DriveState.AtNearTarget: - case DriveState.ExitingToNearTarget: - case DriveState.AtPastTarget: - case DriveState.AtTarget: - default: - Debug.LogError("Invalid Drive state for driving: " + _driveStateManager.State); - return; - } - }, Debug.LogError); + _driveStateManager.CompleteMovement(); + + // Complete driving + _statusText.text = "Drive complete"; + _stopButton.SetActive(false); + + // Enable return to surface button + _driveGroup.SetActive(true); + _driveButton.interactable = false; + _exitButton.SetActive(true); + }); + }, Debug.LogError); + break; + case DriveState.Outside: + case DriveState.ExitingToOutside: + case DriveState.AtExitMargin: + case DriveState.ExitingToMargin: + case DriveState.AtDura: + case DriveState.ExitingToDura: + case DriveState.AtNearTarget: + case DriveState.ExitingToNearTarget: + case DriveState.AtPastTarget: + case DriveState.AtTarget: + default: + Debug.LogError("Invalid Drive state for driving: " + _driveStateManager.State); + return; + } + }, Debug.LogError); }, Debug.LogError); return; void CompleteAndAdvance() { - CommunicationManager.Instance.SetCanWrite(_manipulatorId, - false, 0, - _ => - { - _driveStateManager.CompleteMovement(); - Drive(); - }, Debug.LogError); + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = _manipulatorId, + CanWrite = false, + Hours = 0 + }, _ => + { + _driveStateManager.CompleteMovement(); + Drive(); + }, Debug.LogError); } } @@ -527,7 +538,12 @@ public void Exit() // Increment state _driveStateManager.ExitIncrement(); - CommunicationManager.Instance.SetCanWrite(_manipulatorId, true, 1, canWrite => + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = _manipulatorId, + CanWrite = true, + Hours = 1 + }, canWrite => { if (!canWrite) return; @@ -645,7 +661,12 @@ public void Exit() void CompleteAndAdvance() { - CommunicationManager.Instance.SetCanWrite(_manipulatorId, false, 0, _ => + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = _manipulatorId, + CanWrite = false, + Hours = 0 + }, _ => { _driveStateManager.CompleteMovement(); Exit(); @@ -654,7 +675,12 @@ void CompleteAndAdvance() void CompleteOutside() { - CommunicationManager.Instance.SetCanWrite(_manipulatorId, false, 0, _ => + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = _manipulatorId, + CanWrite = false, + Hours = 0 + }, _ => { _driveStateManager.CompleteMovement(); diff --git a/Assets/Scripts/Pinpoint/UI/EphysCopilot/InsertionSelectionPanelHandler.cs b/Assets/Scripts/Pinpoint/UI/EphysCopilot/InsertionSelectionPanelHandler.cs index ca7b1a53..a3d2ebe7 100644 --- a/Assets/Scripts/Pinpoint/UI/EphysCopilot/InsertionSelectionPanelHandler.cs +++ b/Assets/Scripts/Pinpoint/UI/EphysCopilot/InsertionSelectionPanelHandler.cs @@ -390,61 +390,69 @@ private void MoveToTargetInsertion() .dv.APMLDV); // Move - CommunicationManager.Instance.SetCanWrite(ProbeManager.ManipulatorBehaviorController.ManipulatorID, true, 1, - canWrite => - { - if (canWrite) - CommunicationManager.Instance.GotoPos(new GotoPositionRequest - { - ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, - Position = dvPosition, - Speed = ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED - }, _ => - { - CommunicationManager.Instance.GotoPos( - new GotoPositionRequest + CommunicationManager.Instance.SetCanWrite(new CanWriteRequest + { + ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, + CanWrite = true, + Hours = 1 + }, canWrite => + { + if (canWrite) + CommunicationManager.Instance.GotoPos(new GotoPositionRequest + { + ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, + Position = dvPosition, + Speed = ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED + }, _ => + { + CommunicationManager.Instance.GotoPos( + new GotoPositionRequest + { + ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, + Position = apPosition, + Speed = ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED + }, _ => + { + CommunicationManager.Instance.GotoPos(new GotoPositionRequest { ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, - Position = apPosition, + Position = mlPosition, Speed = ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED }, _ => { - CommunicationManager.Instance.GotoPos(new GotoPositionRequest - { - ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, - Position = mlPosition, - Speed = ManipulatorBehaviorController.AUTOMATIC_MOVEMENT_SPEED - }, _ => - { - CommunicationManager.Instance.SetCanWrite( - ProbeManager.ManipulatorBehaviorController.ManipulatorID, false, - 1, _ => - { - // Hide lines - _lineGameObjects.ap.SetActive(false); - _lineGameObjects.ml.SetActive(false); - _lineGameObjects.dv.SetActive(false); - - // Complete movement - EndMovement(); - _moveButton.interactable = false; - }, Debug.LogError); - }, error => - { - Debug.LogError(error); - EndMovement(); - }); + CommunicationManager.Instance.SetCanWrite( + new CanWriteRequest + { + ManipulatorId = ProbeManager.ManipulatorBehaviorController.ManipulatorID, + CanWrite = false, + Hours = 1 + }, _ => + { + // Hide lines + _lineGameObjects.ap.SetActive(false); + _lineGameObjects.ml.SetActive(false); + _lineGameObjects.dv.SetActive(false); + + // Complete movement + EndMovement(); + _moveButton.interactable = false; + }, Debug.LogError); }, error => { Debug.LogError(error); EndMovement(); }); - }, error => - { - Debug.LogError(error); - EndMovement(); - }); - }, Debug.LogError); + }, error => + { + Debug.LogError(error); + EndMovement(); + }); + }, error => + { + Debug.LogError(error); + EndMovement(); + }); + }, Debug.LogError); return; void EndMovement()