增强现实第1部分:获取方向数据(译文)
By S.F.
本文链接 https://www.kyfws.com/news/augmented-reality-part-1-getting-orientation-data/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 6 分钟阅读 - 2671 个词 阅读量 0增强现实第1部分:获取方向数据(译文)
原文地址:https://www.codeproject.com/Articles/292145/Augmented-Reality-Part-1-Getting-Orientation-Data
原文作者:Joel Ivory Johnson
译文由本站翻译
前言
获取方向数据
下载代码(382 KB)该博客文章的视频3分钟的代码视频演练
介绍
几天前,我开始开发程序来用手机控制计算机望远镜.在不知不觉中,我发现自己属于增强现实的一部分.我认为如果我将笔记收集在一起共享,可能对其他人有帮助.我也在这篇文章中尝试新的东西.除了博客文章和代码外,我还在上面的链接中以视频形式提供了此信息.视频和这篇文章涵盖了相同的信息. 在开始使用增强现实技术之前,您需要确保自己的设备具有受支持的功能.我在本系列中分享的许多概念都可以应用于其他手机,但是我将专注于Windows Phone并利用其必须提供的功能.如果您想利用这些在其他设备上的帖子中的信息,如果您的设备和开发环境尚未提供某些高级功能,则可能必须查找或实现这些功能. 首先,您将需要一台装有Windows Phone开发人员工具的计算机和一台Windows Phone.并非所有Windows Phone都能正常工作.手机将需要具有GPS硬件和指南针/磁力计.所有Windows手机GPS硬件,但不是所有手机都具有测距仪.有些设备具有测角仪,但没有使第三方开发人员可以使用的驱动程序.在撰写本文时,我有两部装有Mango的手机.我的HD7有一个指南针,但没有必需的驱动程序.我的Samsung Focus确实具有必要的驱动程序.在继续进行之前,请确保您的设备支持毫伏表.如果没有,那么您需要先找到可以使用的设备,然后才能继续进行进一步的开发.
我的手机是否支持所需的API
要测试您的设备,请创建一个新的Windows Phone项目并添加对" Microsoft.Devices.Sensors"的引用.您只需要一行代码即可检查设备是否装有压力计.
bool compassFound = Motion.IsMotionAvailable;
在该行之后设置一个断点,然后在手机上运行该程序(目前,它将始终在模拟器上返回"false").希望它将为您返回"
true`".
获取设备的方向
拥有支持指南针的设备后,让我们获取设备的方向.至少,您的设备中包含一个测力计和一个加速度计.如果是较新的设备,也可能在其中装有陀螺仪.您可以分别从所有这些传感器获取读数,但我们将依靠Motion API从它发现的传感器中获取信息,并使其执行所需的数学运算,以易于使用的形式获取数据.与传感器API交互时,将使用的一般模式是创建一个代表传感器的对象,订阅一个事件以获取有关读数变化的通知,然后调用Start()方法来打开并开始从传感器接收数据.
指南针(以及Motion
API)有时需要校准.除了在有传感器数据时调用的事件之外,还有一个事件用于通知设备需要校准.如果触发了此事件,则需要告诉用户在图8中移动他或她的电话.在对电话进行校准之后,您的应用程序将开始接收读数,并且您可以删除通知.
bool IsMotionAvailable {get; set; }
private Motion _motion;
IsMotionAvailable = Motion.IsSupported;
if (IsMotionAvailable)
{
_motion = new Motion();
_motion.Calibrate += new EventHandler(motion_Calibrate);
_motion.CurrentValueChanged += new EventHandler>(motion_CurrentValueChanged);
_motion.Start();
}
从Motion API返回的信息会告诉我们设备的当前方向和运动/加速度.目前,我们仅关注设备的方向,将忽略其他可用数据.目前,感兴趣的领域是"音高",“偏航”,“滚动"和"量化”.在描述飞机的运动时,还使用了第三个数字.如果飞机正在改变其俯仰角,则意味着计划的前部向上或向下倾斜.如果飞机机翼保持水平,但开始向左或向右移动,则其偏航角正在改变.最后,如果飞机开始向左或向右倾斜,那么我们可以说飞机正在滚动.这些术语以类似的方式应用于电话.如果将设备正面朝上放置在水平桌子上,且设备顶部朝北,则其俯仰,偏航和横滚都将设置为零. (我将其称为"零位置").当您更改设备的方向时,这些字段将相应更改. Motion API返回以弧度为单位的旋转测量值.鉴于.NET Framework中可用的数学函数也可以使用弧度,因此这是有道理的.但是,当在屏幕上显示它们时,使用度会更容易.因此,仅用于显示,我有弧度到度转换器.
public class RadToDegreeConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter,
System.Globalization.CultureInfo culture)
{
double v;
if (value is float)
v = (float)value;
else if (value is double)
v = (double)value;
else if (value is decimal)
v = (double)(decimal)value;
else
return String.Empty;
v = v * 180d / Math.PI;
return v.ToString("000.0");
}
public object ConvertBack(object value,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
返回的" Quanternion"图还包含旋转信息,并且可以通过XNA向量类使用.我仅将"偏航",“俯仰"和"滚动"用于显示目的,但在实际算法中使用了” Quanternion"字段.您的增强现实应用程序将需要知道手机上的摄像头朝向的方向.假设您使用的是后置摄像头,则意味着您将需要知道设备后部朝向的方向.要获取此信息,请先创建一个" Vector3",它表示设备后部在零位置时面向的方向.该向量将随着来自Motion API返回的数据一起旋转,所得的向量将告诉我们设备所面对的方向.
Vector3 DeviceFaceVector = new Vector3(0,0,-10);
Vector CurrentDirectionVector { get; set; }
void motion_CurrentValueChanged(object sender, SensorReadingEventArgs e)
{
var attitude = e.SensorReading.Attitude;
this.Dispatcher.BeginInvoke(() =>
{
IsCalibrated = true;
Pitch = attitude.Pitch;
Yaw = attitude.Yaw;
Roll = attitude.Roll;
CurrentDirectionVector = Vector3.Transform(DeviceFaceVector, attitude.Quaternion);
});
}
" CurrentDirectionVector"将告诉我们设备背面朝向哪个方向.让我们将其从"笛卡尔(x,y,z)“坐标转换为极坐标,以便我们可以显示手机所面对的方向(以北距为单位)和手机所处的天空或地面的角度斜.只需几个函数调用即可完成此转换.
void CalculateAltaAzimuth()
{
double x = CurrentDirectionVector.X;
double y = CurrentDirectionVector.Y;
double z = CurrentDirectionVector.Z;
ViewingAzimuth = Math.Atan2(x, y);
ViewingAltitude = Math.Atan2(z, Math.Sqrt(x*x + y*y));
}
在屏幕上显示值
为了在屏幕上显示这些值,我将使用数据绑定.但我也想将相机的视角用作程序背景.最终,我们将在此背景上叠加图像.要将图像作为背景,请创建一个框架元素(网格,矩形,画布或其他一些元素),该元素会在希望背景显示的屏幕部分上延伸.我将其延伸到整个屏幕.
<Canvas Width="800" Height="480" x:Name="RealityOverlay">
在后面的代码中,我需要制作一个视频画笔,将其用于绘制此表面.视频画笔会将摄像机设置为其来源.
_photoCamera = new PhotoCamera(CameraType.Primary);
VideoBrush vb = new VideoBrush();
vb.SetSource(_photoCamera);
PhotoBackground.Fill = vb;
这使我们知道了如何知道设备的位置.在下一篇文章中,我将展示如何获取到兴趣点的距离和方向.然后,我将展示如何将这些兴趣点投射到屏幕上,使它们看起来像是环境的一部分.
解释以上内容的视频
3分钟代码演练
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# 新闻 翻译