private void PollForDeviceConfig() { if (WaitingForDeviceConfig) { #if UNITY_EDITOR bool complete = WearableUSBHasReceivedDeviceConfiguration(); if (complete) { USBDeviceConfiguration config = WearableUSBGetDeviceConfiguration(); _config.updateInterval = WearableTools.MillisecondsToClosestSensorUpdateInterval(config.intervalMilliseconds); _config.accelerometer.isEnabled = config.sensorAccelerometer != 0; _config.gyroscope.isEnabled = config.sensorGyroscope != 0; _config.rotationNineDof.isEnabled = config.sensorRotationNineDof != 0; _config.rotationSixDof.isEnabled = config.sensorRotationSixDof != 0; _config.headNodGesture.isEnabled = config.gestureHeadNod != 0; _config.headShakeGesture.isEnabled = config.gestureHeadShake != 0; _config.doubleTapGesture.isEnabled = config.gestureDoubleTap != 0; _config.touchAndHoldGesture.isEnabled = config.gestureTouchAndHold != 0; _config.inputGesture.isEnabled = config.gestureInput != 0; _config.affirmativeGesture.isEnabled = config.gestureAffirmative != 0; _config.negativeGesture.isEnabled = config.gestureNegative != 0; OnReceivedDeviceConfiguration(_config.Clone()); } #endif } }
internal override void OnUpdate() { if (!_enabled) { return; } // Clear the current frames; _lastSensorFrame will retain its previous value. if (_currentSensorFrames.Count > 0) { _currentSensorFrames.Clear(); } if (_connectedDevice == null) { return; } while (Time.unscaledTime >= _nextSensorUpdateTime) { // If it's time to emit frames, do so until we have caught up. float deltaTime = WearableTools.SensorUpdateIntervalToSeconds(_sensorUpdateInterval); _nextSensorUpdateTime += deltaTime; bool anySensorsEnabled = false; // Update all active sensors if (_sensorStatus[SensorId.Accelerometer]) { UpdateAccelerometerData(); anySensorsEnabled = true; } if (_sensorStatus[SensorId.Gyroscope]) { UpdateGyroscopeData(); anySensorsEnabled = true; } if (_sensorStatus[SensorId.Rotation]) { UpdateRotationSensorData(); anySensorsEnabled = true; } // Emit a gesture if needed bool gestureEmitted = UpdateGestureData(); if (anySensorsEnabled || gestureEmitted) { // Update the timestamp and delta-time and emit _lastSensorFrame.deltaTime = deltaTime; _lastSensorFrame.timestamp = _nextSensorUpdateTime; _currentSensorFrames.Add(_lastSensorFrame); OnSensorsOrGestureUpdated(_lastSensorFrame); } } }
static WearableConstants() { // Ensure that empty frame has a valid rotation quaternion EMPTY_FRAME = new SensorFrame { rotationNineDof = new SensorQuaternion { value = Quaternion.identity }, rotationSixDof = new SensorQuaternion { value = Quaternion.identity } }; CONNECTING_STATES = new List <ConnectionStatus> { ConnectionStatus.FirmwareUpdateRequired, ConnectionStatus.FirmwareUpdateAvailable, ConnectionStatus.Connecting, ConnectionStatus.AutoReconnect, ConnectionStatus.SecurePairingRequired }; EMPTY_DEVICE_LIST = new Device[0]; GESTURE_IDS = (GestureId[])Enum.GetValues(typeof(GestureId)); SENSOR_IDS = (SensorId[])Enum.GetValues(typeof(SensorId)); UPDATE_INTERVALS = (SensorUpdateInterval[])Enum.GetValues(typeof(SensorUpdateInterval)); SIGNAL_STRENGTHS = (SignalStrength[])Enum.GetValues(typeof(SignalStrength)); ACTIVE_NOISE_REDUCTION_MODES = (ActiveNoiseReductionMode[])Enum.GetValues(typeof(ActiveNoiseReductionMode)); EMPTY_ACTIVE_NOISE_REDUCTION_MODES = new ActiveNoiseReductionMode[0]; DEVICE_STATUS_FLAGS = (DeviceStatusFlags[])Enum.GetValues(typeof(DeviceStatusFlags)); OS_PERMISSIONS = (OSPermission[])Enum.GetValues(typeof(OSPermission)); OS_SERVICES = (OSService[])Enum.GetValues(typeof(OSService)); DISABLED_DEVICE_CONFIG = new WearableDeviceConfig(); DISABLED_DEVICE_CONFIG.DisableAllSensors(); DISABLED_DEVICE_CONFIG.DisableAllGestures(); #pragma warning disable 618 DISALLOWED_EDITOR_PROVIDERS = new[] { ProviderId.BluetoothProvider }; DISALLOWED_RUNTIME_PROVIDERS = new[] { ProviderId.USBProvider }; #pragma warning restore 618 DEBUG_PROVIDER_DEFAULT_AVAILABLE_ANR_MODES = new[] { ActiveNoiseReductionMode.Off, ActiveNoiseReductionMode.Low, ActiveNoiseReductionMode.High }; EMPTY_DEVICE_STATUS = new DeviceStatus(); EMPTY_DYNAMIC_DEVICE_INFO = new DynamicDeviceInfo { transmissionPeriod = -1, activeNoiseReductionMode = ActiveNoiseReductionMode.Invalid, availableActiveNoiseReductionModes = WearableTools.GetActiveNoiseReductionModesAsInt(EMPTY_ACTIVE_NOISE_REDUCTION_MODES), controllableNoiseCancellationLevel = 0, controllableNoiseCancellationEnabled = false, totalControllableNoiseCancellationLevels = 0 }; }
internal override void SetDeviceConfiguration(WearableDeviceConfig config) { #if UNITY_EDITOR USBDeviceConfiguration deviceConfig = new USBDeviceConfiguration { intervalMilliseconds = (int)WearableTools.SensorUpdateIntervalToMilliseconds(config.updateInterval), sensorRotationNineDof = config.rotationNineDof.isEnabled ? 1 : 0, sensorRotationSixDof = config.rotationSixDof.isEnabled ? 1 : 0, sensorGyroscope = config.gyroscope.isEnabled ? 1 : 0, sensorAccelerometer = config.accelerometer.isEnabled ? 1 : 0, gestureHeadNod = config.headNodGesture.isEnabled ? 1 : 0, gestureHeadShake = config.headShakeGesture.isEnabled ? 1 : 0, gestureDoubleTap = config.doubleTapGesture.isEnabled ? 1 : 0, gestureTouchAndHold = config.touchAndHoldGesture.isEnabled ? 1 : 0, gestureInput = config.inputGesture.isEnabled ? 1 : 0, gestureAffirmative = config.affirmativeGesture.isEnabled ? 1 : 0, gestureNegative = config.negativeGesture.isEnabled ? 1 : 0 }; WearableUSBSetDeviceConfiguration(deviceConfig); #endif // Assume the configuration succeeded, because it generally will. Failed configs will show up when we poll // for status flags, and adjust the internal config as necessary. _config = config.Clone(); }
internal override void SetSensorUpdateInterval(SensorUpdateInterval updateInterval) { if (_connectedDevice == null) { Debug.LogWarning(WearableConstants.SetUpdateRateWithoutDeviceWarning); return; } _sensorUpdateInterval = updateInterval; // n.b. currently, the only way to set the global update interval is along with a call to EnableSensor. // Until a method is added for this, a suitable workaround is to call EnableSensor on a sensor that is // already enabled. If no sensors are enabled, the cached value will of _sensorUpdateInterval will be // used the next time a sensor is enabled. #if UNITY_EDITOR var enumerator = _sensorStatus.GetEnumerator(); try { while (enumerator.MoveNext()) { KeyValuePair <SensorId, bool> element = enumerator.Current; if (element.Value) { int milliseconds = (int)WearableTools.SensorUpdateIntervalToMilliseconds(_sensorUpdateInterval); WearableUSBEnableSensor((int)element.Key, milliseconds); } } } finally { enumerator.Dispose(); } #endif // UNITY_EDITOR }
private USBAppIntentProfile MakeUSBProfile(AppIntentProfile appIntentProfile) { USBAppIntentProfile usbProfile = new USBAppIntentProfile(); if (appIntentProfile != null) { // Sensors usbProfile.sensorBitmask = 0; for (int i = 0; i < WearableConstants.SensorIds.Length; i++) { SensorId sensor = WearableConstants.SensorIds[i]; // Does this profile require this sensor? if (appIntentProfile.GetSensorInProfile(sensor)) { SensorFlags sensorBit = WearableTools.GetSensorFlag(sensor); usbProfile.sensorBitmask |= (int)sensorBit; } } // Gestures usbProfile.gestureBitmask = 0; for (int i = 0; i < WearableConstants.GestureIds.Length; i++) { GestureId gesture = WearableConstants.GestureIds[i]; // Does this profile require this gesture? if (appIntentProfile.GetGestureInProfile(gesture)) { GestureFlags gestureBit = WearableTools.GetGestureFlag(gesture); usbProfile.gestureBitmask |= (int)gestureBit; } } usbProfile.updateIntervalBitmask = 0; for (int i = 0; i < WearableConstants.UpdateIntervals.Length; i++) { SensorUpdateInterval interval = WearableConstants.UpdateIntervals[i]; // Does this profile require this update interval? if (appIntentProfile.GetIntervalInProfile(interval)) { int intervalBit = WearableTools.SensorUpdateIntervalToBit(interval); usbProfile.updateIntervalBitmask |= intervalBit; } } } return(usbProfile); }
internal override void OnUpdate() { if (!_enabled) { return; } if (Time.unscaledTime >= _nextSensorUpdateTime) { _nextSensorUpdateTime += WearableTools.SensorUpdateIntervalToSeconds(_sensorUpdateInterval); // Update all active sensors if (_sensorStatus[SensorId.Accelerometer]) { UpdateAccelerometerData(); } if (_sensorStatus[SensorId.Gyroscope]) { UpdateGyroscopeData(); } if (_sensorStatus[SensorId.Rotation] || _sensorStatus[SensorId.GameRotation]) { UpdateRotationSensorData(); } UpdateGestureData(); // Update the timestamp and delta-time, then emit the frame _lastSensorFrame.deltaTime = Time.unscaledTime - _lastSensorFrame.timestamp; _lastSensorFrame.timestamp = Time.unscaledTime; _currentSensorFrames.Clear(); _currentSensorFrames.Add(_lastSensorFrame); OnSensorsUpdated(_lastSensorFrame); } else { // Otherwise, the list should be empty. _lastSensorFrame will retain its previous value. if (_currentSensorFrames.Count > 0) { _currentSensorFrames.Clear(); } } }
internal override void StartSensor(SensorId sensorId) { if (_connectedDevice == null) { _sensorStatus[sensorId] = false; Debug.LogWarning(WearableConstants.StartSensorWithoutDeviceWarning); return; } if (_sensorStatus[sensorId]) { return; } #if UNITY_EDITOR int milliseconds = (int)WearableTools.SensorUpdateIntervalToMilliseconds(_sensorUpdateInterval); WearableUSBEnableSensor((int)sensorId, milliseconds); #endif // UNITY_EDITOR _sensorStatus[sensorId] = true; }
/// <summary> /// Get a list of <see cref="ActiveNoiseReductionMode"/>s supported by the device. An empty list will be /// returned if the feature is not supported. /// </summary> /// <returns></returns> public ActiveNoiseReductionMode[] GetAvailableActiveNoiseReductionModes() { return(WearableTools.GetActiveNoiseReductionModesAsList(availableActiveNoiseReductionModes)); }
internal override void OnUpdate() { UpdateVirtualDeviceInfo(); // Report found devices if searching. if (_searchingForDevice && Time.unscaledTime >= _nextDeviceSearchUpdateTime) { _nextDeviceSearchUpdateTime += WearableConstants.DeviceSearchUpdateIntervalInSeconds; if (_verbose) { Debug.Log(WearableConstants.DebugProviderFoundDevices); } var devices = new[] { _virtualDevice }; OnReceivedSearchDevices(devices); } // Handle connection states if (_connectionPhase != ConnectionPhase.Idle && Time.unscaledTime >= _nextConnectionStateTime) { PerformDeviceConnection(); } // Clear the current frames; _lastSensorFrame will retain its previous value. _currentSensorFrames.Clear(); _currentGestureData.Clear(); if (_connectedDevice.HasValue) { // Configuration status if (_waitingToSendConfigSuccess && Time.unscaledTime >= _sendConfigSuccessTime) { _waitingToSendConfigSuccess = false; OnConfigurationSucceeded(); } if (_waitingToSendConfigFailure && Time.unscaledTime >= _sendConfigFailureTime) { _waitingToSendConfigFailure = false; OnConfigurationFailed(ConfigStatus.Failure, ConfigStatus.Failure); } // Device configuration requests if (_waitingToSendConfigRequestResponse && Time.unscaledTime >= _sendConfigRequestResponseTime) { _waitingToSendConfigRequestResponse = false; OnReceivedDeviceConfiguration(_config.Clone()); } // Intent validation if (_waitingToSendIntentValidation && Time.unscaledTime >= _sendIntentValidationTime) { _waitingToSendIntentValidation = false; OnReceivedIntentValidationResponse(_intentResponse); } // Sensor and gesture data while (Time.unscaledTime >= _nextSensorUpdateTime) { // If it's time to emit frames, do so until we have caught up. float deltaTime = WearableTools.SensorUpdateIntervalToSeconds(_config.updateInterval); _nextSensorUpdateTime += deltaTime; // If the service is mock-suspended, don't update any data. Continue to iterate through this loop, // however, so we don't fall behind when the service resumes. Drop all gestures that are pending. if (_dynamicDeviceInfo.deviceStatus.ServiceSuspended) { _pendingGestures.Clear(); continue; } // Check if sensors need to be updated bool anySensorsEnabled = _config.HasAnySensorsEnabled(); // Prepare the frame's timestamp for frame emission if (anySensorsEnabled) { // Update the timestamp and delta-time _lastSensorFrame.deltaTime = deltaTime; _lastSensorFrame.timestamp = _nextSensorUpdateTime; // Simulate movement if (_simulatedMovementMode == MovementSimulationMode.ConstantRate) { // Calculate rotation, which is used by all sensors. if (_rotationType == RotationType.Euler) { _rotation = Quaternion.Euler(_eulerSpinRate * _lastSensorFrame.timestamp); } else if (_rotationType == RotationType.AxisAngle) { _rotation = Quaternion.AngleAxis( _axisAngleSpinRate.w * _lastSensorFrame.timestamp, new Vector3(_axisAngleSpinRate.x, _axisAngleSpinRate.y, _axisAngleSpinRate.z).normalized); } } else { _rotation = Quaternion.identity; } // Update all active sensors, even if motion is not simulated if (_config.accelerometer.isEnabled && _virtualDevice.IsSensorAvailable(SensorId.Accelerometer)) { UpdateAccelerometerData(); } if (_config.gyroscope.isEnabled && _virtualDevice.IsSensorAvailable(SensorId.Gyroscope)) { UpdateGyroscopeData(); } if ((_config.rotationSixDof.isEnabled && _virtualDevice.IsSensorAvailable(SensorId.RotationSixDof)) || (_config.rotationNineDof.isEnabled && _virtualDevice.IsSensorAvailable(SensorId.RotationNineDof))) { UpdateRotationSensorData(); } // Emit the frame _currentSensorFrames.Add(_lastSensorFrame); OnSensorsUpdated(_lastSensorFrame); } // Add any gestures simulated in the past sensor frame. UpdateGestureData(); for (int i = 0; i < _currentGestureData.Count; i++) { OnGestureDetected(_currentGestureData[i].gestureId); } } } // Allow the provider base to do its own update work base.OnUpdate(); }
/// <summary> /// Returns the Product <see cref="VariantType"/> of the device. /// </summary> /// <returns></returns> public VariantType GetVariantType() { return(WearableTools.GetVariantType(GetProductType(), variantId)); }
/// <summary> /// Returns the <see cref="ProductType"/> of the device. /// </summary> /// <returns></returns> public ProductType GetProductType() { return(WearableTools.GetProductType(productId)); }
internal override void OnUpdate() { UpdateVirtualDeviceInfo(); if (!_enabled) { return; } // Clear the current frames; _lastSensorFrame will retain its previous value. if (_currentSensorFrames.Count > 0) { _currentSensorFrames.Clear(); } if (_connectedDevice == null) { return; } while (Time.unscaledTime >= _nextSensorUpdateTime) { // If it's time to emit frames, do so until we have caught up. float deltaTime = WearableTools.SensorUpdateIntervalToSeconds(_sensorUpdateInterval); _nextSensorUpdateTime += deltaTime; // Check if sensors need to be updated bool anySensorsEnabled = false; for (int i = 0; i < WearableConstants.SensorIds.Length; i++) { if (_sensorStatus[WearableConstants.SensorIds[i]]) { anySensorsEnabled = true; break; } } // Emit a gesture if needed bool gestureEmitted = UpdateGestureData(); if (anySensorsEnabled || gestureEmitted) { // Update the timestamp and delta-time _lastSensorFrame.deltaTime = deltaTime; _lastSensorFrame.timestamp = _nextSensorUpdateTime; } if (anySensorsEnabled) { if (_simulateMovement) { // Calculate rotation, which is used by all sensors. if (_rotationType == RotationType.Euler) { _rotation = Quaternion.Euler(_eulerSpinRate * _lastSensorFrame.timestamp); } else if (_rotationType == RotationType.AxisAngle) { _rotation = Quaternion.AngleAxis( _axisAngleSpinRate.w * _lastSensorFrame.timestamp, new Vector3(_axisAngleSpinRate.x, _axisAngleSpinRate.y, _axisAngleSpinRate.z).normalized); } } else { _rotation = Quaternion.identity; } // Update all active sensors, even if motion is not simulated if (_sensorStatus[SensorId.Accelerometer]) { UpdateAccelerometerData(); } if (_sensorStatus[SensorId.Gyroscope]) { UpdateGyroscopeData(); } if (_sensorStatus[SensorId.Rotation]) { UpdateRotationSensorData(); } } // Emit the frame if needed if (anySensorsEnabled || gestureEmitted) { _currentSensorFrames.Add(_lastSensorFrame); OnSensorsOrGestureUpdated(_lastSensorFrame); } } }
public override string ToString() { const string ItemSeparator = ", "; const string NoneLabel = "None"; const string SensorsLabel = "Sensors: "; const string GesturesLabel = "Gestures: "; const string IntervalsLabel = "Intervals: "; const string IntervalFormat = "{0}ms"; if (_stringBuilder == null) { _stringBuilder = new StringBuilder(); } else { _stringBuilder.Length = 0; } _stringBuilder.Append(SensorsLabel); for (int i = 0; i < _sensors.Count; i++) { SensorId id = _sensors[i]; _stringBuilder.Append(_sensors[i].ToString()); if (i != _sensors.Count - 1) { _stringBuilder.Append(ItemSeparator); } } if (_sensors.Count == 0) { _stringBuilder.Append(NoneLabel); } _stringBuilder.AppendLine(); _stringBuilder.Append(IntervalsLabel); for (int i = 0; i < _intervals.Count; i++) { _stringBuilder.AppendFormat( IntervalFormat, ((int)WearableTools.SensorUpdateIntervalToMilliseconds(_intervals[i])).ToString()); if (i != _intervals.Count - 1) { _stringBuilder.Append(ItemSeparator); } } if (_intervals.Count == 0) { _stringBuilder.Append(NoneLabel); } _stringBuilder.AppendLine(); _stringBuilder.Append(GesturesLabel); for (int i = 0; i < _gestures.Count; i++) { _stringBuilder.Append(_gestures[i].ToString()); if (i != _gestures.Count - 1) { _stringBuilder.Append(ItemSeparator); } } if (_gestures.Count == 0) { _stringBuilder.Append(NoneLabel); } return(_stringBuilder.ToString()); }
public override string ToString() { const string ITEM_SEPARATOR = ", "; const string NONE_LABEL = "None"; const string SENSORS_LABEL = "Sensors: "; const string GESTURES_LABEL = "Gestures: "; const string INTERVALS_LABEL = "Intervals: "; const string INTERVAL_FORMAT = "{0}ms"; if (_stringBuilder == null) { _stringBuilder = new StringBuilder(); } else { _stringBuilder.Length = 0; } _stringBuilder.Append(SENSORS_LABEL); for (int i = 0; i < _sensors.Count; i++) { SensorId id = _sensors[i]; _stringBuilder.Append(_sensors[i].ToString()); if (i != _sensors.Count - 1) { _stringBuilder.Append(ITEM_SEPARATOR); } } if (_sensors.Count == 0) { _stringBuilder.Append(NONE_LABEL); } _stringBuilder.AppendLine(); _stringBuilder.Append(INTERVALS_LABEL); for (int i = 0; i < _intervals.Count; i++) { _stringBuilder.AppendFormat( INTERVAL_FORMAT, ((int)WearableTools.SensorUpdateIntervalToMilliseconds(_intervals[i])).ToString()); if (i != _intervals.Count - 1) { _stringBuilder.Append(ITEM_SEPARATOR); } } if (_intervals.Count == 0) { _stringBuilder.Append(NONE_LABEL); } _stringBuilder.AppendLine(); _stringBuilder.Append(GESTURES_LABEL); for (int i = 0; i < _gestures.Count; i++) { _stringBuilder.Append(_gestures[i].ToString()); if (i != _gestures.Count - 1) { _stringBuilder.Append(ITEM_SEPARATOR); } } if (_gestures.Count == 0) { _stringBuilder.Append(NONE_LABEL); } return(_stringBuilder.ToString()); }
/// <summary> /// Returns true if a device supports using a gesture with <see cref="GestureId"/> /// <paramref name="gestureId"/>, otherwise false if it does not. /// </summary> /// <param name="gestureId"></param> /// <returns></returns> public bool IsGestureAvailable(GestureId gestureId) { var gestureFlag = WearableTools.GetGestureFlag(gestureId); return((availableGestures & gestureFlag) == gestureFlag); }
/// <summary> /// Returns true if a device supports using a sensor with <see cref="SensorId"/> /// <paramref name="sensorId"/>, otherwise false if it does not. /// </summary> /// <param name="sensorId"></param> /// <returns></returns> public bool IsSensorAvailable(SensorId sensorId) { var sensorFlag = WearableTools.GetSensorFlag(sensorId); return((availableSensors & sensorFlag) == sensorFlag); }