/****************************************************************************** * Copyright (C) Ultraleap, Inc. 2011-2023. * * * * Use subject to the terms of the Apache License 2.0 available at * * http://www.apache.org/licenses/LICENSE-2.0, or another agreement * * between Ultraleap and you, your company or other organization. * ******************************************************************************/ using UnityEngine; namespace Leap { using LeapInternal; using System; /// /// The Device class represents a physically connected device. /// /// The Device class contains information related to a particular connected /// device such as device id, field of view relative to the device, /// and the position and orientation of the device in relative coordinates. /// /// The position and orientation describe the alignment of the device relative to the user. /// The alignment relative to the user is only descriptive. Aligning devices to users /// provides consistency in the parameters that describe user interactions. /// /// Note that Device objects can be invalid, which means that they do not contain /// valid device information and do not correspond to a physical device. /// @since 1.0 /// public class Device : IEquatable { /// /// Constructs a default Device object. /// /// Get valid Device objects from a DeviceList object obtained using the /// Controller.Devices() method. /// /// @since 1.0 /// public Device() { } public Device(IntPtr deviceHandle, IntPtr internalHandle, float horizontalViewAngle, float verticalViewAngle, float range, float baseline, DeviceType type, bool isStreaming, uint status, string serialNumber, uint deviceID) { Handle = deviceHandle; HorizontalViewAngle = horizontalViewAngle; VerticalViewAngle = verticalViewAngle; Range = range; Baseline = baseline; Type = type; IsStreaming = isStreaming; SerialNumber = serialNumber; DeviceID = deviceID; UpdateStatus((eLeapDeviceStatus)status); } public Device(IntPtr deviceHandle, IntPtr internalHandle, float horizontalViewAngle, float verticalViewAngle, float range, float baseline, DeviceType type, bool isStreaming, uint status, string serialNumber) : this(deviceHandle, internalHandle, horizontalViewAngle, verticalViewAngle, range, baseline, type, isStreaming, status, serialNumber, 0) { } /// /// For internal use only. /// public void Update( float horizontalViewAngle, float verticalViewAngle, float range, float baseline, uint status, string serialNumber) { HorizontalViewAngle = horizontalViewAngle; VerticalViewAngle = verticalViewAngle; Range = range; Baseline = baseline; SerialNumber = serialNumber; UpdateStatus((eLeapDeviceStatus)status); } /// /// For internal use only. /// public void Update(Device updatedDevice) { HorizontalViewAngle = updatedDevice.HorizontalViewAngle; VerticalViewAngle = updatedDevice.VerticalViewAngle; Range = updatedDevice.Range; Baseline = updatedDevice.Baseline; IsStreaming = updatedDevice.IsStreaming; SerialNumber = updatedDevice.SerialNumber; } /// /// Updates the status fields by parsing the uint given by the event /// internal void UpdateStatus(eLeapDeviceStatus status) { if ((status & eLeapDeviceStatus.eLeapDeviceStatus_Streaming) == eLeapDeviceStatus.eLeapDeviceStatus_Streaming) IsStreaming = true; else IsStreaming = false; if ((status & eLeapDeviceStatus.eLeapDeviceStatus_Smudged) == eLeapDeviceStatus.eLeapDeviceStatus_Smudged) IsSmudged = true; else IsSmudged = false; if ((status & eLeapDeviceStatus.eLeapDeviceStatus_Robust) == eLeapDeviceStatus.eLeapDeviceStatus_Robust) IsLightingBad = true; else IsLightingBad = false; if ((status & eLeapDeviceStatus.eLeapDeviceStatus_LowResource) == eLeapDeviceStatus.eLeapDeviceStatus_LowResource) IsLowResource = true; else IsLowResource = false; } /// /// For internal use only. /// public IntPtr Handle { get; private set; } [Obsolete("Use LeapC.SetLeapPause instead")] public bool SetPaused(bool pause) { return false; } /// /// Compare Device object equality. /// /// Two Device objects are equal if and only if both Device objects represent the /// exact same Device and both Devices are valid. /// /// @since 1.0 /// public bool Equals(Device other) { return SerialNumber == other.SerialNumber; } /// /// A string containing a brief, human readable description of the Device object. /// @since 1.0 /// public override string ToString() { return "Device serial# " + this.SerialNumber; } /// /// The angle in radians of view along the x axis of this device. /// /// The Leap Motion controller scans a region in the shape of an inverted pyramid /// centered at the device's center and extending upwards. The horizontalViewAngle /// reports the view angle along the long dimension of the device. /// /// @since 1.0 /// public float HorizontalViewAngle { get; private set; } /// /// The angle in radians of view along the z axis of this device. /// /// The Leap Motion controller scans a region in the shape of an inverted pyramid /// centered at the device's center and extending upwards. The verticalViewAngle /// reports the view angle along the short dimension of the device. /// /// @since 1.0 /// public float VerticalViewAngle { get; private set; } /// /// The maximum reliable tracking range from the center of this device. /// /// The range reports the maximum recommended distance from the device center /// for which tracking is expected to be reliable. This distance is not a hard limit. /// Tracking may be still be functional above this distance or begin to degrade slightly /// before this distance depending on calibration and extreme environmental conditions. /// /// @since 1.0 /// public float Range { get; private set; } /// /// The distance in mm between the center points of the stereo sensors. /// /// The baseline value, together with the maximum resolution, influence the /// maximum range. /// /// @since 2.2.5 /// public float Baseline { get; private set; } /// /// Reports whether this device is streaming data to your application. /// /// Currently only one controller can provide data at a time. /// @since 1.2 /// public bool IsStreaming { get; internal set; } /// /// The device type. /// /// Use the device type value in the (rare) circumstances that you /// have an application feature which relies on a particular type of device. /// Current types of device include the original Leap Motion peripheral, /// keyboard-embedded controllers, and laptop-embedded controllers. /// /// @since 1.2 /// public DeviceType Type { get; private set; } /// /// An alphanumeric serial number unique to each device. /// /// Consumer device serial numbers consist of 2 letters followed by 11 digits. /// /// When using multiple devices, the serial number provides an unambiguous /// identifier for each device. /// @since 2.2.2 /// public string SerialNumber { get; private set; } /// /// Reports the ID assoicated with the device /// public uint DeviceID { get; private set; } private bool poseSet = false; private Pose devicePose = Pose.identity; /// /// The transform to world coordinates from 3D Leap coordinates. /// public Pose DevicePose { get { if (poseSet) // Assumes the devicePose never changes and so, uses the cached pose. { return devicePose; } //float[] data = new float[16]; //eLeapRS result = LeapC.GetDeviceTransform(Handle, data); //if (result != eLeapRS.eLeapRS_Success || data == null) //{ // devicePose = Pose.identity; // return devicePose; //} //// Get transform matrix and convert to unity space by inverting Z. //Matrix4x4 transformMatrix = new Matrix4x4( // new Vector4(data[0], data[1], data[2], data[3]), // new Vector4(data[4], data[5], data[6], data[7]), // new Vector4(data[8], data[9], data[10], data[11]), // new Vector4(data[12], data[13], data[14], data[15])); //Matrix4x4 toUnity = Matrix4x4.Scale(new Vector3(1, 1, -1)); //transformMatrix = toUnity * transformMatrix; //// Identity matrix here means we have no device transform, also check validity. //if (transformMatrix.isIdentity || !transformMatrix.ValidTRS()) //{ // devicePose = Pose.identity; // return devicePose; //} //// Return the valid pose //devicePose = new Pose(transformMatrix.GetColumn(3), transformMatrix.rotation); poseSet = true; return devicePose; } } /// /// Returns the internal status field of the current device /// protected uint GetDeviceStatus() { eLeapRS result; LEAP_DEVICE_INFO deviceInfo = new LEAP_DEVICE_INFO(); deviceInfo.serial = IntPtr.Zero; deviceInfo.size = (uint)System.Runtime.InteropServices.Marshal.SizeOf(deviceInfo); result = LeapC.GetDeviceInfo(Handle, ref deviceInfo); if (result != eLeapRS.eLeapRS_Success) return 0; uint status = deviceInfo.status; System.Runtime.InteropServices.Marshal.FreeCoTaskMem(deviceInfo.serial); return status; } /// /// The software has detected a possible smudge on the translucent cover /// over the Leap Motion cameras. /// @since 3.0 /// public bool IsSmudged { get; internal set; } /// /// The software has entered low-resource mode /// @since 3.0 /// public bool IsLowResource { get; internal set; } /// /// The software has detected excessive IR illumination, which may interfere /// with tracking. If robust mode is enabled, the system will enter robust mode when /// isLightingBad() is true. /// @since 3.0 /// public bool IsLightingBad { get; internal set; } /// /// The available types of Leap Motion controllers. /// public enum DeviceType { TYPE_INVALID = -1, /// /// A standalone USB peripheral. The original Leap Motion controller device. /// @since 1.2 /// TYPE_PERIPHERAL = (int)eLeapDeviceType.eLeapDeviceType_Peripheral, /// /// Internal research product codename "Dragonfly". /// TYPE_DRAGONFLY = (int)eLeapDeviceType.eLeapDeviceType_Dragonfly, /// /// Internal research product codename "Nightcrawler". /// TYPE_NIGHTCRAWLER = (int)eLeapDeviceType.eLeapDeviceType_Nightcrawler, /// /// Research product codename "Rigel". /// TYPE_RIGEL = (int)eLeapDeviceType.eLeapDevicePID_Rigel, /// /// The Ultraleap Stereo IR 170 (SIR170) hand tracking module. /// TYPE_SIR170 = (int)eLeapDeviceType.eLeapDevicePID_SIR170, /// /// The Ultraleap 3Di hand tracking camera. /// TYPE_3DI = (int)eLeapDeviceType.eLeapDevicePID_3Di, /// /// The Ultraleap Leap Motion Controller 2 hand tracking camera. /// TYPE_LMC2 = (int)eLeapDeviceType.eLeapDevicePID_LMC2 } } }