视觉slam第四讲笔记:优化理论基础:李群李代数求导

视觉SLAM第四讲笔记

一.符号说明

R ˙ \dot{R} R˙ :矩阵R的一阶导数
^ \hat{} ^ : 将一个向量变为反对称矩阵,
ˇ \check{} ˇ : 将一个反对称矩阵变为向量
a ^ = A = ( 0 − a 3 a 2 a 3 0 − a 1 − a 2 a 1 0 ) , A ˇ = a \hat{a}= A =\begin{pmatrix} 0 & -a_{3} & a_{2}\\ a_{3} & 0 & -a_{1}\\ -a_{2} & a_{1} & 0 \end{pmatrix},\check{A}=a a^=A=0a3a2a30a1a2a10,Aˇ=a

二.问题:

问题:什么样的相机位姿最符合当前的观测数据?
解决方法:将其构建为优化问题,求解最有的Rt,使得误差最小。旋转矩阵有正交单位的约束,采用李代数可以将其化为无约束的优化问题。
数学模型: 某时刻机器人位姿 T T T,观测到位于世界坐标的 p p p点的数据为 z z z,设观测噪声为 w w w, 则 z = T p + w z=Tp+w z=Tp+w理想情况下为 z = T p z=Tp z=Tp, 故误差为
e = z − T p e=z-Tp e=zTp对于N个点,则有N个式子,需要找出 T T T 满足整体误差最小,即
m i n T J ( T ) = ∑ i = 1 N ∣ ∣ z i − T p i ∣ ∣ 2 2 \underset{T}{min} J(T)=\sum_{i=1}^{N} ||z_i-Tp_i||_{2}^{2} TminJ(T)=i=1NziTpi22因此需要计算 J ( T ) J(T) J(T) 关于 T T T 的导数。

思路

  • 1.用李代数表示姿态,根据李代数加法对李代数求导
  • 2.对李群左乘或右乘微小扰动,对扰动求导。

三.李群和李代数:

3.1李群

特殊正交群:旋转矩阵的集合: S O ( n ) SO(n) SO(n)= { R ∈ R n × n ∣ R R T = I , d e t ( R ) = 1 R\in \mathbb{R}^{n\times n}|RR^{^{T}}=I,det(R)=1 RRn×nRRT=I,det(R)=1 }
特殊欧氏群:变换矩阵的集合: S E ( 3 ) SE(3) SE(3)= { T = T= T= ( R t 0 T 1 ) ∈ R 4 × 4 \begin{pmatrix} R & t \\0^T & 1\end{pmatrix}\in \mathbb{R}^{4\times 4} (R0Tt1)R4×4| R ∈ S O ( 3 ) , t ∈ R 3 R\in SO(3),t\in \mathbb{R}^{3} RSO(3),tR3}
:一种集合只有一种运算的代数结构
李群:具有连续(光滑)性质的群

3.2李代数的引出

根据旋转矩阵的性质, R R T = I RR^T=I RRT=I,对两边分别求导,可知
R ( t ) ˙ R ( t ) T = − ( R ( t ) ˙ R ( t ) T ) T \dot{R(t)}R(t)^T =-(\dot{R(t)}R(t)^T)^T R(t)˙R(t)T=(R(t)˙R(t)T)T即为反对称矩阵,故根据符号说明处,可以找到一个与之对应的三维向量
R ( t ) ˙ R ( t ) T = ϕ ( t ) ^ \dot{R(t)}R(t)^T =\hat{\phi(t)} R(t)˙R(t)T=ϕ(t)^所以 R ( t ) ˙ = ϕ ( t ) ^ R ( t ) = ( 0 − ϕ 3 ϕ 2 ϕ 3 0 − ϕ 1 − ϕ 2 ϕ 1 0 ) R ( t ) \dot{R(t)}=\hat{\phi(t)}R(t)=\begin{pmatrix}0 & -\phi_{3} & \phi_{2}\\ \phi_{3} & 0 & -\phi_{1}\\ -\phi_{2} & \phi_{1} & 0 \end{pmatrix}R(t) R(t)˙=ϕ(t)^R(t)=0ϕ3ϕ2ϕ30ϕ1ϕ2ϕ10R(t)
可以看出,每次对 R R R 求导只需要左乘 ϕ ^ ( t ) \hat\phi(t) ϕ^(t)
R ( t ) 在 t = t 0 R(t)在t=t_{0} R(t)t=t0时刻进行泰勒展开:
R ˙ = ϕ ^ ( t 0 ) R ( t ) = ϕ ^ 0 R ( t ) \dot{R}=\hat\phi(t_{0})R(t)=\hat\phi_{0}R(t) R˙=ϕ^(t0)R(t)=ϕ^0R(t)解得:
R ( t ) = e x p ( ϕ ^ 0 t ) R(t) = exp(\hat\phi_{0}t) R(t)=exp(ϕ^0t)该泰勒展开只在t=0附近有效。
效果:旋转矩阵和反对称矩阵通过指数关系联系在一起。即当某个时刻的R已知,可以求得向量 ϕ \phi ϕ描述R在局部的导数关系 ϕ \phi ϕ即李代数。

