vegehunter 发布的文章

参考链接

https://docs.sillytavern.app/installation/docker/


为酒馆创建目录,例如~/sillyTavern,然后创建以下目录

mkdir config data plugins extensions

创建脚本文件start.sh,写入下面的内容并保存,执行脚本(需要魔法),它便开始自动拉取最新的酒馆镜像,映射端口(默认为8000,可自行修改),映射目录,在后台启动容器。

#!/bin/bash
SILLYTAVERN_VERSION="latest"
PUBLIC_PORT="8000"
CONFIG_PATH="./config"
DATA_PATH="./data"
PLUGINS_PATH="./plugins"
EXTENSIONS_PATH="./extensions"

docker run -d \
  --name="sillytavern" \
  -p "$PUBLIC_PORT:8000/tcp" \
  -v "$CONFIG_PATH:/home/node/app/config:rw" \
  -v "$DATA_PATH:/home/node/app/data:rw" \
  -v "$EXTENSIONS_PATH:/home/node/app/public/scripts/extensions/third-party:rw" \
  -v "$PLUGINS_PATH:/home/node/app/plugins:rw" \
  ghcr.io/sillytavern/sillytavern:"$SILLYTAVERN_VERSION"

接下来就可以通过http:127.0.0.1:8000来访问酒馆了。

image.png

被白名单机制屏蔽了,下面显示的被屏蔽的IP是宿主机(也就是网关)在docker默认网络中的IP,我们把这个IP加入到./config/config.yaml中去。

# 找到以下内容,将宿主机IP追加到后面
whitelist:
  - ::1
  - 127.0.0.1

重启容器。

docker container restart sillytavern

image.png

成功。

1. 高斯分布

假定信号传播过程中的噪声,在实部和虚部都是高斯分布的:均值为0,方差为$\sigma^2$,

$$ noise = a + bj \quad, \quad a \sim N(0, \sigma^2), \quad b \sim N(0, \sigma^2) $$

高斯分布的噪声,它的平均功率被称为AWGN(Average White Gaussian Noise),

$$ P_n = 2\sigma^2 $$

对噪声时域序列做傅立叶变换,那么频谱中每一个频率点的噪声复数,同样是高斯分布的,

$$ F(k) = A + Bj \quad, \quad A \sim N(0, \sigma^2), \quad B \sim N(0, \sigma^2) $$


2. 卡方分布

如果我们对噪声傅立叶变换结果(我们只关注其中一个频率点,后文省略符号$k$)取能量(模方),得到能量频谱$C$,

$$ C = A^2 + B^2 $$

令$X = A/\sigma$,$Y = B/\sigma$,则$X$和$Y$就是标准正态分布的。令$Z = X^2 + Y^2$,则$Z$是自由度为2的中心卡方分布,$Z \sim \chi_2^2$。根据自由度为$k$的卡方分布的概率密度$f(x, k)$

$$ f(x, k) = \frac 1{2^{\frac k2}\Gamma(\frac k2)} x^{\frac k2 - 1} e^{-\frac x2} $$

我们可以写出$Z$的概率密度$f_Z(z)$为

$$ f_Z(z) = \frac 12 e^{- \frac z2} $$

由于$C = A^2 + B^2 = \sigma^2 (X^2 + Y^2) = \sigma^2 Z$,所以$C$也服从自由度为2的卡方分布,$C \sim \chi_2^2$,下面推导$C$的概率密度

$$ \begin{align} \int_{\infty} f_C(c) dc &= \int_{\infty} f_Z(z) dz \\ \int_{\infty} f_C(\sigma^2 z) \sigma^2 dz &= \int_{\infty} f_Z(z) dz \\ f_C(\sigma^2 z) \sigma^2 &= \frac 12 e^{- \frac z2} \\ f_C(c) &= \frac 1{2 \sigma^2} e^{- \frac c{2 \sigma^2}} \end{align} $$

这个形式同时也是$\lambda = \frac 1{2 \sigma^2}$的指数分布。


3. Gamma分布

$shape = \alpha$,$velocity = \beta$的$Gamma(\alpha, \beta)$分布的概率密度为

