Skip to content
This repository has been archived by the owner on Jun 14, 2024. It is now read-only.

Enable cancelling localization sessions #247

Merged
merged 14 commits into from
Oct 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace Microsoft.MixedReality.SpatialAlignment
internal class SpatialAnchorsAndroidCoordinateService : SpatialAnchorsCoordinateService
{
private long lastFrameProcessedTimeStamp;
private static object initializeLock = new object();
private static TaskCompletionSource<object> initializeCompletionSource = null;

/// <summary>
/// Instantiates a new <see cref="SpatialAnchorsAndroidCoordinateService"/>.
Expand All @@ -30,7 +32,16 @@ public SpatialAnchorsAndroidCoordinateService(SpatialAnchorsConfiguration spatia
/// <inheritdoc/>
protected override Task OnInitializeAsync()
{
TaskCompletionSource<object> taskCompletionSource = new TaskCompletionSource<object>();
lock (initializeLock)
{
if (initializeCompletionSource != null)
{
Debug.Log("SpatialAnchorsAndroidCoordinateService: initializeCompletionSource already initialized");
return initializeCompletionSource.Task;
}

initializeCompletionSource = new TaskCompletionSource<object>();
}

UnityAndroidHelper.Instance.DispatchUiThread(unityActivity =>
{
Expand All @@ -40,17 +51,18 @@ protected override Task OnInitializeAsync()
using (AndroidJavaClass cloudServices = new AndroidJavaClass("com.microsoft.CloudServices"))
{
cloudServices.CallStatic("initialize", unityActivity);
taskCompletionSource.SetResult(null);
Debug.Log("SpatialAnchorsAndroidCoordinateService: session successfully initialized");
initializeCompletionSource.SetResult(null);
}
}
catch (Exception ex)
{
Debug.LogError($"Exception throw initializing SpatialAnchorAndroidCoordinateService: {ex.ToString()}");
taskCompletionSource.SetException(ex);
initializeCompletionSource.SetException(ex);
}
});

return taskCompletionSource.Task;
return initializeCompletionSource.Task;
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,18 @@ private void Update()
Updated?.Invoke();
}

private class SpatialCoordinateLocalizationSession : DisposableBase, ISpatialLocalizationSession
private class SpatialCoordinateLocalizationSession : SpatialLocalizationSession
{
public IPeerConnection Peer => peerConnection;
/// <inheritdoc/>
public override IPeerConnection Peer => peerConnection;
chrisfromwork marked this conversation as resolved.
Show resolved Hide resolved

private readonly IPeerConnection peerConnection;
private readonly SpatialAnchorsCoordinateService coordinateService;
private readonly SpatialAnchorsConfiguration configuration;
private readonly SpatialAnchorsLocalizer localizer;
private readonly TaskCompletionSource<string> coordinateIdentifierTaskSource;

public SpatialCoordinateLocalizationSession(SpatialAnchorsLocalizer localizer, SpatialAnchorsCoordinateService coordinateService, SpatialAnchorsConfiguration configuration, IPeerConnection peerConnection)
public SpatialCoordinateLocalizationSession(SpatialAnchorsLocalizer localizer, SpatialAnchorsCoordinateService coordinateService, SpatialAnchorsConfiguration configuration, IPeerConnection peerConnection) : base()
{
this.localizer = localizer;
this.coordinateService = coordinateService;
Expand All @@ -116,45 +117,56 @@ private void OnUpdated()
coordinateService.FrameUpdate();
}

public async Task<ISpatialCoordinate> LocalizeAsync(CancellationToken cancellationToken)
/// <inheritdoc/>
public override async Task<ISpatialCoordinate> LocalizeAsync(CancellationToken cancellationToken)
{
ISpatialCoordinate coordinateToReturn = null;
if (configuration.IsCoordinateCreator)
using (var cancellableCTS = CancellationTokenSource.CreateLinkedTokenSource(defaultCancellationToken, cancellationToken))
{
localizer.DebugLog("User getting initialized coordinate");
coordinateToReturn = await coordinateService.TryCreateCoordinateAsync(localizer.anchorPosition, Quaternion.Euler(localizer.anchorRotation), cancellationToken);

localizer.DebugLog($"Sending coordinate id: {coordinateToReturn.Id}");
peerConnection.SendData(writer => writer.Write(coordinateToReturn.Id));

localizer.DebugLog("Message sent.");
}
else
{
localizer.DebugLog("Non-host waiting for coord id to be sent over");
string coordinateIdentifier = await coordinateIdentifierTaskSource.Task.Unless(cancellationToken);

if (!cancellationToken.IsCancellationRequested)
if (configuration.IsCoordinateCreator)
{
localizer.DebugLog($"Coordinate id: {coordinateIdentifier}, starting discovery.");
if (await coordinateService.TryDiscoverCoordinatesAsync(cancellationToken, coordinateIdentifier))
{
localizer.DebugLog("Discovery complete, retrieving reference to ISpatialCoordinate");
if (!coordinateService.TryGetKnownCoordinate(coordinateIdentifier, out coordinateToReturn))
{
Debug.LogError("We discovered, but for some reason failed to get coordinate from service.");
}
localizer.DebugLog("User getting initialized coordinate");
coordinateToReturn = await coordinateService.TryCreateCoordinateAsync(localizer.anchorPosition, Quaternion.Euler(localizer.anchorRotation), cancellableCTS.Token);
if (coordinateToReturn != null)
{
localizer.DebugLog($"Sending coordinate id: {coordinateToReturn.Id}");
peerConnection.SendData(writer => writer.Write(coordinateToReturn.Id));
localizer.DebugLog("Message sent.");
}
else
{
Debug.LogError("Failed to discover spatial coordinate.");
Debug.LogError("Coordinate discovery returned null coordinate");
return null;
}
}
else
{
localizer.DebugLog("Non-host waiting for coord id to be sent over");
string coordinateIdentifier = await coordinateIdentifierTaskSource.Task.Unless(cancellableCTS.Token);

if (!cancellableCTS.Token.IsCancellationRequested)
{
localizer.DebugLog($"Coordinate id: {coordinateIdentifier}, starting discovery.");
if (await coordinateService.TryDiscoverCoordinatesAsync(cancellableCTS.Token, coordinateIdentifier))
{
localizer.DebugLog("Discovery complete, retrieving reference to ISpatialCoordinate");
if (!coordinateService.TryGetKnownCoordinate(coordinateIdentifier, out coordinateToReturn))
{
Debug.LogError("We discovered, but for some reason failed to get coordinate from service.");
}
}
else
{
Debug.LogError("Failed to discover spatial coordinate.");
}
}
}
}

return coordinateToReturn;
}

/// <inheritdoc/>
protected override void OnManagedDispose()
{
base.OnManagedDispose();
Expand All @@ -163,9 +175,10 @@ protected override void OnManagedDispose()
localizer.Updated -= OnUpdated;
}

public void OnDataReceived(BinaryReader reader)
/// <inheritdoc/>
public override void OnDataReceived(BinaryReader reader)
{
coordinateIdentifierTaskSource.SetResult(reader.ReadString());
coordinateIdentifierTaskSource.TrySetResult(reader.ReadString());
}
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ public static Task AsTask(this CancellationToken cancellationToken)
/// <param name="task">The task to await.</param>
/// <param name="cancellationToken">The cancellation token to stop awaiting.</param>
/// <returns>The task that can be awaited unless the cancellation token is triggered.</returns>
public static Task Unless(this Task task, CancellationToken cancellationToken)
public static async Task Unless(this Task task, CancellationToken cancellationToken)
{
return Task.WhenAny(task, cancellationToken.AsTask());
await (await Task.WhenAny(task, cancellationToken.AsTask()));
chrisfromwork marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
Expand All @@ -195,9 +195,16 @@ public static Task Unless(this Task task, CancellationToken cancellationToken)
/// <param name="task">The task to await.</param>
/// <param name="cancellationToken">The cancellation token to stop awaiting.</param>
/// <returns>The task that can be awaited unless the cancellation token is triggered.</returns>
public async static Task<T> Unless<T>(this Task<T> task, CancellationToken cancellationToken)
public static async Task<T> Unless<T>(this Task<T> task, CancellationToken cancellationToken)
{
return (await Task.WhenAny(task, cancellationToken.AsTask())) is Task<T> result ? result.Result : default(T);
Task returnedTask = await Task.WhenAny(task, cancellationToken.AsTask());
if (returnedTask is Task<T> taskWithResult)
{
return await taskWithResult;
}

await returnedTask;
return default;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1969,7 +1969,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 0, a: 1}
m_Color: {r: 1, g: 0, b: 0, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,24 @@ protected void DoStopListening(ref SocketerClient listener)
/// <param name="port">port to use for communication</param>
public void ConnectTo(string serverAddress, int port)
{
if (client != null)
{
if (client.Host == serverAddress &&
client.Port == port)
{
Debug.Log($"Client already created: {client.Host}:{client.Port}");
return;
}
else
{
Debug.Log($"Disconnecting existing client {client.Host}:{client.Port}");
client.Stop();
client.Connected -= OnClientConnected;
client.Disconnected -= OnClientDisconnected;
client = null;
}
}

Debug.LogFormat($"Connecting to {serverAddress}:{port}");
client = SocketerClient.CreateSender(SocketerClient.Protocol.TCP, serverAddress, port);
client.Connected += OnClientConnected;
Expand Down Expand Up @@ -152,6 +170,20 @@ private void OnClientDisconnected(SocketerClient client, int sourceId, string ho
oldConnections.Enqueue(clientConnection);
clientConnection = null;
}

if (!AttemptReconnectWhenClient)
{
Debug.Log("Stopping subscriptions to disconnected client");
client.Stop();
client.Connected -= OnClientConnected;
client.Disconnected -= OnClientDisconnected;

if (this.client == client)
{
Debug.Log("Clearing client cache");
this.client = null;
}
}
}

private void Update()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public interface ISpatialLocalizationSession : IDisposable
/// <returns></returns>
Task<ISpatialCoordinate> LocalizeAsync(CancellationToken cancellationToken);

/// <summary>
/// Call to cancel the localization sessions
/// </summary>
void Cancel();

/// <summary>
/// Call to provide network information
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ public override bool TryDeserializeSettings(BinaryReader reader, out MarkerVisua
return true;
}

private class LocalizationSession : DisposableBase, ISpatialLocalizationSession
private class LocalizationSession : SpatialLocalizationSession
{
public IPeerConnection Peer => peerConnection;
/// <inheritdoc />
public override IPeerConnection Peer => peerConnection;

private readonly MarkerVisualDetectorSpatialLocalizer localizer;
private readonly MarkerVisualDetectorLocalizationSettings settings;
Expand All @@ -54,7 +55,7 @@ private class LocalizationSession : DisposableBase, ISpatialLocalizationSession

private string coordinateId = string.Empty;

public LocalizationSession(MarkerVisualDetectorSpatialLocalizer localizer, MarkerVisualDetectorLocalizationSettings settings, IPeerConnection peerConnection, bool debugLogging = false)
public LocalizationSession(MarkerVisualDetectorSpatialLocalizer localizer, MarkerVisualDetectorLocalizationSettings settings, IPeerConnection peerConnection, bool debugLogging = false) : base()
{
DebugLog("Session created");
this.localizer = localizer;
Expand All @@ -70,49 +71,59 @@ public LocalizationSession(MarkerVisualDetectorSpatialLocalizer localizer, Marke
/// <inheritdoc />
protected override void OnManagedDispose()
{
coordinateService.Dispose();
base.OnManagedDispose();
discoveryCTS.Dispose();
coordinateService.Dispose();
}

/// <inheritdoc />
public async Task<ISpatialCoordinate> LocalizeAsync(CancellationToken cancellationToken)
public override async Task<ISpatialCoordinate> LocalizeAsync(CancellationToken cancellationToken)
{
DebugLog($"Waiting for marker visual, CanBeCanceled:{cancellationToken.CanBeCanceled}, IsCancellationRequested:{cancellationToken.IsCancellationRequested}");
await Task.WhenAny(coordinateAssigned.Task, Task.Delay(-1, cancellationToken));
if (string.IsNullOrEmpty(coordinateId))
if (!defaultCancellationToken.CanBeCanceled)
{
DebugLog("Failed to assign coordinate id");
Debug.LogError("Session is invalid. No localization performed.");
return null;
}

ISpatialCoordinate coordinate = null;
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(discoveryCTS.Token, cancellationToken))
DebugLog($"Waiting for marker visual, CanBeCanceled:{cancellationToken.CanBeCanceled}, IsCancellationRequested:{cancellationToken.IsCancellationRequested}");
using (var cancellableCTS = CancellationTokenSource.CreateLinkedTokenSource(defaultCancellationToken, cancellationToken))
{
DebugLog($"Attempting to discover coordinate: {coordinateId}, CanBeCanceled:{cts.Token.CanBeCanceled}, IsCancellationRequested:{cts.Token.IsCancellationRequested}");
if (await coordinateService.TryDiscoverCoordinatesAsync(cts.Token, new string[] { coordinateId.ToString() }))
await Task.WhenAny(coordinateAssigned.Task, Task.Delay(-1, cancellableCTS.Token));
if (string.IsNullOrEmpty(coordinateId))
{
DebugLog($"Coordinate discovery completed: {coordinateId}");
if (!coordinateService.TryGetKnownCoordinate(coordinateId, out coordinate))
DebugLog("Failed to assign coordinate id");
return null;
}

ISpatialCoordinate coordinate = null;
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(discoveryCTS.Token, cancellableCTS.Token))
{
DebugLog($"Attempting to discover coordinate: {coordinateId}, CanBeCanceled:{cts.Token.CanBeCanceled}, IsCancellationRequested:{cts.Token.IsCancellationRequested}");
if (await coordinateService.TryDiscoverCoordinatesAsync(cts.Token, new string[] { coordinateId.ToString() }))
{
DebugLog("Failed to find spatial coordinate although discovery completed.");
DebugLog($"Coordinate discovery completed: {coordinateId}");
if (!coordinateService.TryGetKnownCoordinate(coordinateId, out coordinate))
{
DebugLog("Failed to find spatial coordinate although discovery completed.");
}
else
{
SendCoordinateFound(coordinate.Id);
return coordinate;
}
}
else
{
SendCoordinateFound(coordinate.Id);
return coordinate;
DebugLog("TryDiscoverCoordinatesAsync failed.");
}
}
else
{
DebugLog("TryDiscoverCoordinatesAsync failed.");
}
}

return null;
}

/// <inheritdoc />
public void OnDataReceived(BinaryReader reader)
public override void OnDataReceived(BinaryReader reader)
{
string command = reader.ReadString();
DebugLog($"Received command: {command}");
Expand Down