3.3李代数:

每个李群都有相应的李代数,李代数描述了李群的局部性质。
李代数=1个集合+1个数域+1个二元运算[,]组成.

李代数 s o ( 3 ) \mathfrak{so(3)} so(3)

定义在 R 3 \mathbb{R}^{3} R3上的向量, ϕ \phi ϕ S O ( 3 ) SO(3) SO(3)对应的李代数。
因为每个向量 ϕ \phi ϕ对应一个反对称矩阵 Φ = ϕ ^ = ( 0 − ϕ 3 ϕ 2 ϕ 3 0 − ϕ 1 − ϕ 2 ϕ 1 0 ) \Phi =\hat\phi=\begin{pmatrix}0 & -\phi_{3} & \phi_{2}\\\phi_{3} & 0 & -\phi_{1}\\ -\phi_{2} & \phi_{1} & 0 \end{pmatrix} Φ=ϕ^=0ϕ3ϕ2ϕ30ϕ1ϕ2ϕ10定义李代数运算,即两个向量 ϕ 1 , ϕ 2 \phi_{1},\phi_{2} ϕ1,ϕ2的李括号为:
[ ϕ 1 , ϕ 2 ] = ( Φ 1 Φ 2 − Φ 2 Φ 1 ) ˇ [\phi_{1},\phi_{2}]=\check{(\Phi_{1}\Phi_{2}-\Phi_{2}\Phi_{1}) } [ϕ1,ϕ2]=(Φ1Φ2Φ2Φ1)ˇ
李代数 s o ( 3 ) \mathfrak{so(3)} so(3)小结
集合 s o ( 3 ) \mathfrak{so(3)} so(3)的元素是三维向量或者三维反对称矩阵,可以表示旋转矩阵的导数:
s o ( 3 ) = { ϕ ∈ R 3 , Φ = ϕ ^ ∈ R 3 × 3 } \mathfrak{so(3)}=\{\phi\in \mathbb{R}^{3},\Phi =\hat\phi\in \mathbb{R}^{3\times 3}\} so(3)={ϕR3,Φ=ϕ^R3×3}
并且和特殊正交群 S O ( n ) SO(n) SO(n)的关系为 R = e x p ( ϕ ^ ) R = exp(\hat\phi) R=exp(ϕ^)

李代数 s e ( 3 ) \mathfrak{se(3)} se(3)

位于 R 6 \mathbb{R}^{6} R6空间中,为特殊欧氏群 S E ( 3 ) SE(3) SE(3)对应的李代数
s e ( 3 ) = { ξ = ( ρ ϕ ) ∈ R 6 , ρ ∈ R 3 , ϕ ∈ s o ( 3 ) , ξ ^ = ( ϕ ^ ρ 0 T 0 ) ∈ R 4 × 4 } \mathfrak{se(3)}= \{ \xi=\begin{pmatrix} \rho \\ \phi \end{pmatrix} \in \mathbb{R}^{6},\rho \in \mathbb{R}^{3},\phi\in \mathfrak{so(3)} ,\hat{\xi}= \begin{pmatrix} \hat{\phi} & \rho \\ 0^T & 0 \end{pmatrix}\in \mathbb{R}^{4 \times 4}\} se(3)={ξ=(ρϕ)R6,ρR3,ϕso(3),ξ^=(ϕ^0Tρ0)R4×4}
元素 ξ \xi ξ 为六维向量, ρ \rho ρ表示平移(不是直接的平移),, ϕ \phi ϕ表示旋转, ξ ^ \hat{\xi} ξ^表示将六维向量转为四维矩阵,此处不再表示反对称
李代数 s e ( 3 ) \mathfrak{se(3)} se(3)对应的运算为:
[ ξ 1 , ξ 2 ] = { ξ 1 ^ ξ 2 ^ − ξ 2 ^ ξ 1 ^ ˇ } [\xi_{1},\xi_{2}]=\{\check{\hat{\xi_{1}}\hat{\xi_{2}}-\hat{\xi_{2}}\hat{\xi_{1}}}\} [ξ1,ξ2]={ξ1^ξ2^ξ2^ξ1^ˇ}

