如何利用多个环境光传感器联合判别光线方向
最近遇到一个有趣的问题,如何实现对于光线方向的判别?一般来说,环境光传感器只能感受到光的强度,无法获得光线的方向。但是经过调查,环境光传感器输出的数值除了与光照强度有关,还与照射传感器的方向有关。
如下图所示,垂直照射传感器接收平面时响应最大,而光线平行于平面时,则没有读数。可以利用这个特性,将多个传感器组成阵列,联合判别光线方向。
问题描述
现有某个位于 \(x, y\) 的光源,沿负 y 轴方向发射强度为 \(c\) 的光线;
多个传感器间隔 \(x_0\) 一字排开,则第 \(k\) 个传感器位置为 \(kx_0, k=0, 1, 2, \dots\)
传感器响应函数为 \(f(c, \theta)\),其中 \(\theta\) 为入射角度,\(c\) 为入射光强。
为了简化问题,这里考虑了2d的情况,并且认为传感器的响应函数为二次函数:$$f(c, \theta) = c(1-(\frac{2\theta}{\pi})^2)$$
其中 \(\theta = \arctan(\frac{k x_0 - x}{y})\).
要根据每个传感器的值 \(f_k\),获取光源的位置 \(x, y\) 和强度 \(c\)。
解决思路(略)
这个问题其实就是求解非线性的方程组,可以使用非线性最小二乘拟合。
最小二乘即最小化误差的平方和寻找数据的最佳函数匹配。
形式为求得数据与实际数据之间误差的平方和:\(\sum(y_i - f(x_i))^2\)
可以理解为,对于未知的函数 \(f(x)\),有一组自变量 \(x_i\) 对应观测值 \(y_i\)
对于非线性最小二乘,\(f(x)\) 无法表示为线性关系,通常使用迭代法,找一个 \(x_0\),然后不断寻找增量 \(\Delta x\), 使代价函数减小。
在这个问题中,“未知函数”由要求的未知量决定,\(x_i, y_i\) 为传感器序号和传感器数值。
scipy.optimize.curve_fit 是专门用于求解非线性最小二乘的函数🥳,最后我用这个尝试了一下,效果还不错!代码放在这里。
讨论
无噪声
有一定噪声
默认迭代次数内可能无法收敛,可以手动调整 maxfev=5000
;还有,函数设置中,也避免梯度消失的情况,传感器只对入射角度在 \((-\pi/2, \pi/2)\) 内的光线有输出,其余为 0,但是这样设置的话有可能存在梯度消失的问题。
传感器间距、数目越大,分辨率越高。如果光线位置距离传感器来说很远,那么所有的传感器获得的数值相差无几,就会导致估计得到的结果与实际差距很大,或者达到最大迭代次数仍无法求出结果。
容忍噪声的程度取决于噪声是否不会破坏传感器感光的大体趋势,即传感器读数大体上应该根据入射角度的增大而减小,如果噪声干扰了这个趋势就会无法判别。这说明,如果增大传感器间距和数目,也可增强克服噪声的能力。