Leap Motion的坐标系和变换操作(翻译)
Coordinate Systems

A fundamental task when using the Leap Motion controller in an application is mapping the coordinate values received from the controller to the appropriate application-defined coordinate system.

在一个应用里面使用Leap Motion控制器的一个基本的任务是:把从控制器处接收到的基于Leap Motion坐标系下的坐标值,转换到对应的应用内定义的坐标系下。
Leap Motion Coordinates
The Leap Motion Controller provides coordinates in units of real world millimeters within the Leap Motion frame of reference. That is, if a finger tip’s position is given as (x, y, z) = [100, 100, -100], those numbers are millimeters – or, x = +10cm, y = 10cm, z = -10cm.
Leap Motion坐标系是以真实世界中的毫米为单位的。也就是说。如果一个指尖的位置值(x,y,z)是[100,100,-100]的话,则表示其值是在x值为10厘米,y值为10厘米,z值为-10厘米处。
The Leap Controller hardware itself is the center of this frame of reference. The origin is located at the top, center of the hardware. That is if you touch the middle of the Leap Motion controller (and were able to get data) the coordinates of your finger tip would be [0, 0, 0]. The Leap Motion controller uses a right-handed coordinate system.
Leap Motion控制器硬件是居于Leap Motion坐标系的中心。Leap Motion坐标系的原点定位在硬件的顶面中心。也就是说,如果你用手触碰到Leap Motion控制器的中心位置。则获取到你的指尖的位置坐标值为[0,0,0],如下图。显然,Leap Motion控制器使用了一个右手坐标系(译注:拿到Leap Motion实物时,可以参考下图的小绿灯,如果把Leap Motion控制器贴在头戴式VR显示器上的时候,让小绿灯朝上,并且靠近右手边。)
In its normal position, that is on a desk with the user on one side and the computer monitor on the other, the user is “in front” (+z) of the controller and the monitor screen is “behind”(-z) the controller. If the user enables automatic orientation, the Leap Motion software adjusts the coordinate system if the controller is reversed (the green LED is facing away from the user). However, if the user places their controller in a different position (upside down or sideways), the Leap Motion software cannot detect or adjust for this.
在如上图的普通位置下,即把Leap Motion控制器平放在桌面上。用户在控制器的一边,计算机显示器在控制器的另一边。则用户在Leap Motion坐标系的正Z方向处,计算机显示器在负Z轴方向处。如果在Leap Motion控制面板上启动了“自动朝向”选项的话。当Leap Motion控制器位置放反(比如绿色的LED灯不朝向用户)的话,Leap Motion软件会调整坐标系统。当然,如果用户把Leap Motion控制器正反面颠倒或者把它左右颠倒的话,Leap Motion软件则无法检测和调整它。
Design your application to encourage the user to not get too close to the Leap Motion Controller with visual cues; hovering your hands right over the controller increases the chance that fingers and hands will block each other from view.
当设计你的应用的时候,应该提示不要让用户太靠近Leap Motion控制器。把用户的双手悬浮盖在控制器的上面的话,会增加手指之间相互遮挡的可能性。
Mapping Coordinates to your Application
To use information from the Leap Motion device in your application, you have to interpret that data so it makes sense in your application. For example, to map Leap Motion coordinates to application coordinates, you have to decide which axes to use, how much of the Leap Motion field of view to take advantage of, and whether to use an absolute mapping or a relative mapping.
为了使用从Leap Motion设备中获取到的数据信息。你的应用程序必须解析转译成你的应用能够理解的数据。例如,为了把Leap Motion的坐标系映射到你的应用程序的坐标系。你必须决定使用哪个坐标轴,使用多少Leap Motion的视场(field of view)信息,使用绝对映射(absolute mapping)还是相对映射(relative mapping),等等。
For 3D applications, it usually makes sense to use all three axes of the Leap Motion device. For 2D applications, you can often discard one axis, typically the z-axis, and map input from the two remaining axes to the 2D application coordinates.
对于3D应用来说。通常都会直接使用全部3个由Leap Motion设备提供的坐标轴。对2D应用的话,则一般会舍弃掉其中一个,通常是舍弃掉Z轴。只映射剩余的两个坐标轴。
Whether you use two or three axes, you have to decide how much of the Leap Motion range and field of view to use in your application. The field of view is an inverted pyramid. The available range on the x and z axes is much smaller close to the device than it is near the top of the range. If you use too wide a range, or allow too low a height, then the user won’t be able to reach the bottom corners of your application. Consider the following example, which maps the Leap Motion coordinates to the rectangle below (this example requires a plugged-in Leap Motion controller to view):
无论使用多少个Leap Motion提供的坐标值。你都必须决定使用多少“Leap Motion的处理范围(range)”和“视场(field of view)”。视场是一个金字塔形的棱锥体。在X轴和Z轴方向上的有效处理范围(available range)。如果你使用一个太大的处理范围的话,或者使用一个太小的视场高度(即金字塔棱锥体的高度)。则用户将不能达到你的应用的可视范围的底部。试考虑以下的范例:
Notice that when you try to reach the bottom corners, your finger passes out of the device’s field of view and you cannot move the cursor there.
如上图所示,你可考到,当你试图达到底部(也就是两根红线的另一端端点的连线,上图没画出来)的时候,你的手指就已经超过Leap Motion设备的视场范围(也就是说无法检测到手指了)。这个时候你就不能用你的手指移动绿色的光标了。
You also have to decide how to scale the Leap Motion coordinates to suit your application (i.e. how many pixels per millimeter in a 2D application). The greater the scale factor, the more affect a small physical movement will have. This can make it easier for the user to move a pointer, for example, from one side of the application to another, but also makes precise positioning more difficult. You will need to find the best balance between speed and precision for your application.
同时你还需要决定Leap Motion坐标系对应于你的应用的像素比值(scale)。对于一个2D应用来说,就是要决定一毫米对应几个像素值。这个比例值越大,则越小的手部物理上的移动也能影响侦测到,这将会让用户移动一个光标指针越容易。例如,从应用的一端移动到另一端。但同时也会让精确的定位会变得越困难(因为一毫米内像素点会变得更多)。所以你必须选择一个在精度和速度之间的最佳平衡值。
Finally, the difference between coordinate systems may require flipping an axis or three. For example, many 2D window drawing APIs put the origin at the top, left corner of the window, with y values increasing downward. Leap Motion y values increase upwards, so you have to essentially flip the y axis when making the conversion. As another example, the Unity 3D game development system uses a left-handed coordinate system, wheras the Leap Motion software uses a right-handed coordinate system.
最后,把Leap Motion坐标系映射到应用本身的坐标系,坐标轴需要翻转调整下。例如,需要2D的窗口绘图API把坐标系的原点设置在窗口的左上角。Y轴垂直向下为正,而Leap Motion的坐标系的Y轴则是垂直向上为正。因此你需要把Leap Motion坐标系下的Y坐标值取相反数,才是应用本身坐标系下的Y坐标值。另一个例子。Unity3D采用左手坐标系。而Leap Motion坐标系采用右手坐标系,他们之间的转换也需要处理下。
Mapping coordinates is much like converting temperatures from celsius to fahrenheit if you imagine each axis as a scale with corresponding start (freezing) and an end (boiling) points:
You can use this formula to make the conversion:
By changing the start and end points you can change the mapping of coordinates to make movements cover a larger or smaller area in your application. The following example uses this formula on the x and y axes to map an area of the Leap Motion field of view to a rectangular display area. You can play with the controls to set the ranges of the Leap Motion Scale.
If you decrease the range values, a smaller range of physical motion is mapped to the width of the display area, making it easier to move from one side to the other.