四.指数和对数映射

问题:由前面已知 R = e x p ( ϕ ^ ) R = exp(\hat\phi) R=exp(ϕ^),问题:如何计算矩阵的指数 e x p ( ϕ ^ ) exp(\hat\phi) exp(ϕ^)
定义:矩阵的指数:指数映射

李代数 s o ( 3 ) \mathfrak{so(3)} so(3)的指数映射

因为,任意矩阵 A A A 的指数映射为 e x p ( A ) = ∑ n = 0 ∞ 1 n ! A n exp(A)=\sum_{n=0}^{\infty}\frac{1}{n!}A^n exp(A)=n=0n!1An所以对 s o ( 3 ) \mathfrak{so(3)} so(3)中的任意元素 ϕ \phi ϕ对应的三维矩阵 ϕ ^ \hat\phi ϕ^可以定义指数映射为
R = e x p ( ϕ ^ ) = ∑ n = 0 ∞ 1 n ! ( ϕ ^ ) n R=exp(\hat\phi)=\sum_{n=0}^{\infty}\frac{1}{n!}(\hat\phi)^n R=exp(ϕ^)=n=0n!1(ϕ^)n对于三维向量 ϕ \phi ϕ定义模长和方向表示为 ϕ = θ a \phi=\theta a ϕ=θa,其中 a a a为单位向量,带入上式 ϕ ^ = θ a ^ \hat\phi=\theta \hat a ϕ^=θa^,则
e x p ( ϕ ^ ) = e x p ( θ a ^ ) = ∑ n = 0 ∞ 1 n ! ( θ a ^ ) n = cos ⁡ θ I + ( 1 − cos ⁡ θ ) a a T + sin ⁡ θ a ^ exp(\hat\phi)=exp(\theta \hat a)=\sum_{n=0}^{\infty}\frac{1}{n!}(\theta \hat a)^n=\cos\theta I+(1-\cos\theta)aa^T+\sin \theta \hat a exp(ϕ^)=exp(θa^)=n=0n!1(θa^)n=cosθI+(1cosθ)aaT+sinθa^
上式和Rodrigues变换一致,说明: s o ( 3 ) \mathfrak{so(3)} so(3)旋转向量组成的空间,其中的元素为旋转向量,其对应的指数映射为Rodrigues变换。通过上式,可以将李代数 s o ( 3 ) \mathfrak{so(3)} so(3)中的任一旋转向量对应到 S O ( 3 ) SO(3) SO(3)的旋转矩阵。

定义对数映射:
ϕ = l n ( R ) ˇ = ( ∑ 0 ∞ ( − 1 ) n n + 1 ( R − I ) n + 1 ) ˇ \phi = ln\check{(R)}=(\sum_{0}^{\infty}\tfrac{(-1)^n}{n+1}(R-I)^{n+1})\check{} ϕ=ln(R)ˇ=(0n+1(1)n(RI)n+1)ˇ


小结李代数是旋转向量,指数映射为旋转向量到旋转矩阵的Rodrigues变换,对数映射是旋转矩阵到旋转向量的运算,旋转矩阵的导数可以有旋转向量指定


李代数 s e ( 3 ) \mathfrak{se(3)} se(3)的指数映射

