草庐IT

c# - 用倾角计计算重力

coder 2024-05-28 原文

如何将倾角计(俯仰、偏航和滚转)转换为系统在 [X,Y,Z] 中预期的引力?

在特定的 Pitch、Yaw 和 Roll 角度下静止的系统应该在特定的 [X*g,Y*g,Z*g] 处被拉到地面,假设这是为了模拟目的。我想创建一个函数,其输入为 Pitch、Yaw 和 Roll,输出为向下时刻的 Vector3(X,Y,Z)

意味着静止的物体向后向下会从加速度计输出类似 [0,-1,0][pitch,yaw,roll]->[0 ,-1,0],其中 [0,-1,0] 减去 [0,-1,0] 得到 [0 ,0,0]。或者,如果我们以 1g 的速度向左拉,我们就会有一个加速度计显示 [1,-1,0] 使新值 [1,0,0]

系统支持 [pitch,yaw,roll]->[0,-1,0] 函数是我所追求的

Vector3 OriToXYZ(float pitch, float yaw, float roll){
    Vector3 XYZ = Vector.Zero;
    //Simulate what the XYZ should be on a object in this orientation
    //oriented against gravity
    ...
    return XYZ;
}

是的,我知道,因为下面的解释表明我无法根据滚动检测系统是否颠倒,因为滚动只给出(-90 到 90),但这是一个不同的问题。

这就是方向的布局方式。

有关为什么、什么以及如何使用此信息的更多信息,请继续阅读。

计划是通过模拟/计算方向(俯仰、偏航、滚动)的预期重力值,使用增量计替代陀螺仪,以去除加速度计数据中的重力分量。

由于加速度计 (XYZ) 是重力 (XYZ) 和运动 (XYZ) 两个分量的组合,我假设 gravity(XYZ)-calc_g(XYZ) = 0, 允许我执行 accelerometer(XYZ)- calc_g(XYZ) =movement(XYZ)

展示为什么我认为这是可能的。当我绘制手机的值并以某种钟摆运动用力向侧面移动手机时,看起来像正弦/余弦运动的线是倾斜计,其他线是 XYZ 加速度计:

  • red = (Pitch & accell-X)
  • green = (Yaw & accell-Y)
  • blue = (Roll & accell-Z)

加速度值乘以 90,因为它的范围是(-2 到 2),所以它在绘图中的范围是从 -180 到 180,俯仰偏航和滚动范围如上图所示。图片中间是Y = 0,左边是X=0(X=时间)

已解决 Romasz

的解决方案
VectorX = Cos(Pitch)*Sin(Roll);
VectorY = -Sin(Pitch);
VectorZ = -Cos(Pitch)*Cos(Roll);

结果

*图表并非来自同一测量。

最佳答案

(评论后(完全)编辑)

如果你想计算倾斜方向的重力分量,那么你只需要俯仰和滚动(在 WP 约定中)——关于 Z(偏航)的旋转对加速度计没有影响。该公式应如下所示:

VectorX = Cos(Pitch)*Sin(Roll);
VectorY = -Sin(Pitch);
VectorZ = -Cos(Pitch)*Cos(Roll);

(您可以找到类似的公式,例如 herehere )

由于多种原因,准确性可能存在一些问题:

  • 倾角为单精度,加速度为 double
  • 倾角仪可能需要一段时间才能稳定
  • 执行倾斜计和加速度计读数时的不同时间(注意,因为这些传感器具有不同的最小报告间隔)
  • 加速度计的精度取决于它们的位置

另请注意,加速度计可能会过载(其范围为 +-2g)- 例如,如果您拍下手机。


为了测试它,我编写了一个简单的应用程序 ( which you can download here ) - 比较加速度计指示的值和通过倾斜计算的值。因为加速度计的值是相对于重力的,所以很简单:
在 XAML 中 - 几个 TextBlocks:

<Grid x:Name="LayoutRoot" Background="Transparent" Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" VerticalAlignment="Center" Orientation="Horizontal">
            <TextBlock Text="Incliation:" FontSize="16"/>
            <TextBlock Name="incXTB" Margin="10"/>
            <TextBlock Name="incYTB" Margin="10"/>
        </StackPanel>
        <StackPanel Grid.Row="1" VerticalAlignment="Center" Orientation="Horizontal">
            <TextBlock Text="Accelerometers:" FontSize="16"/>
            <TextBlock Name="accXTB" Margin="10"/>
            <TextBlock Name="accYTB" Margin="10"/>
            <TextBlock Name="accZTB" Margin="10"/>
        </StackPanel>
        <StackPanel Grid.Row="2" VerticalAlignment="Center" Orientation="Horizontal">
            <TextBlock Text="Through Inc:" FontSize="16"/>
            <TextBlock Name="accincXTB" Margin="10"/>
            <TextBlock Name="accincYTB" Margin="10"/>
            <TextBlock Name="accincZTB" Margin="10"/>
        </StackPanel>