$$ f(x, \alpha, \beta) = \frac {\beta^{\alpha}}{\Gamma(\alpha)} x^{\alpha - 1} e^{-\beta x} \quad,(x \ge 0) $$

参数为$\lambda$的指数分布是Gamma分布的特殊形式,它的$\alpha = 1$,$\beta = \lambda$,那么能量频谱$C$实际上也服从$Gamma(1, \frac 1{2 \sigma^2})$分布。

如果我们对能量频谱进行积分(在离散的场景下对应为求和),定义积分次数为$N$的能量频谱积分$X$为

$$ X = \Sigma_{i = 0}^N C_i $$

由于$C$是$Gamma$分布的,并且$Gamma$分布具有可加性($N$个$Gamma(\alpha, \beta)$分布的随机变量之和服从$Gamma(N\alpha, \beta)$分布),所以能量频谱积分$X$服从$Gamma(N, \frac 1{2 \sigma^2})$分布,我们写出$X$的概率密度,

$$ f(x, N, \frac 1{2 \sigma^2}) = \frac 1{(N - 1)! 2 (\sigma^2)^N} x^{N - 1} e^{-\frac x{2 \sigma^2}} \quad,(x \ge 0) $$

3.1 累积分布函数

累积分布函数CDF(Cumulative Distribution Function)是概率密度从$-\infty$到$x_0$的积分,对于服从$Gamma(N, \frac 1{2 \sigma^2})$分布的$X$来说,CDF为

$$ CDF(x_0, N, \frac 1{2 \sigma^2}) = \int_0^{x_0} f(x, N, \frac 1{2 \sigma^2}) dx $$

积分结果无法用初等函数表示,如果给定概率$P(0 \le x \le x_0)$,我们就暂且把对应的阈值$x_0$使用CDF的反函数表示出来(具体值可以通过数值计算求解)

$$ x_0 = CDF^{-1}(P(0 \le x \le x_0), N, \frac 1{2 \sigma^2}) $$

3.2 尺度变换

$Gamma$分布的尺度因子$\theta$和速率因子$\beta$互为倒数,即$\beta \theta = 1$,对速率因子进行$n$倍缩放,等价于对尺度因子进行$\frac 1n$倍缩放。设$y_1 \sim Gamma(\alpha, \beta)$,$y_2 \sim Gamma(\alpha, n\beta)$,两者的概率密度分别为

$$ \begin{align} f(y_1) &= \frac {\beta^{\alpha}}{\Gamma(\alpha)} y_1^{\alpha - 1} e^{-\beta y_1} \quad,(y_1 \ge 0) \\ g(y_2) &= \frac {(n \beta)^{\alpha}}{\Gamma(\alpha)} y_2^{\alpha - 1} e^{-n\beta y_2} \quad,(y_2 \ge 0) \\ &= n \cdot \frac {\beta^{\alpha}}{\Gamma(\alpha)} (ny_2)^{\alpha - 1} e^{-\beta (n y_2)} \\ &= n \cdot f(ny_2) \end{align} $$

令$\alpha = N$,$\beta = 1$,$n = \frac 1{2 \sigma^2}$,则能量频谱积分$X$的CDF为

$$ \begin{align} CDF(x_0, N, \frac 1{2 \sigma^2}) &= \int_0^{x_0} f(x, N, \frac 1{2 \sigma^2}) dx \\ &= \int_0^{x_0} nf(nx, N, 1) dx \\ &= \int_0^{x_0} f(nx, N, 1) d(nx) \\ &= \int_0^{n x_0} f(y, N, 1) dy \\ &= \int_0^{\frac {x_0}{2 \sigma^2}} f(y, N, 1) dy \\ &= CDF(\frac {x_0}{2 \sigma^2}, N, 1) \\ \end{align} $$

$$ \begin{align} &\therefore \frac {x_0}{2 \sigma^2} = CDF^{-1} (P(0 \le y \le \frac {x_0}{2 \sigma^2}), N, 1) \\ &\because P(0 \le x \le x_0) = P(0 \le y \le \frac {x_0}{2 \sigma^2}) \\ &\therefore x_0 = 2 \sigma^2 \cdot CDF^{-1}(P(0 \le x \le x_0), N, 1) \end{align} $$