The X-center value offsets the center of the X scale to the left or right. Because each hand naturally rests to the right or left of the Leap Motion controller, it can be easier for the user to interact with a full-screen application if you offset the coordinate mapping based on which hand is in use.


The Y-floor slider sets the value on the Leap Motion y axis that maps to the bottom of the display area. A larger value means the user has to hold their hand higher above the controller, which also means that they are more likely to be able to reach the bottom corners.


Enabling the clamp option prevents the cursor from leaving the display area – which can provide a valuable cue to the user as to where they can interact.

A more general method of converting coordinates is to go from the Leap Motion coordinates to a normalized scale running between 0 and 1.0 and then from this normalized scale to the final, application scale. In fact, the InteractionBox class in the Leap Motion API will normalize coordinates for you.
The Interaction Box
The InteractionBox defines a rectilinear area within the Leap Motion field of view.
InteractionBox定义了在Leap Motion的视场范围内定义了一个方格区域,如下图:
As long as the user’s hand or finger stays within this box, it is guaranteed to remain in the Leap Motion field of view. You can use this guarantee in your application by mapping the interaction area of your application to the area defined by the InteractionBox instead of mapping to the entire Leap Motion field of view. The InteractionBox class provides the NormalizePoint() method to help map Leap Motion coordinates to your application coordinates (by first normalizing them to the range [0..1]).
只要用户的手掌或者手指留在此交互盒中,便能保证手掌或者手指一直保留在Leap Motion的视场中。通过把你在应用中定义的交互区域,映射到这个InteractionBox,而不是映射到整个Leap Motion的视场中,便可以保证你的手一定能被Leap Motion识别到。InteractionBox类提供了NormalizePoint方法,此方法可以把Leap Motion的坐标映射到你的应用程序的坐标系上。(该方法首先会把坐标值规格化到[0,1]区域内)
The size of the InteractionBox is determined by the Leap Motion field of view and the user’s interaction height setting (in the Leap Motion control panel). The controller software adjusts the size of the box based on the height to keep the bottom corners within the filed of view. If you set the interaction height higher, then the box becomes larger. Users can set the interaction height based on the height they prefer to hold their hands when using the controller. Some users like to hold their hands much higher above the device than others. By using the InteractionBox to map the Leap Motion coordinate system to your application coordinate system, you can accommodate both types of user. A user can also set the interaction height to adjust automatically. If the user moves his or her hands below the current floor of the interaction box, the controller software lowers the height (until it reaches the minimum height); likewise if the user moves above the interaction box, the controller raises the box.
InteractionBox的大小由Leap Motion视场和“用户交互高度设置值”(user's interaction height setting,在Leap Motion控制面板中指定)去确定。Leap Motion软件将会根据高度值,调整这个交互盒的大小,以保持交互盒的底部的四个角都在Leap Motion的视场内。如果你把用户交互高度设置值设得越高的话,这个交互盒将会变得越大。用户可以根据他们希望手抬得有多高的高度,去对应可以设置这个“用户交互高度设置值”,有些用户喜欢把他们的手抬得更高一些。通过使用交互盒把Leap Motion坐标系映射到你的应用程序的坐标系,你可以适应多种用户。用户也可以自动调整设置用户交互高度值。如果用户把他的手移到交互盒的底部之下,Leap Motion控制软件将会自动地调整这个用户交互高度值——除非到达了最小的高度。同样的,当用户把手移动到交互盒的顶部之上时,控制器软件也会升高这个交互盒。
Because the interaction box can change size and position, every Frame object contains an instance of the InteractionBoxclass. The following example illustrates the behavior of the interaction box. Change your interaction height settings using the Leap Motion control panel to see how it affects the box itself.
因为交互盒会改变它的大小和位置,因此每一帧中,从Leap Motion获取的Frame数据结构都将会包含一个InteractionBox类的对象实例。下面的例子将展现交互盒的行为。通过使用Leap Motion控制器软件,改变你的用户交互高度设置值。你将会看到它如何影响交互盒的大小和位置
You can use the clamp control in this example to see the affect of clamping coordinates when you use the NormalizePoint() function. If you do not clamp, you can get values which are less than zero or greater than one.
Because the interaction box can change over time, be aware that the normalized coordinates of a point measured in one frame may not match the normalized coordinates of the same real world point, when normalized using the interaction box provided by another frame. Thus straight lines or perfect circles “drawn in the air” by the user may not be straight or smooth if they are normalized across frames. For most applications, this isn’t a significant problem, but you should test your application with the Automatic Interaction Height setting enabled if you aren’t sure.
因为交互盒一直都在发生变化,所以必须意识到,在每一帧中获取到的一个Leap Motion的Frame数据结构中的一个点的规格化坐标,不一定与真实世界中的那个点的规格化坐标值一一匹配。当在本帧使用由另外一个frame数据中提供的交互盒数据的话。因而,在空中凭空绘制的一个直线或者一个完美的圆,并不一定是严格直线或者平滑的。对大部分的应用来说,这不是一个很大的问题。但如果你的“自动用户交互设置”(automatic interaction height setting)是打开的话,如果你不确定这个误差会导致什么后果的话,你必须测试你的应用程序。
To guarantee that a set of points tracked across frames is normalized consistently, you can save a single InteractionBox object – ideally the one with the largest height, width, and depth – and use that to normalize all the points.
为了保证每一个通过Leap Motion帧数据获取的点都能被规格化。你可以保存一个拥有最大的长宽高的交互盒。用它来规格化所有的点
Mapping Coordinates with the Interaction Box
To use the interaction box, first normalize the point to be mapped and then convert the normalized coordinates to your application coordinate system. Normalizing converts points within the interaction area to the range [0..1] and moves the origin to the bottom, left, back corner. You can then multiply these normalized coordinates by the maximum range for each axis of your application coordinate system, shifting and inverting the axis as necessary.
Mapping to 2D
For example, most 2D drawing coordinate systems put the origin at the top, left corner of the window – and, naturally, don’t use a z-axis. To map Leap Motion coordinates to such a 2D system, you could use the following code:
int appWidth = 800;
int appHeight = 600;

InteractionBox iBox = leap.Frame().InteractionBox;
if(leap.Frame().Hands.Count > 0){
Hand hand = leap.Frame().Hands[0];
Finger finger = hand.Fingers[1];

Leap.Vector leapPoint = finger.StabilizedTipPosition;
Leap.Vector normalizedPoint = iBox.NormalizePoint(leapPoint, false);

float appX = normalizedPoint.x * appWidth;
float appY = (1 - normalizedPoint.y) * appHeight;
//The z-coordinate is not used