</Grid>

在后面的代码中:

public partial class MainPage : PhoneApplicationPage
{
    private Inclinometer myIncMeter = null;
    private float inclX = 0;
    private float inclY = 0;

    private Accelerometer myAccel = null;
    private double accX = 0;
    private double accY = 0;
    private double accZ = 0;

    public MainPage()
    {
        InitializeComponent();
        this.DataContext = this;
        myIncMeter = Inclinometer.GetDefault();
        myIncMeter.ReportInterval = myIncMeter.MinimumReportInterval;
        myAccel = Accelerometer.GetDefault();
        myAccel.ReportInterval = myIncMeter.MinimumReportInterval;

        CompositionTarget.Rendering += CompositionTarget_Rendering;
    }

    private void CompositionTarget_Rendering(object sender, EventArgs e)
    {
        InclinometerReading incRead = myIncMeter.GetCurrentReading();
        AccelerometerReading accRead = myAccel.GetCurrentReading();

        accX = accRead.AccelerationX;
        accY = accRead.AccelerationY;
        accZ = accRead.AccelerationZ;

        inclX = incRead.RollDegrees;
        inclY = incRead.PitchDegrees;

        incXTB.Text = "X: " + inclX.ToString("0.00");
        incYTB.Text = "Y: " + inclY.ToString("0.00");

        accXTB.Text = "X: " + accX.ToString("0.00");
        accYTB.Text = "Y: " + accY.ToString("0.00");
        accZTB.Text = "Z: " + accZ.ToString("0.00");

        accincXTB.Text = "X: " + ((Math.Cos(inclY * Math.PI / 180) * Math.Sin(inclX * Math.PI / 180))).ToString("0.00");
        accincYTB.Text = "Y: " + (-Math.Sin(inclY * Math.PI / 180)).ToString("0.00");
        accincZTB.Text = "Z: " + (-(Math.Cos(inclX * Math.PI / 180) * Math.Cos(inclY * Math.PI / 180))).ToString("0.00");
    }
}

关于c# - 用倾角计计算重力,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21462691/

有关c# - 用倾角计计算重力的更多相关文章

  1. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  5. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby - 使用 Ruby,计算 n x m 数组的每一列中有多少个 true 的简单方法是什么? - 2

    给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in

  8. arrays - 计算数组中的匹配元素 - 2

    给定两个大小相等的数组,如何找到不考虑位置的匹配元素的数量?例如:[0,0,5]和[0,5,5]将返回2的匹配项,因为有一个0和一个5共同;[1,0,0,3]和[0,0,1,4]将返回3的匹配项,因为0有两场,1有一场;[1,2,2,3]和[1,2,3,4]将返回3的匹配项。我尝试了很多想法,但它们都变得相当粗糙和令人费解。我猜想有一些不错的Ruby习惯用法,或者可能是一个正则表达式,可以很好地回答这个解决方案。 最佳答案 您可以使用count完成它:a.count{|e|index=b.index(e)andb.delete_at

  9. ruby-on-rails - 如何计算 Ruby/Rails 中 JSON 对象的数量 - 2

    Ruby中如何“一般地”计算以下格式(有根、无根)的JSON对象的数量?一般来说,我的意思是元素可能不同(例如“标题”被称为其他东西)。没有根:{[{"title":"Post1","body":"Hello!"},{"title":"Post2","body":"Goodbye!"}]}根包裹:{"posts":[{"title":"Post1","body":"Hello!"},{"title":"Post2","body":"Goodbye!"}]} 最佳答案 首先,withoutroot代码不是有效的json格式。它将没有包

  10. ruby - 如何计算自 Ruby 中给定日期以来的周数? - 2

    目标我正在尝试计算自给定日期以来周的距离,而无需跳过任何步骤。我更喜欢用普通的Ruby来做,但ActiveSupport无疑是一个可以接受的选择。我的代码我写了以下内容,这似乎可行,但对我来说似乎还有很长的路要走。require'date'DAYS_IN_WEEK=7.0defweeks_sincedate_stringdate=Date.parsedate_stringdays=Date.today-dateweeks=days/DAYS_IN_WEEKweeks.round2endweeks_since'2015-06-15'#=>32.57ActiveSupport的#weeks

随机推荐