/// <summary> /// Partial initialisation function /// Calculates the state vector \vct{y}_{pi} and Jacobians for a new /// partially-initialised feature from an initial observation. /// @param hi The initial measurement \vct{h}_i , in this case the (x,y) /// image location of the feature. /// </summary> /// <param name="hi"></param> /// <param name="xp">The robot position state \vct{x}_p from which the initial observation was made.</param> public override void func_ypi_and_dypi_by_dxp_and_dypi_by_dhi_and_Ri(Vector hi, Vector xp) { // Representation of a line here: // ypi = (rWi ) // (hLhatWi) // Form the ray (in camera co-ordinates by unprojecting this image location Vector3D hLRi = new Vector3D(((Wide_Camera_Point_Feature_Measurement_Model)wide_model).m_camera.Unproject(hi)); //if (Camera_Constants.DEBUGDUMP) Debug.WriteLine("debug hLRi"); // Form hLhatRi from hLRi // Normalise Vector3D hLhatRi = hLRi; hLhatRi.Normalise(); MatrixFixed dhLhatRi_by_dhLRi = MatrixFixed.dvnorm_by_dv(hLRi); //if (Camera_Constants.DEBUGDUMP) Debug.WriteLine("debug hLhatRi" + hLhatRi); // Now convert this into a direction in world co-ordinates by rotating // Form hLhatWi from hLhatRi // Rotate ((Wide_Camera_Point_Feature_Measurement_Model)wide_model).threed_motion_model.func_q(xp); RotationMatrix RWR = ((Wide_Camera_Point_Feature_Measurement_Model)wide_model).threed_motion_model.get_qRES().RotationMatrix(); Vector3D hLhatWi = new Vector3D(RWR * hLhatRi); //if (Camera_Constants.DEBUGDUMP) Debug.WriteLine("debug hLhatWi" + hLhatWi); // Extract rW from xp ((Wide_Camera_Point_Feature_Measurement_Model)wide_model).threed_motion_model.func_r(xp); // And form ypiRES ypiRES.Update(((Wide_Camera_Point_Feature_Measurement_Model)wide_model).threed_motion_model.get_rRES().GetVNL3(), 0); ypiRES.Update(hLhatWi.GetVNL3(), 3); //if (Camera_Constants.DEBUGDUMP) Debug.WriteLine("debug ypiRES" + ypiRES); // Form Jacobians dypi_by_dxp and dypi_by_dhi // dypi_by_dxp = (drWi_by_dr drWi_by_dq ) // (dhLhatWi_by_dr dhLhatWi_by_dq) // = (I 0 ) // (0 dhLhatWi_by_dq) // hLhatWi = RWR * hLhatRi // => dhLhatWi_by_dq = d/dq ( R(qWR) * hLhatRi) MatrixFixed dhLhatWi_by_dq = MatrixFixed.dRq_times_a_by_dq(((Wide_Camera_Point_Feature_Measurement_Model)wide_model).threed_motion_model.get_qRES(), hLhatRi); // Put dypi_by_dxp together dypi_by_dxpRES.Fill(0.0f); dypi_by_dxpRES.Put(0, 0, 1.0f); dypi_by_dxpRES.Put(1, 1, 1.0f); dypi_by_dxpRES.Put(2, 2, 1.0f); dypi_by_dxpRES.Update(dhLhatWi_by_dq, 3, 3); // cout << "dypi_by_dxpRES" << dypi_by_dxpRES; // dypi_by_dhi = (drWi_by_dhi ) // (dhLhatWi_by_dhi) // = (0 ) // (dhLhatWi_by_dhi) // hLhatWi = RWR * hLhatRi // Need to work out derivative for this // dhLhatWi_by_dhi = RWR * dhLhatRi_by_dhLRi * dhLRi_by_dhi MatrixFixed dhLhatWi_by_dhi = RWR * dhLhatRi_by_dhLRi * ((Wide_Camera_Point_Feature_Measurement_Model)wide_model).m_camera.UnprojectionJacobian(); dypi_by_dhiRES.Fill(0.0f); dypi_by_dhiRES.Update(dhLhatWi_by_dhi, 3, 0); // cout << "dypi_by_dhiRES" << dypi_by_dhiRES; // And construct Ri func_Ri(hi); /* if (Camera_Constants.DEBUGDUMP) Debug.WriteLine("func_ypi: hi = " + hi + "," + "xp = " + xp + "," + "ypiRES = " + ypiRES); */ }
public override void func_zeroedyi_and_dzeroedyi_by_dxp_and_dzeroedyi_by_dyi(Vector yi, Vector xp) { Wide_Camera_Point_Feature_Measurement_Model wm = (Wide_Camera_Point_Feature_Measurement_Model)wide_model; // Extract cartesian and quaternion components of xp wm.threed_motion_model.func_r(xp); wm.threed_motion_model.func_q(xp); // Extract ri and hhati components of yi = ypi func_ri(yi); func_hhati(yi); // ri part: transformation is just the same as in the normal point case // zeroedri = RRW(rWi - rW) //commented out in original code // ri - r Vector3D yWiminusrW = new Vector3D(riRES - wm.threed_motion_model.get_rRES()); Quaternion qRW = wm.threed_motion_model.get_qRES().Inverse(); MatrixFixed dqRW_by_dq = MatrixFixed.dqbar_by_dq(); // Rotation RRW RotationMatrix RRW = qRW.RotationMatrix(); // RRW(rWi - rW) Vector3D zeroedri = new Vector3D(RRW * yWiminusrW); // Now calculate Jacobians // dzeroedri_by_dri is RRW // dzeroedri_by_dhhati = 0 MatrixFixed dzeroedri_by_dri = new MatrixFixed(RRW); // dzeroedyi_by_dxp: // dzeroedri_by_dr = -RRW // dzeroedri_by_dq = d_dq(RRW (ri - r)) MatrixFixed dzeroedri_by_dr = RRW * -1.0f; MatrixFixed dzeroedri_by_dqRW = MatrixFixed.dRq_times_a_by_dq(qRW, yWiminusrW); MatrixFixed dzeroedri_by_dq = dzeroedri_by_dqRW * dqRW_by_dq; // Now for the hhati part (easier...) // zeroedhhati = RRW hhati Vector3D zeroedhhati = new Vector3D(RRW * hhatiRES); // Jacobians // dzeroedhhati_by_dr = 0 // dzeroedhhati_by_dq = d_dq(RRW hhati) // dzeroedhhati_by_dhhati = RRW // dzeroedhhati_by_dri = 0 MatrixFixed dzeroedhhati_by_dqRW = MatrixFixed.dRq_times_a_by_dq(qRW, hhatiRES); MatrixFixed dzeroedhhati_by_dq = dzeroedhhati_by_dqRW * dqRW_by_dq; MatrixFixed dzeroedhhati_by_dhhati = new MatrixFixed(RRW); // And put it all together zeroedyiRES.Update(zeroedri.GetVNL3(), 0); zeroedyiRES.Update(zeroedhhati.GetVNL3(), 3); //cout << "Line: zeroedri = " << zeroedri << "zeroedhhati = " << zeroedhhati; dzeroedyi_by_dxpRES.Fill(0.0f); dzeroedyi_by_dxpRES.Update(dzeroedri_by_dr, 0, 0); dzeroedyi_by_dxpRES.Update(dzeroedri_by_dq, 0, 3); dzeroedyi_by_dxpRES.Update(dzeroedhhati_by_dq, 3, 3); dzeroedyi_by_dyiRES.Fill(0.0f); dzeroedyi_by_dyiRES.Update(dzeroedri_by_dri, 0, 0); dzeroedyi_by_dyiRES.Update(dzeroedhhati_by_dhhati, 3, 3); }
public override void func_zeroedyi_and_dzeroedyi_by_dxp_and_dzeroedyi_by_dyi(Vector yi, Vector xp) { ThreeD_Motion_Model mm = ((Wide_Camera_Point_Feature_Measurement_Model)wide_model).threed_motion_model; // Extract cartesian and quaternion components of xp mm.func_r(xp); mm.func_q(xp); Vector3D yWiminusrW = new Vector3D((new Vector3D(yi)) -(mm.get_rRES())); Quaternion qRES = mm.get_qRES(); Quaternion qRW = qRES.Inverse(); MatrixFixed dqRW_by_dq = MatrixFixed.dqbar_by_dq(); // Rotation RRW RotationMatrix RRW = qRW.RotationMatrix(); // Position of feature relative to robot in robot frame Vector3D zeroedyi = new Vector3D(RRW * yWiminusrW); zeroedyiRES.Update(zeroedyi.GetVNL3()); // Now calculate Jacobians // dzeroedyi_by_dyi is RRW dzeroedyi_by_dyiRES.Update(RRW); // dzeroedyi_by_dxp has 2 partitions: // dzeroedyi_by_dr (3 * 3) // dzeroedyi_by_dq (3 * 4) MatrixFixed dzeroedyi_by_dr = (MatrixFixed)(RRW); dzeroedyi_by_dr *= -1.0f; //These should be 3x4 dimension MatrixFixed dzeroedyi_by_dqRW = MatrixFixed.dRq_times_a_by_dq(qRW, yWiminusrW); MatrixFixed dzeroedyi_by_dq = dzeroedyi_by_dqRW * dqRW_by_dq; dzeroedyi_by_dxpRES.Update(dzeroedyi_by_dr, 0, 0); dzeroedyi_by_dxpRES.Update(dzeroedyi_by_dq, 0, 3); }
/// <summary> /// Create a state vector x_v from its component parts. Puts the matrices r, q, v, omega into their right places. /// </summary> /// <param name="r"></param> /// <param name="q"></param> /// <param name="v"></param> /// <param name="omega"></param> /// <param name="xv"></param> public void compose_xv(ref Vector3D r, ref Quaternion q, ref Vector3D v, ref Vector3D omega, ref Vector xv) { xv.Update(r.GetVNL3(), 0); xv.Update(q.GetRXYZ(), 3); xv.Update(v.GetVNL3(), 7); xv.Update(omega.GetVNL3(), 10); }
// Function to find a region in an image guided by current motion prediction // which doesn't overlap existing features public static bool FindNonOverlappingRegion(Scene_Single scene, Vector local_u, float delta_t, Partially_Initialised_Feature_Measurement_Model default_feature_type_for_initialisation, uint camera_width, uint camera_height, uint BOXSIZE, ref int init_feature_search_ustart, ref int init_feature_search_vstart, ref int init_feature_search_ufinish, ref int init_feature_search_vfinish, uint FEATURE_INIT_STEPS_TO_PREDICT, float FEATURE_INIT_DEPTH_HYPOTHESIS, Random rnd) { ThreeD_Motion_Model threed_motion_model = (ThreeD_Motion_Model)scene.get_motion_model(); Vector local_xv = new Vector(scene.get_xv()); for (uint i = 0; i < FEATURE_INIT_STEPS_TO_PREDICT; i++) { scene.get_motion_model().func_fv_and_dfv_by_dxv(local_xv, local_u, delta_t); local_xv.Update(scene.get_motion_model().get_fvRES()); } threed_motion_model.func_xp(local_xv); Vector local_xp = new Vector(threed_motion_model.get_xpRES()); threed_motion_model.func_r(local_xp); Vector3D rW = threed_motion_model.get_rRES(); threed_motion_model.func_q(local_xp); Quaternion qWR = threed_motion_model.get_qRES(); // yW = rW + RWR hR Vector3D hR = new Vector3D(0.0f, 0.0f, FEATURE_INIT_DEPTH_HYPOTHESIS); // Used Inverse + transpose because this was't compiling the normal way Vector3D yW = new Vector3D(rW + qWR.RotationMatrix() * hR); // Then project that point into the current camera position scene.get_motion_model().func_xp(scene.get_xv()); Fully_Initialised_Feature_Measurement_Model fully_init_fmm = (Fully_Initialised_Feature_Measurement_Model)(default_feature_type_for_initialisation.more_initialised_feature_measurement_model); Vector yWVNL = yW.GetVNL3(); fully_init_fmm.func_hi_and_dhi_by_dxp_and_dhi_by_dyi(yWVNL, scene.get_motion_model().get_xpRES()); // Now, this defines roughly how much we expect a feature initialised to move float suggested_u = fully_init_fmm.get_hiRES()[0]; float suggested_v = fully_init_fmm.get_hiRES()[1]; float predicted_motion_u = camera_width / 2.0f - suggested_u; float predicted_motion_v = camera_height / 2.0f - suggested_v; // So, the limits of a "safe" region within which we can initialise // features so that they end up staying within the screen // (Making the approximation that the whole screen moves like the // centre point) int safe_feature_search_ustart = (int)(-predicted_motion_u); int safe_feature_search_vstart = (int)(-predicted_motion_v); int safe_feature_search_ufinish = (int)(camera_width - predicted_motion_u); int safe_feature_search_vfinish = (int)(camera_height - predicted_motion_v); if (safe_feature_search_ustart < ((int)((BOXSIZE - 1) / 2) + 1)) safe_feature_search_ustart = (int)((BOXSIZE - 1) / 2 + 1); if (safe_feature_search_ufinish > (int)camera_width - ((int)((BOXSIZE - 1) / 2) + 1)) safe_feature_search_ufinish = (int)(camera_width - (BOXSIZE - 1) / 2 - 1); if (safe_feature_search_vstart < ((int)((BOXSIZE - 1) / 2) + 1)) safe_feature_search_vstart = (int)((BOXSIZE - 1) / 2 + 1); if (safe_feature_search_vfinish > (int)camera_height - ((int)((BOXSIZE - 1) / 2) + 1)) safe_feature_search_vfinish = (int)(camera_height - (BOXSIZE - 1) / 2 - 1); return FindNonOverlappingRegionNoPredict(safe_feature_search_ustart, safe_feature_search_vstart, safe_feature_search_ufinish, safe_feature_search_vfinish, scene, ref init_feature_search_ustart, ref init_feature_search_vstart, ref init_feature_search_ufinish, ref init_feature_search_vfinish, rnd); }
public override void func_xpredef_and_dxpredef_by_dxp_and_dxpredef_by_dxpdef (Vector xp, Vector xpdef) { // Split position state into cartesian and quaternion // r0, q0: position in original frame func_r(xp); func_q(xp); Vector3D r0 = rRES; Quaternion q0 = qRES; // rn, qn: definition of new frame func_r(xpdef); func_q(xpdef); Vector3D rn = rRES; Quaternion qn = qRES; Quaternion qnbar = qn.Conjugate(); // Calculate new cartesian part of xp Vector3D Temp31a = new Vector3D(r0 - rn); // Temp31a is r0 - rn RotationMatrix Temp33a = qnbar.RotationMatrix(); Vector3D Temp31b = new Vector3D(Temp33a * Temp31a); // Copy into xpredefRES xpredefRES[0] = Temp31b.GetX(); xpredefRES[1] = Temp31b.GetY(); xpredefRES[2] = Temp31b.GetZ(); // Calculate new quaternion part of xp Quaternion Tempqa = qnbar.Multiply(q0); // Copy into xpredefRES Vector vecTempqa = Tempqa.GetRXYZ(); xpredefRES.Update(vecTempqa, 3); // Form Jacobian dxpredef_by_dxpRES dxpredef_by_dxpRES.Fill(0.0f); dxpredef_by_dxpRES.Update(Temp33a, 0, 0); MatrixFixed Temp44a = MatrixFixed.dq3_by_dq1(qnbar); dxpredef_by_dxpRES.Update(Temp44a, 3, 3); // Form Jacobian dxpredef_by_dxpdefRES dxpredef_by_dxpdefRES.Fill(0.0f); //Temp33a *= -1.0f; Temp33a = (RotationMatrix)(Temp33a * - 1.0f); dxpredef_by_dxpdefRES.Update(Temp33a, 0, 0); Temp44a = MatrixFixed.dq3_by_dq2(q0); MatrixFixed Temp44b = MatrixFixed.dqbar_by_dq(); MatrixFixed Temp44c = Temp44a * Temp44b; dxpredef_by_dxpdefRES.Update(Temp44c, 3, 3); // Top right corner of this Jacobian is tricky because we have to // differentiate a rotation matrix // Uses function that does this in bits.cc // Build this corner in Temp34a //MatrixFixed temp = new MatrixFixed(3,4); MatrixFixed Temp34a = MatrixFixed.dRq_times_a_by_dq(qnbar, Temp31a.GetVNL3()); // So far we have drN_by_dqnbar; want _by_dqn MatrixFixed Temp34b = Temp34a * Temp44b; // Finally copy into result matrix dxpredef_by_dxpdefRES.Update(Temp34b, 0, 3); // cout << "dxpredef_by_dxpdefRES" << dxpredef_by_dxpdefRES; }