4. 虚警率及其门限

定义虚警率$P_{fa}$为:噪声的能量频谱积分$X(k)$在$M$个频率点中的至少一个频率点处的能量积分超过门限值$x_0$的概率。

$$ P_{fa} = 1 - (P(0 \le x \le x_0))^M $$

其中$P(0 \le x \le x_0)$是能量频谱积分在任一频率点处,能量积分的值都不超过$x_0$的概率。若虚警率是给定的常数,则

$$ P(0 \le x \le x_0) = 1 - P_{fa}^{\frac 1M} $$

将这个表达式代入到尺度变换后的能量积分频谱的CDF阈值中,可得阈值$x_0$为

$$ x_0 = 2 \sigma^2 \cdot CDF^{-1}(1 - P_{fa}^{\frac 1M}, N, 1) $$

将噪声的平均功率$P_n$代入上式,

$$ x_0 = P_n \cdot CDF^{-1}(1 - P_{fa}^{\frac 1M}, N, 1) $$

这就是虚警率为$P_{fa}$对应的捕获门限值。其中的CDF反函数值,在虚警率、积分次数和频谱宽度给定的情况下,是与噪声平均功率无关的常数K,我们可以提前用数值求解方法计算出来。

$$ \begin{align} K &= CDF^{-1}(1 - P_{fa}^{\frac 1M}, N, 1) \\ x_0 &= P_n \cdot K \end{align} $$

0. 本文参考链接

https://www.bilibili.com/opus/750451200508297219

https://www.bilibili.com/video/BV1h84y1o7Zp/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click

https://docs.pikvm.org/wol/

https://docs.pikvm.org/faq/

https://github.com/pikvm/pikvm/blob/master/docs/wol.md

https://toolshu.com/docker-mirror


1. 制作PiKVM

1.1 物料和硬件

物品名称作用
orangePi-zeroPiKVM服务器本体。
Micro SD卡作为PiKVM服务器的硬盘。(>=8G)
采集卡被控机的HDMI输出作为输入数据(HDMI输入),同时转发给显示器(HDMI输出)和PiKVM服务器(Micro-USB输出)。
网线将PiKVM服务器接入网络。
USB-typeA to Micro-USB数据线PiKVM模拟键鼠信号,通过USB发送给被控机。
  • orangePi-zero只有一个USB-typeA和一个Micro-USB接口(它同时也是电源输入接口)。
  • 采集卡的Micro-USB连接至orangePi-zero的USB接口传输数据,同时它也给采集卡供电。
  • orangePi-zero需要使用一个USB接口连接至被控机,发送模拟键鼠信号。

考虑到接口数量限制,系统的供电方案分为以下三种:

被控机是否支持关机USB供电有无USB-HUB供电方案
-采集卡的Micro-USB连接至orangePi-zero的USB-typeA,orangePi-zero的Micro-USB连接至被控机的USB-typeA
×orangePi-zero的Micro-USB连接至5V电源,orangePi-zero的USB-typeA连接至USB-HUB,USB-HUB连接至采集卡的Micro-USB和被控机的USB-typeA
××采集卡的Micro-USB连接至orangePi-zero的USB-typeA,使用特制的线缆将orangePi-zero的Micro-USB连接至被控机的USB-typeA,同时连接至5V电源

方案三和它使用的特质线缆制作方法参考这篇B站文章

1.2 下载和烧录镜像

这里下载名称为"v2-hdmiusb-generic-arm-orangepi-zero.img.bz2"的镜像文件,将镜像文件烧录到Micro SD卡中,然后插入到orangePi-zero中,上电开机,等几秒钟后主板上的绿灯亮起,就可以了。


2. 配置用户

在路由器后台找到orangePi-zero的IP地址,直接在浏览器中访问,使用默认用户名admin和默认密码admin登录。

PiKVM_web.png