根据类似的泰勒展开,
T = e x p ( ξ ^ ) = ( ∑ n = 0 ∞ 1 n ! ( ϕ ^ ) n ∑ n = 0 ∞ 1 ( n + 1 ) ! ( ϕ ^ ) n ρ 0 T 1 ) = ( R J ρ 0 T 1 ) = T T=exp(\hat\xi)=\begin{pmatrix} \sum_{n=0}^{\infty}\frac{1}{n!}(\hat\phi)^n & \sum_{n=0}^{\infty}\frac{1}{(n+1)!}(\hat\phi)^n\rho\\0^T & 1\end{pmatrix}=\begin{pmatrix} R & J\rho \\0^T & 1\end{pmatrix}=T T=exp(ξ^)=(n=0n!1(ϕ^)n0Tn=0(n+1)!1(ϕ^)nρ1)=(R0TJρ1)=T根据 ϕ = θ a \phi=\theta a ϕ=θa,则
J = sin ⁡ θ θ I + ( 1 − sin ⁡ θ θ ) a a T + 1 − cos ⁡ θ θ a ^ J=\frac{\sin \theta}{\theta}I+(1-\frac{\sin \theta}{\theta})aa^T+\frac{1-\cos \theta}{\theta}\hat a J=θsinθI+(1θsinθ)aaT+θ1cosθa^
小结:平移部分经过指数映射后,发生了以 J J J为系数矩阵的线性变换。
t = J ρ t=J\rho t=Jρ

小结:图解

下次附上来:P71

五.李代数求导

BCH公式与近似形式

两个李代数指数映射乘积不符合指数和对数运算的规律,由BCH公式给出:
l n ( R 1 R 2 ) = l n ( e x p ( ϕ ^ 1 ) e x p ( ϕ ^ 2 ) ) ˇ ≈ { J l ( ϕ 2 ) − 1 ϕ 1 + ϕ 2 , 当 ϕ 1 为 小 量 J r ( ϕ 1 ) − 1 ϕ 2 + ϕ 1 , 当 ϕ 2 为 小 量 ln(R_1R_2)=ln(exp(\hat\phi_{1})exp(\hat\phi_{2}))\check{} \approx \left \{ \begin{array}{l} J_l(\phi_{2})^{-1}\phi_{1}+\phi_{2}, 当\phi_{1}为小量 \\ J_r(\phi_{1})^{-1}\phi_{2}+\phi_{1} , 当\phi_{2}为小量 \end{array} \right. ln(R1R2)=ln(exp(ϕ^1)exp(ϕ^2))ˇ{Jl(ϕ2)1ϕ1+ϕ2ϕ1Jr(ϕ1)1ϕ2+ϕ1ϕ2
说明: =当旋转矩阵 R R R(对应李代数 ϕ \phi ϕ )左乘微小旋转矩阵 Δ R \Delta R ΔR(对应李代数 Δ ϕ \Delta \phi Δϕ),可看作在原有李代数 ϕ \phi ϕ的基础上,加上 J l ( ϕ ) − 1 Δ ϕ J_l(\phi)^{-1}\Delta \phi Jl(ϕ)1Δϕ;当旋转矩阵 R R R 右乘微小旋转矩阵 Δ R \Delta R ΔR,可看作在原有李代数 ϕ \phi ϕ的基础上,加上 J r ( ϕ ) − 1 Δ ϕ J_r(\phi)^{-1}\Delta\phi Jr(ϕ)1Δϕ;需要注意左乘还是右乘
根据左乘模型,因为
J l ( ϕ ) = sin ⁡ θ θ I + ( 1 − sin ⁡ θ θ ) a a T + 1 − cos ⁡ θ θ a ^ J_l(\phi)=\frac{\sin \theta}{\theta}I+(1-\frac{\sin \theta}{\theta})aa^T+\frac{1-\cos \theta}{\theta}\hat a Jl(ϕ)=θsinθI+(1θsinθ)aaT+θ1cosθa^所以
J l ( ϕ ) − 1 = θ 2 cot ⁡ θ 2 I + ( 1 − θ 2 cot ⁡ θ 2 ) a a T − θ 2 a ^ J_l(\phi)^{-1}=\frac{\theta}{2}\cot\frac{\theta}{2}I+(1-\frac{\theta}{2}\cot\frac{\theta}{2})aa^T-\frac{\theta}{2}\hat a Jl(ϕ)1=2θcot2θI+(12θcot2θ)aaT2θa^
可知 J r ( ϕ ) = J l ( − ϕ ) J_r(\phi)=J_l(-\phi) Jr(ϕ)=Jl(ϕ)


小结

对于李群 S O ( 3 ) SO(3) SO(3),李代数 s o ( 3 ) \mathfrak{so(3)} so(3)下的微小旋转:
乘法: Δ R ⋅ R = e x p ( Δ ϕ ^ ) e x p ( ϕ ^ ) ) = e x p ( ( ϕ + J l ( ϕ ) − 1 Δ ϕ ) ^ ) \Delta R·R=exp(\Delta\hat\phi)exp(\hat\phi))=exp((\phi+ J_l(\phi)^{-1}\Delta \phi)\hat{} ) ΔRR=exp(Δϕ^)exp(ϕ^))=exp((ϕ+Jl(ϕ)1Δϕ)^)加法:
e x p ( ( ϕ + Δ ϕ ) ^ ) = e x p ( ( J l Δ ϕ ) ) ^ e x p ( ϕ ^ ) = e x p ( ϕ ^ ) e x p ( ( J r Δ ϕ ) ) ^ exp((\phi+\Delta\phi\hat))=exp((J_l\Delta \phi)\hat)exp(\hat{\phi})=exp(\hat{\phi})exp((J_r\Delta \phi)\hat) exp((ϕ+Δϕ)^)=exp((JlΔϕ))^exp(ϕ^)=exp(ϕ^)exp((JrΔϕ))^此处 J l J_l Jl为3*3 矩阵。

