12 namespace mrpt {
namespace srba {
14 #define OBS_SUPER_VERBOSE 0
16 template <
class KF2KF_POSE_TYPE,
class LM_TYPE,
class OBS_TYPE,
class RBA_OPTIONS>
24 m_profiler.enter(
"add_observation");
26 ASSERT_( !( fixed_relative_position!=NULL && unknown_relative_position_init_val!=NULL) )
28 const bool is_1st_time_seen = ( new_obs.
feat_id>=rba_state.all_lms.size() || rba_state.all_lms[new_obs.
feat_id].rfp==NULL );
32 (fixed_relative_position!=NULL)
34 (!is_1st_time_seen && rba_state.all_lms[new_obs.
feat_id].has_known_pos );
38 const size_t new_obs_idx = rba_state.all_observations.size();
40 #ifdef SRBA_WORKAROUND_MSVC9_DEQUE_BUG
43 rba_state.all_observations.push_back(
k2f_edge_t());
46 rba_state.all_observations_Jacob_validity.push_back(1);
47 char *
const jacob_valid_bit = &(*rba_state.all_observations_Jacob_validity.rbegin());
50 #ifdef SRBA_WORKAROUND_MSVC9_DEQUE_BUG
51 k2f_edge_t & new_k2f_edge = *(*rba_state.all_observations.rbegin());
53 k2f_edge_t & new_k2f_edge = *rba_state.all_observations.rbegin();
64 new_rfp.id_frame_base = observing_kf_id;
65 new_rfp.pos = *fixed_relative_position;
69 rba_state.known_lms.end(),
70 typename TRelativeLandmarkPosMap::value_type(new_obs.
feat_id, new_rfp )
74 if (new_obs.
feat_id >= rba_state.all_lms.size()) rba_state.all_lms.resize(new_obs.
feat_id+1);
83 new_rfp.id_frame_base = observing_kf_id;
84 if (unknown_relative_position_init_val)
85 new_rfp.pos = *unknown_relative_position_init_val;
88 sensor_model_t::inverse_sensor_model(new_rfp.pos,new_obs.
obs_data,this->parameters.sensor);
91 RBA_OPTIONS::sensor_pose_on_robot_t::template sensor2robot_point<LM_TYPE>(new_rfp.pos, this->parameters.sensor_pose );
95 rba_state.unknown_lms.end(),
96 typename TRelativeLandmarkPosMap::value_type( new_obs.
feat_id, new_rfp )
100 if (new_obs.
feat_id >= rba_state.all_lms.size()) rba_state.all_lms.resize(new_obs.
feat_id+1);
105 rba_state.lin_system.dh_df.appendCol( new_obs.
feat_id );
112 const TKeyFrameID base_id = lm_rel_pos->id_frame_base;
116 new_k2f_edge.
obs.
kf_id = observing_kf_id;
117 new_k2f_edge.
obs.
obs = new_obs;
126 ASSERTDEB_( observing_kf_id < rba_state.keyframes.size() )
128 keyframe_info &kf_info = rba_state.keyframes[ observing_kf_id ];
141 m_profiler.enter(
"add_observation.jacobs.sym");
146 bool graph_says_ignore_this_obs =
false;
148 if (base_id!=new_k2f_edge.
obs.
kf_id)
150 #if OBS_SUPER_VERBOSE
151 std::cout <<
"Jacobian dh_dAp for obs #"<<new_obs_idx <<
" has these edges [obs_kf="<<observing_kf_id<<
" base_kf="<< base_id<<
"]:\n";
155 const TKeyFrameID from = std::max(observing_kf_id, base_id);
156 const TKeyFrameID to = std::min(observing_kf_id, base_id);
158 const bool all_edges_inverse = (from!=observing_kf_id);
161 ASSERTMSG_(it_map != rba_state.spanning_tree.sym.all_edges.end(),
mrpt::format(
"No ST.all_edges found for observing_id=%u, base_id=%u", static_cast<unsigned int>(observing_kf_id), static_cast<unsigned int>(base_id) ) )
166 if (it_obs_ed != it_map->second.end())
172 for (
size_t j=0;j<obs_edges.size();j++)
174 const size_t i = all_edges_inverse ? (obs_edges.size()-j-1) : j;
178 const size_t edge_id = obs_edges[i]->id;
181 const bool normal_dir = (obs_edges[i]->to==curKF);
183 #if OBS_SUPER_VERBOSE
184 std::cout <<
" * edge #"<<edge_id<<
": "<<obs_edges[i]->from <<
" => "<<obs_edges[i]->to <<
" (inverse: " << (normal_dir ?
"no":
"yes") <<
")\n";
188 typename TSparseBlocksJacobians_dh_dAp::col_t & col = rba_state.lin_system.dh_dAp.getCol(edge_id);
193 typename TSparseBlocksJacobians_dh_dAp::col_t::value_type( new_obs_idx,
typename TSparseBlocksJacobians_dh_dAp::TEntry() )
196 typename TSparseBlocksJacobians_dh_dAp::TEntry & entry = it_new_entry->second;
198 entry.sym.obs_idx = new_obs_idx;
199 entry.sym.is_valid = jacob_valid_bit;
200 entry.sym.edge_normal_dir = normal_dir;
201 entry.sym.kf_d = curKF;
202 entry.sym.kf_base = base_id;
203 entry.sym.feat_rel_pos = lm_rel_pos;
204 entry.sym.k2k_edge_id = edge_id;
208 entry.sym.rel_pose_base_from_d1 = & rba_state.spanning_tree.num[curKF][base_id];
209 entry.sym.rel_pose_d1_from_obs =
210 (curKF==observing_kf_id) ?
213 & rba_state.spanning_tree.num[observing_kf_id][curKF];
216 curKF = normal_dir ? obs_edges[i]->from : obs_edges[i]->to;
222 graph_says_ignore_this_obs=
true;
229 if (!is_fixed && !graph_says_ignore_this_obs)
238 const size_t col_idx = it_idx->second;
241 cout <<
"dh_df: col_idx=" << col_idx <<
" feat_id=" << remapIdx <<
" obs_idx=" << new_obs_idx << endl;
244 typename TSparseBlocksJacobians_dh_df::col_t & col = rba_state.lin_system.dh_df.getCol(col_idx);
249 typename TSparseBlocksJacobians_dh_df::col_t::value_type( new_obs_idx,
typename TSparseBlocksJacobians_dh_df::TEntry() )
252 typename TSparseBlocksJacobians_dh_df::TEntry & entry = it_new_entry->second;
254 entry.sym.obs_idx = new_obs_idx;
255 entry.sym.is_valid = jacob_valid_bit;
258 entry.sym.feat_rel_pos = lm_rel_pos;
261 entry.sym.rel_pose_base_from_obs =
265 & rba_state.spanning_tree.num[observing_kf_id][base_id];
268 m_profiler.leave(
"add_observation.jacobs.sym");
270 m_profiler.leave(
"add_observation");
Elemental observation data.
obs_traits_t::observation_t obs
Observation data.
TLandmarkID feat_id
Observed what.
OBS_TRAITS::obs_data_t obs_data
Observed data.
vec_t::const_iterator const_iterator
kf2kf_pose_traits< KF2KF_POSE_TYPE >::k2k_edge_vector_t k2k_edge_vector_t
iterator find(const size_t i)
Constant-time find, returning an iterator to the pair or to end() if not found (that is...
const Scalar * const_iterator
std::deque< k2f_edge_t * > adjacent_k2f_edges
lm_traits_t::TRelativeLandmarkPos * feat_rel_pos
Pointer to the known/unknown rel.pos. (always!=NULL)
obs_traits_t::array_obs_t obs_arr
Observation data, summarized as an array of its parameters: obs.obs_data.getAsArray(obs_arr);.
bool is_first_obs_of_unknown
true if this is the first observation of a feature with unknown relative position ...
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
landmark_traits_t::TRelativeLandmarkPos TRelativeLandmarkPos
One landmark position (relative to its base KF)
#define OBS_SUPER_VERBOSE
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
TKeyFrameID kf_id
Observed from.
The argument "LM_TRAITS" can be any of those defined in srba/models/landmarks.h (typically, either landmarks::Euclidean3D or landmarks::Euclidean2D).
Information per key-frame needed for RBA.
Keyframe-to-feature edge: observation data stored for each keyframe.
#define ASSERTMSG_(f, __ERROR_MSG)
size_t add_observation(const TKeyFrameID observing_kf_id, const typename observation_traits_t::observation_t &new_obs, const array_landmark_t *fixed_relative_position=NULL, const array_landmark_t *unknown_relative_position_init_val=NULL)
Creates a new known/unknown position landmark (upon first LM observation ), and expands Jacobians wit...
bool feat_has_known_rel_pos
whether it's a known or unknown relative position feature
uint64_t TKeyFrameID
Numeric IDs for key-frames (KFs)