登陆后,显示了这个页面,选择中间的"Terminal"进入终端。

         _____ _        _  ____      ____  __
        |  __ (_)      | |/ /\ \    / /  \/  |
        | |__) |   __  | ' /  \ \  / /| \  / |
        |  ___/ | (__) |  <    \ \/ / | |\/| |
        | |   | |      | . \    \  /  | |  | |
        |_|   |_|      |_|\_\    \/   |_|  |_|

    Welcome to Pi-KVM - Open Source IP-KVM based on Raspberry Pi
    ____________________________________________________________________________

    The root filesystem of Pi-KVM is mounted in read-only mode by default.
    Use command "rw" to remount it in the RW-mode and "ro" to switch it back.

    To prevent kernel messages from printing to the terminal use "dmesg -n 1".

    To change KVM password use command "kvmd-htpasswd set admin".

    Useful links:
      * https://pikvm.org
      * https://wiki.archlinux.org/index.php/Network_configuration

首先修改root用户密码,默认密码是root。执行下面的命令。

# login root
su
# enter read-write mode
rw
# edit root password
passwd

然后删除掉web管理界面的默认用户admin,创建你自己的用户,并设置密码。

# delete user "admin"
kvmd-htpasswd del admin
# create your user for web-control
kvmd-htpasswd set YourUserName
# restart service
systemctl restart kvmd kvmd-nginx

3. 配置WOL (Wake On Line)

3.1 被控机

以Windows被控机为例,在设备管理器中找到网络适配器,找到网卡设备,右键选择属性。

设备管理器.png

在“高级”选项中,将“关机 网络唤醒”和“魔术封包唤醒”的值修改为“开启”。

高级.png

在“电源管理”选项中,勾选“允许此设备唤醒计算机”。

电源管理.png

3.2 PiKVM

打开文件/etc/kvmd/override.yaml,使用以下内容覆盖该文件。

kvmd:
    wol:
        mac: 38:60:77:cc:ed:b7

其中mac填写你的被控机对应网卡的MAC地址,注意,这里使用的是官方文档给出的单被控机用法,只支持一台被控机WOL(由于系统镜像的原因,ugpio库缺少wol插件,所以目前无法通过官方给出的gpio的方式WOL多台被控机,或许可以使用exec脚本而非gpio的方式实现,有兴趣可以自行研究)。

修改完成后,重启kvmdkvmd-nginx服务。

systemctl restart kvmd kvmd-nginx

在浏览器输入IP重新进入PiKVM控制页面,选择KVM,把右上角的“System”标签展开后可以看到新增了一项“Wake on Line Server”。

WOL.png

点击后,PiKVM就会广播发送魔术包,默认端口号是9,但只有MAC地址与配置文件中一致的设备(被控机)才会执行WOL,其他设备会把包丢弃。

WOL2.png

现在可以看到被控机完成了WOL,并且视频输出正常。

开机.png

开机2.png


4. 在docker部署zerotier(可选)

4.1 安装docker

直接使用可执行文件二进制包,在docker官网找到armhf版本(我们使用的PiKVM镜像OS运行在armv7l架构,32位arm),下载下来。将解压后的可执行文件复制到/usr/local/bin目录中即可使用。

4.2 更换国内可访问的docker镜像源

在配置文件/etc/docker/daemon.json写入以下内容

{
        "registry-mirrors": [
                "https://docker.1ms.run",
                "https://docker.m.ixdev.cn",
                "http://docker.m.daocloud.io",
                "https://dockerproxy.net",
                "https://xdark.top"
        ]
}

重启docker,因为我们是直接使用docker二进制文件,所以只需要将守护进程dockerd杀死,重新执行。

# kill
ps | grep dockerd | awk '{print $1;}' | xargs kill -9
# restart
dockerd &

4.3 部署

为了方便维护,建议在宿主机创建一个配置文件目录(例如/path/to/config),映射到容器中。执行下面的命令创建并运行zerotier容器。

docker run -d \
  --name 容器名称 \
  --restart=always \
  --device=/dev/net/tun \
  --cap-add=NET_ADMIN \
  --network=host \
  -v /path/to/config:/var/lib/zerotier-one \
  zerotier/zerotier:latest \
  你的网络hash