对于李群 S E ( 3 ) SE(3) SE(3),李代数 s e ( 3 ) \mathfrak{se(3)} se(3)下的微小变换亦类似,只是此处 J l J_l Jl为6*6 矩阵。

李代数 s o ( 3 ) \mathfrak{so(3)} so(3)下的求导

对空间点 p p p 进行旋转得到 R p Rp Rp , R R R 对应的李代数为 ϕ \phi ϕ ,根据导数的定义,对旋转矩阵求导,得到旋转后的坐标相对于旋转的导数为 ∂ ( R p ) ∂ R = ∂ ( e x p ( ϕ ^ ) p ) ∂ ϕ = − ( R p ) ^ J l \frac{\partial (Rp)}{\partial R}=\frac{\partial (exp(\hat\phi)p)}{\partial \phi}=-(Rp)\hat{}J_l R(Rp)=ϕ(exp(ϕ^)p)=(Rp)^Jl

扰动模型(左乘)

对旋转矩阵 R R R 左乘扰动 Δ R \Delta R ΔR , R R R 对应的李代数为 ϕ \phi ϕ , Δ R \Delta R ΔR 对应的李代数为 φ \varphi φ, 根据导数的定义,对扰动的李代数求导, ∂ ( R p ) ∂ φ = − ( R p ) ^ \frac{\partial (Rp)}{\partial \varphi}=-(Rp)\hat{} φ(Rp)=(Rp)^

对变换矩阵 T T T的左乘扰动类似:
∂ ( T p ) ∂ δ ξ = ( I − ( R p + t ) ^ 0 T 0 T ) = − ( T p ) ⨀ \frac{\partial (Tp)}{\partial \delta \xi}=\begin{pmatrix} I & -(Rp+t)\hat{} \\ 0^T & 0^T \end{pmatrix}=-(Tp)^{\bigodot} δξ(Tp)=(I0T(Rp+t)^0T)=(Tp)
⨀ {\bigodot} :将齐次坐标的空间点变为4*6矩阵

六.Sophus李代数库实践

编译安装

mkdir build
cd build
cmake ..
sudo make install

报错:
1.Sophus/sophus/so2.cpp:33:26:error: lvalue required as left operand of assignment
unit_complex_.real() = 1.;
2. Sophus/sophus/so2.cpp:33:26:error: lvalue required as left operand of assignment
unit_complex_.imag() = 1.;*
解决:该错误位于so2.cpp源码文件下:将开头的

  unit_complex_.real() = 1.;
  unit_complex_.imag() = 0.;

修改为

  unit_complex_.real(1.);
  unit_complex_.imag(0.);

设置CMakeLists.txt:

