00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 template <int D, typename E, typename VertexXiType, typename VertexXjType>
00018 OptimizableGraph::Vertex* BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::createFrom(){
00019 return new VertexXiType();
00020 }
00021
00022 template <int D, typename E, typename VertexXiType, typename VertexXjType>
00023 OptimizableGraph::Vertex* BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::createTo(){
00024 return new VertexXjType();
00025 }
00026
00027
00028 template <int D, typename E, typename VertexXiType, typename VertexXjType>
00029 void BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::constructQuadraticForm()
00030 {
00031 VertexXiType* from = static_cast<VertexXiType*>(_vertices[0]);
00032 VertexXjType* to = static_cast<VertexXjType*>(_vertices[1]);
00033
00034
00035 const JacobianXiOplusType& A = jacobianOplusXi();
00036 const JacobianXjOplusType& B = jacobianOplusXj();
00037
00038 const InformationType& omega = _information;
00039
00040 bool fromNotFixed = !(from->fixed());
00041 bool toNotFixed = !(to->fixed());
00042
00043 if (fromNotFixed || toNotFixed) {
00044 #ifdef G2O_OPENMP
00045 from->lockQuadraticForm();
00046 to->lockQuadraticForm();
00047 #endif
00048 Matrix<double, D, 1> omega_r = - omega * _error;
00049 if (fromNotFixed) {
00050 Matrix<double, VertexXiType::Dimension, D> AtO = A.transpose() * omega;
00051 from->b().noalias() += A.transpose() * omega_r;
00052 from->A().noalias() += AtO*A;
00053 if (toNotFixed ) {
00054 if (_hessianRowMajor)
00055 _hessianTransposed.noalias() += B.transpose() * AtO.transpose();
00056 else
00057 _hessian.noalias() += AtO * B;
00058 }
00059 }
00060 if (toNotFixed ) {
00061 to->b().noalias() += B.transpose() * omega_r;
00062 to->A().noalias() += B.transpose() * omega * B;
00063 }
00064 #ifdef G2O_OPENMP
00065 to->unlockQuadraticForm();
00066 from->unlockQuadraticForm();
00067 #endif
00068 }
00069 }
00070
00071 template <int D, typename E, typename VertexXiType, typename VertexXjType>
00072 void BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::linearizeOplus()
00073 {
00074 VertexXiType* vi = static_cast<VertexXiType*>(_vertices[0]);
00075 VertexXjType* vj = static_cast<VertexXjType*>(_vertices[1]);
00076
00077 bool iNotFixed = !(vi->fixed());
00078 bool jNotFixed = !(vj->fixed());
00079
00080 if (!iNotFixed && !jNotFixed)
00081 return;
00082
00083 #ifdef G2O_OPENMP
00084 vi->lockQuadraticForm();
00085 vj->lockQuadraticForm();
00086 #endif
00087
00088 const double delta = 1e-9;
00089 const double scalar = 1.0 / (2*delta);
00090 ErrorVector errorBak;
00091 ErrorVector errorBeforeNumeric = _error;
00092
00093 if (iNotFixed) {
00094
00095 double add_vi[VertexXiType::Dimension];
00096 std::fill(add_vi, add_vi + VertexXiType::Dimension, 0.0);
00097
00098 for (int d = 0; d < VertexXiType::Dimension; ++d) {
00099 vi->push();
00100 add_vi[d] = delta;
00101 vi->oplus(add_vi);
00102 computeError();
00103 errorBak = _error;
00104 vi->pop();
00105 vi->push();
00106 add_vi[d] = -delta;
00107 vi->oplus(add_vi);
00108 computeError();
00109 errorBak -= _error;
00110 vi->pop();
00111 add_vi[d] = 0.0;
00112
00113 _jacobianOplusXi.col(d) = scalar * errorBak;
00114 }
00115 }
00116
00117 if (jNotFixed) {
00118
00119 double add_vj[VertexXjType::Dimension];
00120 std::fill(add_vj, add_vj + VertexXjType::Dimension, 0.0);
00121
00122 for (int d = 0; d < VertexXjType::Dimension; ++d) {
00123 vj->push();
00124 add_vj[d] = delta;
00125 vj->oplus(add_vj);
00126 computeError();
00127 errorBak = _error;
00128 vj->pop();
00129 vj->push();
00130 add_vj[d] = -delta;
00131 vj->oplus(add_vj);
00132 computeError();
00133 errorBak -= _error;
00134 vj->pop();
00135 add_vj[d] = 0.0;
00136
00137 _jacobianOplusXj.col(d) = scalar * errorBak;
00138 }
00139 }
00140
00141 _error = errorBeforeNumeric;
00142 #ifdef G2O_OPENMP
00143 vj->unlockQuadraticForm();
00144 vi->unlockQuadraticForm();
00145 #endif
00146 }
00147
00148 template <int D, typename E, typename VertexXiType, typename VertexXjType>
00149 void BaseBinaryEdge<D, E, VertexXiType, VertexXjType>::mapHessianMemory(double* d, int i, int j, bool rowMajor)
00150 {
00151 (void) i; (void) j;
00152
00153 if (rowMajor) {
00154 new (&_hessianTransposed) HessianBlockTransposedType(d, VertexXjType::Dimension, VertexXiType::Dimension);
00155 } else {
00156 new (&_hessian) HessianBlockType(d, VertexXiType::Dimension, VertexXjType::Dimension);
00157 }
00158 _hessianRowMajor = rowMajor;
00159 }