其中,--cap-add=NET_ADMIN给容器控制网络的权限,--network=host让容器使用宿主机的网络命名空间,最后将容器的CMD设置为你的网络hash,这样容器一启动就自动加入网络。

创建好容器后,进入容器的bash,使用下面的命令追踪你自己的私有moon节点。

# enter container
docker exec -it 容器名称或hash bash
# orbit
zerotier-cli orbit 你的moon节点hash 你的moon节点hash

前言

  1. 本文使用的是废旧、无用的光猫,请不要随意修改你现在正常使用的光猫。
  2. 本文仅针对IPv4,未考虑IPv6场景。

准备工作

恢复出厂设置

光猫接通电源后,按住复位键20s左右,所有灯亮起再灭掉,就完成了恢复出厂设置。

网线连接光猫

默认IP地址为192.168.1.1,临时把你电脑的网卡IP地址改为192.168.1.x网段,子网掩码255.255.255.0。使用网线连接该网卡的网口和光猫的任一LAN口。


默认用户名密码

以移动光猫为例。

用户类型用户名密码
普通用户光猫背面光猫背面
超级管理员CMCCAdminaDm8H%MdA

开启telnet

使用ZTE开源工具

开源工具使用方法

假设光猫的IP为192.168.1.1,http服务的端口号为80,使用移动光猫的超级管理员用户名密码

# 开启telnet
./zteOnu.exe --ip 192.168.1.1 --port 80 -u CMCCAdmin --pass aDm8H%MdA --telnet
# 若失败则可以尝试使用针对新版本的方法:先把网卡的MAC地址改为000729553557,再执行下面的命令
./zteOnu.exe --ip 192.168.1.1 --port 80 -u CMCCAdmin --pass aDm8H%MdA --telnet --new

# 查看帮助
./zteOnu.exe -h

成功后显示telnet的默认用户名是root,默认密码是Zte521

ZteONU 0.0.7, built at 2024-10-13T08:29:47Z
source: https://github.com/thank243/zteOnu
-----------------------------------
step [0] reset factory: ok
step [1] request factory mode: ok
step [2] send sq: ok
step [3] check login auth: ok
step [4] enter factory mode: ok
-----------------------------------
Permanent Telnet succeed
user: root, pass: Zte521
wait reboot..

此时光猫会重启,若没有重启则手动重启一下。


连接telnet

使用上述步骤的用户名和密码,通过telnet连接到光猫,执行以下命令

# user用户提权为管理员
sendcmd 1 DB set DevAuthInfo 1 Level 1

# 设置2.4G的ssid前缀为空
sendcmd 1 DB set WLANCfg 0 ESSIDPrefix ""

# 设置5G的ssid前缀为空
sendcmd 1 DB set WLANCfg 4 ESSIDPrefix ""

# 保存配置
sendcmd 1 DB save

这样,普通用户也会具有超级管理员权限,并且wifi名称就可以随意更改了,不必再带有“CMCC”前缀。


光猫后台配置

浏览器访问192.168.1.1,进入光猫后台。

WAN侧配置

  1. 删除多余的WAN连接。
  2. 新增一个IPv4/v6的WAN连接,模式为桥接(bridge)。
  3. 绑定所有LAN端口和2.4G/5G频段的WLAN口,取消DHCP使能。

WLAN配置

设置2.4G和5GHz频段的WLAN名称、密码等。

LAN侧配置

  1. 取消勾选DHCP服务。
  2. 为了方便管理后台,把光猫的IP地址改为与上级路由同一网段(例如上级路由器网段是192.168.233.x,那就需要把光猫的IP改为这个网段内的地址例如192.168.233.233)。

确定修改后,光猫自动重启,以后就可以通过上文设置的IP访问光猫后台了(例如192.168.233.233),记得把你自己的电脑临时改为同一网段的IP(或者DHCP),因为无法跨网段访问。


光猫作为交换机&无线AP使用

把网线从你的电脑拔出(记得恢复你电脑网卡的IP地址获取方式为DHCP,有静态需求的自行配置),把上级路由器的LAN口和光猫的任一LAN口连接。从此以后这个光猫就成为无线AP或者交换机了,可以随时访问光猫的后台。


