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 ...
随机推荐
- VMware下Mac系统自适应屏幕
1.下载VMwareTool工具镜像 链接:https://pan.baidu.com/s/1gvXBdzrwYyOEl6yhJurUig 提取码:s1po 2.打开Mac系统,推出DVD 2.设置连 ...
- 自学Python6.3-内置模块(1)
自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...
- 【BZOJ1856】[SCOI2010]字符串(组合数学)
[BZOJ1856][SCOI2010]字符串(组合数学) 题面 BZOJ 洛谷 题解 把放一个\(1\)看做在平面直角坐标系上沿着\(x\)正半轴走一步,放一个\(0\)看做往\(y\)轴正半轴走一 ...
- [hgoi#2019/2/16t1]math
题目描述 解法 我们稍微枚举一下前面几位,可以得到这样的规律. \[X_i=\frac{1}{2^{i+1}-1}\] \[Y_i=\frac{1}{2^{2^i}-1}\] 那么要使\(xm=yn\ ...
- emWin 之 WM_SetCallback 创建回调函数
@2018-7-11 [小记] emWin 通过函数 WM_SetCallback ( ) 自定义回调函数 > 下段代码就是通过 MESSAGEBOX 控件的 OK 按键实现删除信息框的对话框 ...
- java匹配竖线的错误警示
String s1 = "|"; // 输出 | System.out.println(s1); String s2 = s1.replaceAll("|",& ...
- MQTT——取消订阅报文和断开连接报文
笔者已经把连接报文,订阅报文,发布报文都讲解了完了.而接下来就是取消订阅报文和断开连接报文.和其他的报文比较的话,他们显示非常简单.甚至笔者觉得可以不必要拿出来讲.只要看一下MQTT文档就没有什么不清 ...
- 【CH1602】最大异或和 trie+贪心
题目大意:给定 N 个数,求这 N 个数中任选两个数进行异或运算,求最大的异或和是多少. 一个 int 类型的整数,可以看作一个长度为32位的字符串,异或运算不像加法,最大值不一定是由两个较大值得到. ...
- (转)同一服务器部署多个tomcat时的端口号修改详情
背景:在同一个服务器上部署工程,总会遇到tomcat端口占用的情况,所有有必要分清楚各个端口的作用,和需要更改的端口. 同一服务器部署多个tomcat时,存在端口号冲突的问题,所以需要修改tomcat ...
- 关于navicat远程连接mysql问题
如果你想连接你的mysql的时候发生这个错误: ERROR 1130: Host '192.168.1.81' is not allowed to connect to this MySQL serv ...