手机测高仪
先了解你将做出什么
应用介绍
学校门口那棵大树有多高?对面的楼有几层楼那么高?
爬上去量显然不现实。但只要站在远处瞄一眼,手机就能算出来——这就是这一篇要做的东西。

这个App用到的数学,就是数学课上讲的正切(tan)。 很多同学学的时候觉得”这玩意儿有什么用”,做完这个App你就知道了: 测量员、建筑师、林业工人量高度,用的就是这个办法。
手机测高仪教程(难度系数:★★☆)
原理:一个直角三角形
想象你站在树前面,眼睛盯着树顶:
- 你离树的水平距离,记作
d(这个你自己量,走过去数步子也行)。 - 你的视线和水平方向的夹角,叫仰角,记作
θ(这个交给手机的传感器读)。 - 你的眼睛离地面的高度,记作
h(一般比身高矮 10 厘米左右)。
你的眼睛、树顶、以及树上和你眼睛齐平的那一点,正好组成一个直角三角形。
在这个三角形里,仰角的对边(树顶比你眼睛高出来的那一段)和邻边(水平距离 d)的比值,
就是 tan θ。所以:
树高 = d × tan(θ) + h
d × tan(θ) 算出的是”比你眼睛高出来的部分”,再加上你眼睛离地的高度 h,才是树的总高。
因为三角形的底边是从你的眼睛出发的,不是从地面出发的。
算出来的 d × tan(θ) 只是树顶比你眼睛高出来的那一截,
你眼睛以下还有一米五左右的树干呢,得补上。
漏掉这一项,量什么都会矮一米多——这是做这类测量App最常见的错误。
认识方向传感器1
方向传感器1能告诉你手机现在是怎么摆着的,它给三个角度:
| 属性 | 含义 | 这个App用不用 |
|---|---|---|
方位角 |
手机朝向哪个方向(东南西北),做指南针用这个 | 不用 |
倾斜角 |
手机前后翻的角度,抬头低头就是它在变 | 用这个 |
翻转角 |
手机左右歪的角度 | 不用 |
我们要的就是 倾斜角(英文 pitch)。手机平放时它接近 0,
把手机立起来往上抬,这个数就会变大。
先把传感器的读数显示出来
不要急着套公式。 做传感器相关的App,第一步永远是”先把读数打到屏幕上看看”, 搞清楚它到底怎么变,再决定怎么用。
global 当前仰角 = 0
global 已锁定 = false
when 方向传感器1.OrientationChanged(azimuth, pitch, roll) {
if not (已锁定) {
当前仰角 = abs(pitch)
标签_角度.Text = join("当前仰角:", round(当前仰角), "°")
}
}
方向改变时 这个事件,只要手机一动就会触发,数字会实时跳。
这里用了 abs() 取绝对值,原因是:不同手机、不同握法,倾斜角可能是正数也可能是负数。
我们只关心”抬起了多少度”,不关心正负,取绝对值最省事。
先把这几行写好,连上 AI伴侣,然后:
- 手机平放在桌上,看看显示多少度?(应该接近 0)
- 手机竖起来,屏幕正对自己,看看多少度?(应该接近 90)
- 慢慢抬起手机,数字是变大还是变小?
每台手机都值得这样试一遍。 如果你发现抬起来数字反而变小,
说明你的手机方向和我们假设的相反,把 abs(pitch) 改成 90 - abs(pitch) 就对了。
这就是为什么要”先看读数再写公式”——传感器这东西,不实测是不能想当然的。
锁定读数
瞄准树顶的时候,眼睛得盯着树,没法同时看屏幕;而且手一移开去点按钮,角度就变了。
所以要有个”锁定“的动作:对准之后点一下按钮,数字就定住不动了。
已锁定 这个变量就是干这个的——上面那段代码里,
只有 not (已锁定) 成立时才更新 当前仰角。锁定之后传感器照样在报数,但我们不理它了。
when 按钮_测量.Click() {
if 已锁定 {
已锁定 = false
按钮_测量.Text = "锁定读数"
标签_结果.Text = "对准目标顶端,然后点按钮"
} else {
已锁定 = true
按钮_测量.Text = "重新瞄准"
算高度()
}
}
一个按钮管两件事:没锁定时点它就锁定并计算,已锁定时点它就解锁重新瞄。 按钮上的字也跟着变,用户不用猜。
套公式算高度
procedure 算高度() {
if isempty(文本输入框_距离.Text) {
标签_结果.Text = "先填上你离目标有多远(米)"
} else if 当前仰角 >= 89 {
标签_结果.Text = "角度太接近垂直了,往后退几步再量"
} else {
标签_结果.Text = join("目标大约高 ",
decimals(文本输入框_距离.Text * tan(当前仰角)
+ choose(isempty(文本输入框_眼高.Text), 1.5, 文本输入框_眼高.Text), 1),
" 米")
}
}
三个分支,两个是在防止算出离谱的结果:
- 距离没填就算不了,先提醒。
- 仰角接近 90 度时
tan会飙到无穷大——你几乎站在树底下往上看, 算出来会是几千米。这时候该提醒用户往后退,而不是给一个荒唐的数字。 - 眼高没填就默认 1.5 米,用
choose(条件, 甲, 乙)一行搞定,不用再写一个 if。
decimals(数值, 1) 是把结果保留一位小数——量个树高报到小数点后八位,没有意义还难看。
tan(89°) ≈ 57,tan(89.9°) ≈ 573,tan(90°) 直接是无穷大。
也就是说你站得离树越近、抬头越狠,误差被放大得越厉害。 稍微抖一下手,结果可能差出几十米。
所以真正的测量作业里有个经验:仰角控制在 30~60 度之间最准。 太小了三角形太扁,太大了 tan 太敏感。你可以把这个建议也做进App里提醒用户。
开始测试
先拿已知高度的东西校准——这是所有测量工具的第一步。
- 找一面墙或者一个门框,先用尺子量出真实高度。
- 退后几米(记下距离),用App瞄准顶端,锁定,看看算出来多少。
- 和真实高度对比,差多少?
按这个顺序查:
- 眼高填了吗? 没填就是默认 1.5,和你的实际眼高差多少?
- 距离量准了吗? 这是误差最大的来源。走路数步子大概每步 0.6~0.75 米, 最好用卷尺或者手机上的测距App量。
- 手机拿稳了吗? 点按钮的一瞬间手一抖,角度就变了。可以把手机靠在什么东西上。
- 角度是不是太大? 退远一点,让仰角落在 30~60 度之间再量。
校准准了之后,再去量大树和楼房。
后记
这个App的精度大概能到 ±10%,量一棵十米的树误差在一米以内—— 对于”这树大概多高”这个问题,完全够用了。
想更准的话,专业的测距仪用的是激光测距 + 角度传感器, 把”距离”这个最大的误差源也自动化了。原理和我们这个是一样的,就是这个三角形。
几个可以继续挖的方向:
- 量宽度。转 90 度用同样的道理,可以量出一栋楼有多宽。
- 两次测量法。如果连距离都不方便量,可以在两个位置各测一次仰角, 用两个方程解出高度——这样连尺子都不用了,去查查”两角测高法”。
- 记录本。把每次测量的地点和结果存进微数据库,做成一个”我量过的高度”清单。
- 做成指南针。方向传感器1的
方位角你还没用过,加个指针图片跟着转, 一个App就有了两个功能。
下次路过一棵特别高的树,掏出手机量一下——用自己写的程序去测量真实世界, 是编程里最有意思的事情之一ヾ(◍°∇°◍)ノ゙
卡在哪一步?直接查操作
不用退出当前教程。速查会在新页面打开,查完回来继续刚才的进度。