参考链接

https://post.smzdm.com/p/aqm8r8e7/

1. 观测方程

设GNSS接收机和卫星的位矢分别为

$$ \vec{R_r} = \begin{bmatrix} x_r \\ y_r \\ z_r \\ \end{bmatrix} , \quad \vec{R_s^i} = \begin{bmatrix} x_s^i \\ y_s^i \\ z_s^i \\ \end{bmatrix} $$

其中的$i$表示第$i$颗卫星。

伪距观测量$\rho$是指从卫星到接收机的近似距离,因为它包含了大量的误差(接收机钟差、卫星钟差、电离层延迟误差、对流层延迟误差、相对论效应误差、固体潮海潮误差、多普勒效应误差等),所以它并不严格等于二者的几何距离。

$$ \rho_i = |R_{rs}| + (\delta t_r - \delta t_s^i )c\space + \delta_{ion} + \delta_{tro} + \delta_{rel} + \delta_{tide} + \delta\\_{dop} + \delta_{other} $$

有些误差(例如电离层、对流层等)能够进行数学物理建模然后计算出来,我们尽可能多地把误差都减掉,伪距就会变得更准确一点,为了方便我们把这个量定义为修正伪距$\hat \rho$ 。

$$ \hat \rho = |R_{rs}| + \delta t_r c + \delta_{other} $$

接收机和卫星$i$之间的距离为

$$ |R_{rs}^i| = \sqrt{ (x_r - x_s^i)^2 + (y_r - y_s^i)^2 + (z_r - z_s^i)^2 } $$

我们将修正伪距代入上式,忽略$\delta_{other}$,可得

$$ \sqrt{ (x_r - x_s^i)^2 + (y_r - y_s^i)^2 + (z_r - z_s^i)^2 } + \delta t_rc = \hat \rho_i $$

这个就是GNSS观测方程,其中的卫星坐标可根据广播星历计算出来,所以观测方程仅包含四个未知数:接收机三维坐标和接收机钟差。观测方程想要求解需要至少4个方程,换句话说,至少需要同时存在4颗可观测卫星,接收机才能完成单点定位。


2. 观测方程线性化求解

观测方程是非线性方程,很难求解,我们可以将观测方程左边在接收机位矢$\vec{R_{r_0}}$处进行线性化,换句话说,进行泰勒展开但仅保留一阶项。($\vec{R_{r_0}}$是接收机初值,可以是任意值,只不过当初值越接近真实值,线性化后初值邻域内的函数值也越接近真实值)

$$ \frac {1}{2|R_{r_0s}^i|} ( 2(x_{r_0} - x_s^i)(x_r - x_{r_0}) + 2(y_{r_0} - y_s^i)(y_r - y_{r_0}) + 2(z_{r_0} - z_s^i)(z_r - z_{r_0}) ) + \delta t_r c = \hat \rho_i $$

以$x$项为例,我们注意到$(x_{r_0} - x_s^i) / |R_{r_0s}^i|$其实是以卫星$i$的位矢$\vec{R_s^i}$为起点,以接收机位矢$\vec{R_{r_0}}$为终点的向量$\vec{R_{r_0s}^i}$的方向向量$\vec{e_{r_0s}^i}$在$x$轴方向的分量,我们简单计作$e_x^i$。以及$(x_r - x_{r_0})$是接收机位矢变化量$\Delta \vec R_r$在$x$轴方向的分量。所以观测方程线性化后可写成如下形式

$$ e_x^i \Delta x + e_y^i \Delta y + e_z^i \Delta z + \delta t_r c = \hat \rho_i $$

多颗卫星的观测方程线性化后可组成方程组,写成矩阵形式

$$ \begin{bmatrix} e_x^1 & e_y^1 & e_z^1 & 1 \\ ... & ... & ... & ...\\ e_x^n & e_y^n & e_z^n & 1 \\ \end{bmatrix} \begin{bmatrix} \Delta x \\ \Delta y \\ \Delta z \\ \delta t_r c \end{bmatrix} = \begin{bmatrix} \hat \rho_1 \\ ... \\ \hat \rho_n \end{bmatrix} $$

