Adjoint of SE(3)
以前看的书都提到 SE(3) 和 se(3) 的 Adjoint,但是并没有讲这个东西是干什么用的,只是给了一堆性质。这东西来自群论。
参考 Lie Groups for 2D and 3D Transformations 的 2.3。
In Lie groups, it is often necessary to transform a tangent vector from the tangent space around one element to the tangent space. The adjoint performs this transformation.
Tangent Vector 是啥?这个和 Manifold(流型) 有关系。可以看一看 A Framework for Sparse, Non-Linear Least Squares Problems on Manifolds 的 Manifolds 章节,motivation 小结写了为什么要用 Manifold。简单说,Manifold 是一个非线性空间,但是在局部的小区域可以用线性空间拟合。如同一个曲面,在曲面上可导点处的局部性质可以用该点切平面描述。用线性空间拟合后,在局部小区域就可以使用优化算法进行优化了。Tangent Vector 就是这种线性空间中的元素,也就是优化计算出来的增量。
定义
参考 Lie Groups for 2D and 3D Transformations 里的定义,按照我习惯的符号系统,Adjoint 定义如下:
\[\begin{align} \text{Exp}(\text{Ad}_{\mathbf{T}}\cdot\pmb{\xi}) \doteq \mathbf{T} \text{Exp}(\pmb{\xi}) \mathbf{T}^{-1} \label{eq:adj_def} \end{align}\]
这是一个同构映射(Homomorphism),按照维基百科的定义,同构映射是在几何结构(Algebraic structure)中保持结构的(structure-preserving)映射。几何结构中就包括了群(Groups),“结构”没有找到定义,不好理解。也可以参考 Naive Lie Theory 2.2 Crash course on homomorphism,对于群而言,保持结构就是保持定义在群中的二元运算(SE(3) 而言就是矩阵乘法)。公式表达如下:
\[\begin{align} \varphi(g) &= \mathbf{T} g \mathbf{T}^{-1} \notag \\
\varphi(g_1g_2) &= \varphi(g_1)\varphi(g_2) \end{align} \notag\]
对于当前的映射,这个是显然成立的。
表达
现在计算 \(\text{Ad}_{\mathbf{T}}\),参考 State Estimation for Robotics 的公式 (7.33) (7.48),按照我习惯的符号系统,如下:
\[\begin{align} \exp\left(\pmb{\xi}^{\wedge}\right) &= \sum_{n=0}^{\infty} \frac{1}{n!}\left(\pmb{\xi}^{\wedge}\right)^n \notag \\
&= \sum_{n=0}^{\infty} \frac{1}{n!}\left(\begin{bmatrix}\pmb{\rho} \\ \pmb{\phi}\end{bmatrix}^{\wedge}\right)^n \notag \\
&= \sum_{n=0}^{\infty} \frac{1}{n!} \begin{bmatrix}\pmb{\phi}^{\wedge} & \pmb{\rho} \\ \mathbf{0}^T & 0\end{bmatrix} \notag \\
&= \begin{bmatrix} \sum_{n=0}^{\infty}\frac{1}{n!}\left(\pmb{\phi}^{\wedge}\right)^n & \left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left(\pmb{\phi}^{\wedge}\right)^n\right]\pmb{\rho} \\ \mathbf{0}^T & 1 \end{bmatrix} \notag \\
&= \begin{bmatrix} \mathbf{R} & \mathbf{t} \\ \mathbf{0}^T & 1\end{bmatrix} \in SE(3) \label{eq:exp_xi}\end{align}\]
\[\begin{align} \mathbf{R}\mathbf{t}^{\wedge}\mathbf{R}^T = (\mathbf{R}\mathbf{t})^{\wedge} \label{eq:Rt_hat}\end{align}\]
按照 Adjoint 的定义 (\ref{eq:adj_def}) 有如下推导:
\[\begin{align} \text{Ad}_{\mathbf{T}}\cdot\pmb{\xi} &= \text{Log}\left(\mathbf{T} \text{Exp}(\pmb{\xi}) \mathbf{T}^{-1}\right)\notag \\
&= \text{Log}\left(\begin{bmatrix} \mathbf{R} & \mathbf{t} \\ \mathbf{0}^T & 1\end{bmatrix} \begin{bmatrix} \sum_{n=0}^{\infty}\frac{1}{n!}\left(\pmb{\phi}^{\wedge}\right)^n & \left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left(\pmb{\phi}^{\wedge}\right)^n\right]\pmb{\rho} \\ \mathbf{0}^T & 1 \end{bmatrix} \begin{bmatrix} \mathbf{R}^T & -\mathbf{R}^T\mathbf{t} \\ \mathbf{0}^T & 1\end{bmatrix}\right) \notag \\
&= \text{Log}\left( \begin{bmatrix} \mathbf{R} \left[\sum_{n=0}^{\infty}\frac{1}{n!}\left(\pmb{\phi}^{\wedge}\right)^n\right] & \mathbf{R}\left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left(\pmb{\phi}^{\wedge}\right)^n\right]\pmb{\rho}+\mathbf{t} \\ \mathbf{0}^T & 1 \end{bmatrix} \begin{bmatrix} \mathbf{R}^T & -\mathbf{R}^T\mathbf{t} \\ \mathbf{0}^T & 1\end{bmatrix} \right) \notag \\
&= \text{Log}\left( \begin{bmatrix} \mathbf{R} \left[\sum_{n=0}^{\infty}\frac{1}{n!}\left(\pmb{\phi}^{\wedge}\right)^n\right]\mathbf{R}^T & -\mathbf{R} \left[\sum_{n=0}^{\infty}\frac{1}{n!}\left(\pmb{\phi}^{\wedge}\right)^n\right]\mathbf{R}^T\mathbf{t} + \mathbf{R}\left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left(\pmb{\phi}^{\wedge}\right)^n\right]\pmb{\rho}+\mathbf{t} \\ \mathbf{0}^T & 1 \end{bmatrix} \right) \notag \\
&\stackrel{(\ref{eq:Rt_hat})}{=} \text{Log}\left( \begin{bmatrix} \left[\sum_{n=0}^{\infty}\frac{1}{n!}\left((\mathbf{R}\pmb{\phi})^{\wedge}\right)^n\right] & -\left[\sum_{n=0}^{\infty}\frac{1}{n!}\left((\mathbf{R}\pmb{\phi})^{\wedge}\right)^n\right]\mathbf{t} +\left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\mathbf{R}\pmb{\phi})^{\wedge}\right)^n\right]\mathbf{R}\pmb{\rho}+\mathbf{t} \\ \mathbf{0}^T & 1 \end{bmatrix} \right)\notag \\
&= \begin{bmatrix}\bar{\pmb{\rho}} \\ \bar{\pmb{\phi}}\end{bmatrix} \end{align}\]
上式 \(\text{Log}(\cdot)\) 之后的结果是一个 \(6 \times 1\) 的向量(等于 \(\text{Ad}_{\mathbf{T}}\cdot\pmb{\xi}\)),而 \(\pmb{\xi}\) 是 \(6 \times 1\),所以 \(\text{Ad}_{\mathbf{T}}\) 是 \(6 \times 6\)。上式的最后一个等号,参照公式 (\ref{eq:exp_xi}),可以得到
\[\begin{align} \bar{\pmb{\phi}} &= \mathbf{R}\pmb{\phi} \notag \\
&\left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left(\bar{\pmb{\phi}}^{\wedge}\right)^n\right]\bar{\pmb{\rho}} \notag \\
&= -\left[\sum_{n=0}^{\infty}\frac{1}{n!}\left((\mathbf{R}\pmb{\phi})^{\wedge}\right)^n\right]\mathbf{t} +\left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\mathbf{R}\pmb{\phi})^{\wedge}\right)^n\right]\mathbf{R}\pmb{\rho}+\mathbf{t} \notag \\
&= -\left[\sum_{n=0}^{\infty}\frac{1}{n!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\mathbf{t} +\left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\mathbf{R}\pmb{\rho}+\mathbf{t} \notag \\
&= \left(\mathbf{I} - \left[\sum_{n=0}^{\infty}\frac{1}{n!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\right)\mathbf{t} + \left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\mathbf{R}\pmb{\rho} \notag \\
&= \left(\mathbf{I} - \frac{1}{0!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^0 - \left[\sum_{n=1}^{\infty}\frac{1}{n!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\right)\mathbf{t} + \left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\mathbf{R}\pmb{\rho} \notag \\
&= -\left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^{n+1}\right] \mathbf{t} + \left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\mathbf{R}\pmb{\rho} \notag \\
&= -\left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right](\bar{\pmb{\phi}})^{\wedge}\mathbf{t} + \left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\mathbf{R}\pmb{\rho} \notag \\
&= \left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\mathbf{t}^{\wedge}\bar{\pmb{\phi}} + \left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right]\mathbf{R}\pmb{\rho} \notag \\
&= \left[\sum_{n=0}^{\infty}\frac{1}{(n+1)!}\left((\bar{\pmb{\phi}})^{\wedge}\right)^n\right](\mathbf{t}^{\wedge}\mathbf{R}\pmb{\phi} + \mathbf{R}\pmb{\rho})\end{align}\]
所以
\[\begin{align} \text{Ad}_{\mathbf{T}}\cdot\pmb{\xi} &\doteq \text{Ad}_{\mathbf{T}} \cdot \begin{bmatrix}\pmb{\rho} \\ \pmb{\phi}\end{bmatrix}\notag \\ &\doteq \begin{bmatrix}\bar{\pmb{\rho}} \\ \bar{\pmb{\phi}}\end{bmatrix} \notag \\
&= \begin{bmatrix} \mathbf{t}^{\wedge}\mathbf{R}\pmb{\phi} + \mathbf{R}\pmb{\rho} \\ \mathbf{R}\pmb{\phi} \end{bmatrix} \notag \\
&= \begin{bmatrix} \mathbf{R} & \mathbf{t}^{\wedge}\mathbf{R} \\ \mathbf{0}^T & \mathbf{R}\end{bmatrix} \cdot \begin{bmatrix}\pmb{\rho} \\ \pmb{\phi}\end{bmatrix} \end{align}\]
\[\begin{align} \text{Ad}_{\mathbf{T}} = \begin{bmatrix} \mathbf{R} & \mathbf{t}^{\wedge}\mathbf{R} \\ \mathbf{0}^T & \mathbf{R}\end{bmatrix} \end{align}\]
应用
前面讲到了这个东西就是将一个 Tangent Vector 从一个 Vector Space 转换到另外一个 Vector Space。
用定义 (\ref{eq:adj_def}) 求 DSO 中相对位置姿态对绝对位置姿态的偏导,也是解决我在 DSO windowed optimization 公式 开头提到的问题。
首先,涉及到的位置姿态关系在线性化点处如下:
\[\begin{align} \mathbf{T}_{th} = \mathbf{T}_{wt}^{-1} \mathbf{T}_{wh} \end{align}\]
在某一次优化迭代中,\(\mathbf{T}_{th}, \mathbf{T}_{wh}, \mathbf{T}_{wt}\) 已经离开线性化点一段距离 \(\pmb{\xi}_{th}, \pmb{\xi}_{h}, \pmb{\xi}_{t}\),在本次迭代中的更新为 \(\pmb{\xi}_{th} \leftarrow \pmb{\xi}_{th} + \delta \pmb{\xi}_{th}, \pmb{\xi}_{h} \leftarrow \pmb{\xi}_{h} + \delta \pmb{\xi}_{h}, \pmb{\xi}_{t} \leftarrow \pmb{\xi}_{t} + \delta \pmb{\xi}_{t}\)。
\[\begin{align} \text{Exp}(\pmb{\xi}_{th}+\delta \pmb{\xi}_{th})\mathbf{T}_{th} = \mathbf{T}_{wt}^{-1} \text{Exp}(\pmb{\xi}_h+\delta \pmb{\xi}_{h}) \mathbf{T}_{wh} \end{align}\]
\[\begin{align} \text{Exp}(\pmb{\xi}_{th}+\delta \pmb{\xi}_{th}) &= \mathbf{T}_{wt}^{-1} \text{Exp}(\pmb{\xi}_h+\delta \pmb{\xi}_{h}) \mathbf{T}_{wt} \mathbf{T}_{wt}^{-1} \mathbf{T}_{wh} \mathbf{T}_{th}^{-1} \notag \\
&\stackrel{(\ref{eq:adj_def})}{=} \text{Exp}(\text{Ad}_{\mathbf{T}_{wt}^{-1}}(\pmb{\xi}_h+\delta \pmb{\xi}_{h})) \mathbf{T}_{wt}^{-1} \mathbf{T}_{wh} \mathbf{T}_{th}^{-1} \notag \\
&= \text{Exp}(\text{Ad}_{\mathbf{T}_{wt}^{-1}}(\pmb{\xi}_h+\delta \pmb{\xi}_{h})) \end{align}\]
\[\begin{align} \pmb{\xi}_{th}+\delta \pmb{\xi}_{th} = \text{Ad}_{\mathbf{T}_{wt}^{-1}}(\pmb{\xi}_h+\delta \pmb{\xi}_{h}) \end{align}\]
所以
\[\frac{\partial \pmb{\xi}_{th}}{\partial \pmb{\xi}_h} = \text{Ad}_{\mathbf{T}_{wt}^{-1}} \]
这个结果和 Lie Groups for 2D and 3D Transformations 的结论(公式(97))一致。
再算 \(\frac{\partial \pmb{\xi}_{th}}{\partial \pmb{\xi}_t}\)。
\[\begin{align} \text{Exp}(\pmb{\xi}_{th}+\delta \pmb{\xi}_{th})\mathbf{T}_{th} = (\text{Exp}(\pmb{\xi}_t+\delta \pmb{\xi}_{t})\mathbf{T}_{wt})^{-1} \mathbf{T}_{wh} \end{align}\]
\[\begin{align} \text{Exp}(\pmb{\xi}_{th}+\delta \pmb{\xi}_{th}) &= \mathbf{T}_{wt}^{-1}\text{Exp}(-(\pmb{\xi}_t+\delta \pmb{\xi}_{t})) \mathbf{T}_{wt}\mathbf{T}_{wt}^{-1}\mathbf{T}_{wh}\mathbf{T}_{th}^{-1} \notag \\
&= \text{Exp}(-\text{Ad}_{\mathbf{T}_{wt}^{-1}}(\pmb{\xi}_t+\delta \pmb{\xi}_{t}))\end{align}\]
所以
\[\frac{\partial \pmb{\xi}_{th}}{\partial \pmb{\xi}_t} = -\text{Ad}_{\mathbf{T}_{wt}^{-1}}\]
但是这个结果和 DSO windowed optimization 公式 中提到的,从代码中推算出来的结果不同。这只是两边所理解的 \(\pmb{\xi}\) 不同而已。
看最关键的一行将优化计算的 se(3) 更新到 SE(3) 的代码,是“worldToCam”,所以对应的位姿应该用 \(\mathbf{T}_{cw}\) 表达,而不是“camToWorld”—— \(\mathbf{T}_{wc}\)。
重新算一遍。这次涉及到的位置姿态关系在线性化点处如下:
\[\begin{align} \mathbf{T}_{th} = \mathbf{T}_{tw} \mathbf{T}_{hw}^{-1} \end{align}\]
算 \(\frac{\partial \pmb{\xi}_{th}}{\partial \pmb{\xi}_h}\)。
\[\begin{align} \text{Exp}(\pmb{\xi}_{th}+\delta \pmb{\xi}_{th})\mathbf{T}_{th} = \mathbf{T}_{tw} (\text{Exp}(\pmb{\xi}_h+\delta \pmb{\xi}_{h}) \mathbf{T}_{hw})^{-1} \end{align}\]
\[\begin{align} \text{Exp}(\pmb{\xi}_{th}+\delta \pmb{\xi}_{th}) &= \mathbf{T}_{tw} \mathbf{T}_{hw}^{-1} \text{Exp}(-(\pmb{\xi}_h+\delta \pmb{\xi}_{h}))\mathbf{T}_{th}^{-1} \notag \\
&= \mathbf{T}_{th} \text{Exp}(-(\pmb{\xi}_h+\delta \pmb{\xi}_{h}))\mathbf{T}_{th}^{-1} \notag \\
&\stackrel{(\ref{eq:adj_def})}{=} \text{Exp}(-\text{Ad}_{\mathbf{T}_{th}}(\pmb{\xi}_h+\delta \pmb{\xi}_{h})) \end{align}\]
\[\begin{align} \pmb{\xi}_{th}+\delta \pmb{\xi}_{th} = -\text{Ad}_{\mathbf{T}_{th}}(\pmb{\xi}_h+\delta \pmb{\xi}_{h}) \end{align}\]
所以
\[\frac{\partial \pmb{\xi}_{th}}{\partial \pmb{\xi}_h} = -\text{Ad}_{\mathbf{T}_{th}}\]
算 \(\frac{\partial \pmb{\xi}_{th}}{\partial \pmb{\xi}_t}\)。
\[\begin{align} \text{Exp}(\pmb{\xi}_{th}+\delta \pmb{\xi}_{th})\mathbf{T}_{th} = \text{Exp}(\pmb{\xi}_t+\delta \pmb{\xi}_{t})\mathbf{T}_{tw} \mathbf{T}_{hw}^{-1} \end{align}\]
\[\begin{align} \text{Exp}(\pmb{\xi}_{th}+\delta \pmb{\xi}_{th}) &= \text{Exp}(\pmb{\xi}_t+\delta \pmb{\xi}_{t})\mathbf{T}_{tw} \mathbf{T}_{hw}^{-1}\mathbf{T}_{th}^{-1} \notag \\
&= \text{Exp}(\pmb{\xi}_t+\delta \pmb{\xi}_{t}) \end{align}\]
\[\begin{align} \pmb{\xi}_{th}+\delta \pmb{\xi}_{th} = \pmb{\xi}_t+\delta \pmb{\xi}_{t} \end{align}\]
所以
\[\frac{\partial \pmb{\xi}_{th}}{\partial \pmb{\xi}_t} = \mathbf{I}\]
Adjoint of SE(3)的更多相关文章
- IMU 预积分推导
给 StereoDSO 加 IMU,想直接用 OKVIS 的代码,但是有点看不懂.知乎上郑帆写的文章<四元数矩阵与 so(3) 左右雅可比>提到 OKVIS 的预积分是使用四元数,而预积分 ...
- DSO windowed optimization 公式
这里有一个细节,我想了很久才想明白,DSO 中的 residual 联系了两个关键帧之间的相对位姿,但是最终需要优化帧的绝对位姿,中间的导数怎么转换?这里使用的是李群.李代数中的Adjoint. 参考 ...
- eclipse SE增加Web开发插件
最近接触了些java项目,之前安装了eclipse SE版本.没有Web开发插件,调试不了Web代码.点击“Window”--“Preference” 左边菜单栏是找不到“Server”项来配置服务器 ...
- 关于 Java(TM) Platform SE binary 已停止工作 的解决方法
一.问题描述 昨天晚上Myeclipse还用着好好的,今天早上打开工程,只要运行就卡住,大半天弹出个消息窗口:Java(TM) Platform SE binary 已停止工作. 如图 关闭Myecl ...
- Using Headless Mode in the Java SE Platform--转
原文地址: By Artem Ananiev and Alla Redko, June 2006 Articles Index This article explains how to use ...
- Mac下打开eclipse 始终提示 你需要安装Java SE 6 Runtime
Mac下打开eclipse 始终提示 你需要安装Java SE 6 Runtime 周银辉 我的mac os 版本是10.9.2, JDK配置得好好的,但打开eclipse时还是提示需 ...
- 软件工程(FZU2015)赛季得分榜,第11回合(beta冲刺+SE总结)
目录 第一回合 第二回合 第三回合 第四回合 第五回合 第6回合 第7回合 第8回合 第9回合 第10回合 第11回合 增补作业 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分:b ...
- mac下需要安装旧 Java SE 6 才能打开程序解决办法
今天我在mac系统下面安装myeclipse2014(myeclipse-pro-2014-GA-offline-installer-macosx.dmg)的时候,发现显示错误: 您需要安装旧 Jav ...
- ubuntu配置 Java SE 1.6
今天编译android 4.0时提示如下错误: You are attempting to build with the incorrect version of java. Your versi ...
随机推荐
- BZOJ2662[BeiJing wc2012]冻结——分层图最短路
题目描述 “我要成为魔法少女!” “那么,以灵魂为代价,你希望得到什么?” “我要将有关魔法和奇迹的一切,封印于卡片之中„„” 在这个愿望被实现以后的世界里,人们享受着魔法卡片(Spe ...
- 拯救大兵瑞恩 HDU - 4845(状压bfs || 分层最短路)
1.状压bfs 这个状压体现在key上 我i们用把key状压一下 就能记录到一个点时 已经拥有的key的种类 ban[x1][y1][x2][y1]记录两个点之间的状态 是门 还是墙 还是啥都没有 ...
- 在finally块中使用try catch,并且catch的时候抛出异常的一个问题
在finally中使用try/catch,并且catch的时候抛出异常 IDEA会提示警告 Reports throw statements inside of finally blocks. Whi ...
- day24 异常处理
程序一旦发生错误,就从错误的位置停下不在执行后面的内容一般可能预估但是无法处理的问题可以用异常处理进行操作异常处理后会继续执行后面的代码 try: # 写在try中的语句是一定执行的 ret = in ...
- MT【224】反解系数
(2011安徽省赛)$f(x)=ax^3+bx+c(a,b,c\in R),$当$0\le x \le 1$时,$0\le f(x)\le 1$,求$b$的可能的最大值. 提示:取三个点$f(0),f ...
- Leetcode 26.删除排序数组中的重复项 By Python
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成. 示例 1 ...
- 8bit数据 转换为 16bit数据的四种方法
[转]玩转嵌入式(公众号) 在入门单片机时,想必大家都都会遇到一下这种情况 unsigned char a = 0x12; unsigned char b = 0x34; unsigned int c ...
- 洛谷 P3299 [SDOI2013]保护出题人 解题报告
P3299 [SDOI2013]保护出题人 题目描述 出题人铭铭认为给SDOI2012出题太可怕了,因为总要被骂,于是他又给SDOI2013出题了. 参加SDOI2012的小朋友们释放出大量的僵尸,企 ...
- Bean和Spirng模块
容纳Bean 在Spring中,应用对象生存于Spring容器中,如图所示,Spring容器可以创建.装载.配置这些Bean,并且可以管理它们的生命周期. Spring的容器实现 Bean工厂(org ...
- 使用selenium模拟登陆oschina
Selenium把元素定位接口封装得更简单易用了,支持Xpath.CSS选择器.以及标签名.标签属性和标签文本查找. from selenium.webdriver import PhantomJS ...