cmake_minimum_required(VERSION 3.14)
project(FourthuseSophus)

set(CMAKE_CXX_STANDARD 14)

find_package( Sophus REQUIRED )
include_directories( ${Sophus_INCLUDE_DIRS} )

include_directories(/usr/local/include/eigen3)

add_executable(FourthuseSophus main.cpp)
target_link_libraries( FourthuseSophus ${Sophus_LIBRARIES} )

Sophus库下的李代数运算

容易出错:切记SO3是矩阵,是李群,以李代数输出。旋转向量是李代数

#include <iostream>
#include <eigen3/Eigen/Core>
#include <eigen3/Eigen/Geometry>
#include <sophus/so3.h>
#include <sophus/se3.h>

using namespace std;


int main() {
    //设沿着z轴旋转90度
    Eigen::Matrix3d R = Eigen::AngleAxisd(M_PI/2,Eigen::Vector3d(0,0,1)).toRotationMatrix();
    Sophus::SO3 SO3_R(R);                //从旋转矩阵构造李群
    Sophus::SO3 SO3_v(0,0, M_PI/2 );     //从欧拉角构造李群
    Eigen::Quaterniond q(R);
    Sophus::SO3 SO3_q(q);                //四元数构造李群
    cout<< SO3_q<<SO3_R<<SO3_v<<endl;

    Eigen::Vector3d so33 (1, 1, 1);
    Sophus::SO3 SO33 =Sophus::SO3::exp(so33); //从旋转向量构造李群
    cout<<SO33<<endl;
    // SO3是李群,本是矩阵,此处用李代数输出,所以是三维向量,旋转向量是李代数,所以此处输出结果遗址

    //从李群获得李代数 .log
    Eigen::Vector3d so3R = SO3_R.log();
    Eigen::Vector3d so3V = SO3_v.log();
    Eigen::Vector3d so3v= SO33.log();
    cout<<so3R.transpose()<<"\n"<<so3V.transpose()<<"\n" <<so33.transpose()<<endl;

    //从向量到反对称矩阵 hat
    Eigen::Matrix3d hat = Sophus::SO3::hat(so3v);
    cout<<"vector so3 to matrix = \n"<< hat<<endl;

    //从反对称矩阵到向量 vee
    Eigen::Vector3d vee =Sophus::SO3::vee(hat);
    cout<<"matrix to vector=\n"<< vee.transpose()<<endl;

    //so3扰动模型
    Eigen::Vector3d updateso3(1e-4,0,0);
    Sophus::SO3 SO3updated = Sophus::SO3::exp(updateso3)*SO3_R;//左乘扰动
    cout<<"左乘之前:"<<SO3_R <<"扰动更新后:"<< SO3updated<<endl;

    /**********下面为对SE(3)的操作***********/
    Eigen::Vector3d t(1,0,0);
    Sophus::SE3 SE3RT(R,t);               //此处R可以为旋转矩阵、四元数
    cout << "SE3RT=\n"<<SE3RT<<endl;

    typedef Eigen::Matrix<double,6,1> Vector6d;           //重命名,方便写六维向量
    Vector6d se3 = SE3RT.log();           //获得李代数,平移在前,旋转在后
    cout<<"se3="<<se3.transpose()<<endl;

    cout <<"se3 hat="<<endl<<Sophus::SE3::hat(se3)<<endl; //注意并非反对称的,跟原理提到的一样
    cout <<"se3 vee="<<endl<<Sophus::SE3::vee(Sophus::SE3::hat(se3)).transpose()<<endl;

    //se3扰动模型
    Vector6d updatese3;
    updatese3.setZero();
    updatese3(0,0)=1e-4;
    Sophus::SE3 SE3updated = Sophus::SE3::exp(updatese3)*SE3RT;
    cout <<"updatedse3="<<endl<< SE3updated.matrix()<<endl;
    
    return 0;
}

七.单目相机尺度不确定性和相似变换群

用到了再说:P15、P79

参考

[1]: Xiang Gao, Tao Zhang, Yi Liu, Qinrui Yan, 14 Lectures on Visual SLAM: From Theory to Practice, Publishing House of Electronics Industry, 2017.

强烈安利《视觉slam十四讲》,这是极好的一本书
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值