$$ B \vec X = \vec L $$

为了方便,我们把$\vec X$叫做修正向量。

2.1 无冗余观测

若至少4颗卫星的分布良好,不存在过于靠近、共线等线性相关的情况,则方程的解存在

$$ \vec X = (B^TB)^{-1} B^T \vec L $$

这是比较少见的情况,为了泛用性,我们重点讨论下面的一般情况:有冗余观测。

2.2 有冗余观测(最小二乘)

若除了4颗良好卫星之外,还有冗余观测,则方程大概率无解。定义误差向量为

$$ \vec V = B \vec X - \vec L $$

那么我们的目标就是找到一个$\vec X$使$\vec V$的模长尽可能小,我们很自然地想到可以让$V^TV$的一阶导等于零(因为$V^TV$仅有一个极值点,且该点为最小值点)。

$$ \frac {\partial (V^TV)}{\partial X} = 0 $$

$$ \frac {\partial}{\partial X}(V^TV) = 2 \frac {\partial V}{\partial X}V = 2 \frac {\partial (BX)}{\partial X}V = 2 B^T (BX - L) = 2 (B^TBX - B^TL) = 0 $$

$$ \vec X = (B^TB)^{-1} B^T \vec L $$

这个算法就是最小二乘算法LS的核心步骤:误差平方和最小化。这个解$\vec X$的形式与无冗余观测是一样的。

需要注意的是,这里计算得到的解,是观测方程组线性化之后的解,而不是原观测方程组的解,因为线性化只保留了一阶项。所以直接把$\vec X$代入到原始的观测方程组,方程组一定是不成立的。


3. 迭代求解

在得到修正向量$\vec X$之后,我们就可以将其加到接收机初值上得到更准确的接收机向量

$$ \vec R_r = \vec R_{r_0} + \begin{bmatrix} \Delta x \\ \Delta y \\ \Delta z \end{bmatrix} $$

若进行接收机本地时钟校正,则接收机本地时钟也可以变得更准

$$ t_r = t_{r_0} + \delta t_r $$

把当前接收机向量作为初值,代入到观测方程线性化方程组继续求解,则可以迭代求解接收机向量,当误差小于用户指定的阈值,或达到最大迭代次数,迭代停止,我们就求出了接收机的坐标向量,接收机本地时钟也能够完成校正。


4. 加权最小二乘

观测方程线性化方程组

$$ B \vec X = \vec L $$

误差向量

$$ \vec V = B \vec X - \vec L $$

仅考虑有冗余观测的一般情况,我们在进行最小二乘算法的时候,会希望误差越大的观测对最终结果的贡献越小,反之误差越小对结果的贡献越大。我们可以定义一个权重矩阵(简称权阵)$P$

$$ P = \begin{bmatrix} p_1 & & & 0 \\ & p_2 & & \\ & & ... & \\ 0 & & & p_n \end{bmatrix} $$

权阵为对角矩阵,将$P$引入到最小二乘算法中。

$$ \frac {\partial(V^T P V)}{\partial X} = 0 $$

$$ \frac {\partial(V^T P V)}{\partial X} = \frac {\partial (BX)}{\partial X}PV + \frac {\partial (V^T P^T)}{\partial X}V = B^T PV + B^T P^T V $$

因为权阵$P$是对角矩阵,所以

$$ \frac {\partial(V^T P V)}{\partial X} = 2 B^T P (BX - L) = 0 $$

$$ X = (B^T P B)^{-1}B^T P L $$

4.1 权阵定义

权阵如何定义呢?根据“观测误差小的贡献大”的需求,我们可以选取伪距残差的倒数作为权重,为了只关注误差的相对水平,避免出现过大或过小的数值,我们再把伪距残差倒数进行归一化。

$$ p_i = \frac { \frac 1{|\hat \rho_i - |\vec R_{r_0} - \vec R_s^i||} } { \sum_{j = 1}^n \frac 1{|\hat \rho_j - |\vec R_{r_0} - \vec R_s^j||} } $$