-
Joan Vallvé Navarro authoredJoan Vallvé Navarro authored
capture_base.cpp 10.43 KiB
#include "core/capture/capture_base.h"
#include "core/sensor/sensor_base.h"
namespace wolf{
using namespace Eigen;
unsigned int CaptureBase::capture_id_count_ = 0;
CaptureBase::CaptureBase(const std::string& _type,
const TimeStamp& _ts,
SensorBasePtr _sensor_ptr,
StateBlockPtr _p_ptr,
StateBlockPtr _o_ptr,
StateBlockPtr _intr_ptr) :
NodeBase("CAPTURE", _type),
HasStateBlocks(""),
frame_ptr_(), // nullptr
sensor_ptr_(_sensor_ptr),
calib_size_(0),
capture_id_(++capture_id_count_),
time_stamp_(_ts)
{
if (_sensor_ptr)
{
if (_sensor_ptr->getP() != nullptr and _sensor_ptr->isStateBlockDynamic("P"))
{
assert(_p_ptr && "Pointer to dynamic position params is null!");
addStateBlock("P", _p_ptr, nullptr);
}
else
assert(_p_ptr == nullptr && "Provided dynamic sensor position but the sensor position is static or doesn't exist");
if (_sensor_ptr->getO() != nullptr and _sensor_ptr->isStateBlockDynamic("O"))
{
assert(_o_ptr && "Pointer to dynamic orientation params is null!");
addStateBlock("O", _o_ptr, nullptr);
}
else
assert(_o_ptr == nullptr && "Provided dynamic sensor orientation but the sensor orientation is static or doesn't exist");
if (_sensor_ptr->getIntrinsic() != nullptr and _sensor_ptr->isStateBlockDynamic("I"))
{
assert(_intr_ptr && "Pointer to dynamic intrinsic params is null!");
addStateBlock("I", _intr_ptr, nullptr);
}
else
assert(_intr_ptr == nullptr && "Provided dynamic sensor intrinsics but the sensor intrinsics are static or don't exist");
}
else if (_p_ptr || _o_ptr || _intr_ptr)
{
WOLF_ERROR("Provided sensor parameters but no sensor pointer");
}
updateCalibSize();
}
CaptureBase::~CaptureBase()
{
removeStateBlocks(getProblem());
}
void CaptureBase::remove(bool viral_remove_empty_parent)
{
/* Order of removing:
* Factors are removed first, and afterwards the rest of nodes containing state blocks.
* In case multi-threading, solver can be called while removing.
* This order avoids SolverManager to ignore notifications (efficiency)
*/
if (!is_removing_)
{
WOLF_INFO("CaptureBase::remove");
is_removing_ = true;
CaptureBasePtr this_C = shared_from_this(); // keep this alive while removing it
// remove downstream
while (!constrained_by_list_.empty())
{
constrained_by_list_.front()->remove(viral_remove_empty_parent); // remove constrained by
}
while (!feature_list_.empty())
{
feature_list_.front()->remove(viral_remove_empty_parent); // remove downstream
}
// Remove State Blocks
removeStateBlocks(getProblem());
// remove from upstream
FrameBasePtr F = frame_ptr_.lock();
if (F)
{
F->removeCapture(this_C);
if (viral_remove_empty_parent && F->getCaptureList().empty() && F->getConstrainedByList().empty())
F->remove(viral_remove_empty_parent); // remove upstream
}
}
}
bool CaptureBase::process()
{
assert (getSensor() != nullptr && "Attempting to process a capture with no associated sensor. Either set the capture's sensor or call sensor->process(capture) instead.");
return getSensor()->process(shared_from_this());
}
FeatureBasePtr CaptureBase::addFeature(FeatureBasePtr _ft_ptr)
{
//std::cout << "Adding feature" << std::endl;
feature_list_.push_back(_ft_ptr);
return _ft_ptr;
}
void CaptureBase::removeFeature(FeatureBasePtr _ft_ptr)
{
feature_list_.remove(_ft_ptr);
}
void CaptureBase::getFactorList(FactorBasePtrList& _fac_list) const
{
for (auto f_ptr : getFeatureList())
f_ptr->getFactorList(_fac_list);
}
FactorBasePtr CaptureBase::addConstrainedBy(FactorBasePtr _fac_ptr)
{
constrained_by_list_.push_back(_fac_ptr);
return _fac_ptr;
}
void CaptureBase::removeConstrainedBy(FactorBasePtr _fac_ptr)
{
constrained_by_list_.remove(_fac_ptr);
}
bool CaptureBase::isConstrainedBy(const FactorBasePtr &_factor) const
{
FactorBaseConstIter cby_it = std::find_if(constrained_by_list_.begin(),
constrained_by_list_.end(),
[_factor](const FactorBasePtr & cby)
{
return cby == _factor;
}
);
if (cby_it != constrained_by_list_.end())
return true;
else
return false;
}
const std::string& CaptureBase::getStructure() const
{
if (getSensor())
return getSensor()->getStructure();
else
return HasStateBlocks::getStructure();
}
StateBlockPtr CaptureBase::getStateBlock(const std::string& _key) const
{
if (getSensor() and getSensor()->hasStateBlock(_key))
{
if (getSensor()->isStateBlockDynamic(_key))
return HasStateBlocks::getStateBlock(_key);
else
return getSensor()->getStateBlock(_key);
}
else // No sensor associated, or sensor without this state block: assume sensor params are here
return HasStateBlocks::getStateBlock(_key);
}
void CaptureBase::fix()
{
HasStateBlocks::fix();
updateCalibSize();
}
void CaptureBase::unfix()
{
HasStateBlocks::unfix();
updateCalibSize();
}
SizeEigen CaptureBase::computeCalibSize() const
{
SizeEigen sz = 0;
for (const auto& key : getStructure())
{
auto sb = getStateBlock(key);
if (sb && !sb->isFixed())
sz += sb->getSize();
}
return sz;
}
Eigen::VectorXd CaptureBase::getCalibration() const
{
Eigen::VectorXd calib(calib_size_);
SizeEigen index = 0;
for (const auto& key : getStructure())
{
auto sb = getStateBlock(key);
if (sb && !sb->isFixed())
{
calib.segment(index, sb->getSize()) = sb->getState();
index += sb->getSize();
}
}
return calib;
}
void CaptureBase::setCalibration(const VectorXd& _calib)
{
updateCalibSize();
assert(_calib.size() == calib_size_ && "Wrong size of calibration vector");
SizeEigen index = 0;
for (const auto& key : getStructure())
{
auto sb = getStateBlock(key);
if (sb && !sb->isFixed())
{
sb->setState(_calib.segment(index, sb->getSize()));
index += sb->getSize();
}
}
}
void CaptureBase::move(FrameBasePtr _frm_ptr)
{
WOLF_WARN_COND(this->getFrame() == nullptr, "moving a capture not linked to any frame");
WOLF_WARN_COND(_frm_ptr == nullptr, "moving a capture to a null FrameBasePtr");
assert((this->getFrame() == nullptr || this->getFrame()->isKey()) && "Forbidden: moving a capture already linked to a KF");
assert((_frm_ptr == nullptr || _frm_ptr->isKey()) && "Forbidden: moving a capture to a non-estimated frame");
// Unlink
if (this->getFrame())
{
// unlink from previous non-key frame
this->getFrame()->removeCapture(shared_from_this());
this->setFrame(nullptr);
}
// link
link(_frm_ptr);
}
void CaptureBase::link(FrameBasePtr _frm_ptr)
{
assert(!is_removing_ && "linking a removed capture");
assert(this->getFrame() == nullptr && "linking a capture already linked");
if(_frm_ptr)
{
_frm_ptr->addCapture(shared_from_this());
this->setFrame(_frm_ptr);
this->setProblem(_frm_ptr->getProblem());
}
else
{
WOLF_WARN("Linking with a nullptr");
}
}
void CaptureBase::setProblem(ProblemPtr _problem)
{
if (_problem == nullptr || _problem == this->getProblem())
return;
NodeBase::setProblem(_problem);
registerNewStateBlocks(_problem);
for (auto ft : feature_list_)
ft->setProblem(_problem);
}
void CaptureBase::printHeader(int _depth, bool _constr_by, bool _metric, bool _state_blocks, std::ostream& _stream, std::string _tabs) const
{
_stream << _tabs << "Cap" << id() << " " << getType();
if(getSensor() != nullptr)
{
_stream << " -> Sen" << getSensor()->id();
}
else
_stream << " -> Sen-";
_stream << ((_depth < 3) ? " -- " + std::to_string(getFeatureList().size()) + "f" : "");
if (_constr_by)
{
_stream << " <-- ";
for (auto cby : getConstrainedByList())
_stream << "Fac" << cby->id() << " \t";
}
_stream << std::endl;
if(getStateBlockMap().size() > 0)
{
if (_metric && _state_blocks){
for (const auto& key : getStructure())
{
auto sb = getStateBlock(key);
_stream << _tabs << key << "[" << (sb->isFixed() ? "Fix" : "Est") << "] = ( " << sb->getState().transpose() << " )" << std::endl;
}
}
else if (_metric)
{
_stream << _tabs << (isFixed() ? "Fix" : "Est") << ", ts=" << std::setprecision(5)
<< getTimeStamp();
_stream << ",\t x= ( " << std::setprecision(2) << getState().transpose() << " )";
_stream << std::endl;
}
else if (_state_blocks)
{
_stream << " sb:";
for (const auto& key : getStructure())
{
const auto& sb = getStateBlock(key);
_stream << " " << key << "[" << (sb->isFixed() ? "Fix" : "Est") << "]; ";
}
_stream << std::endl;
}
}
// if (_state_blocks)
// for (const auto& sb : getStateBlockVec())
// {
// if(sb != nullptr)
// {
// _stream << " sb: ";
// _stream << (sb->isFixed() ? "Fix" : "Est");
// if (_metric)
// _stream << std::setprecision(2) << " (" << sb->getState().transpose() << " )";
// _stream << std::endl;
// }
// }
}
void CaptureBase::print(int _depth, bool _constr_by, bool _metric, bool _state_blocks, std::ostream& _stream, std::string _tabs) const
{
printHeader(_depth, _constr_by, _metric, _state_blocks, _stream, _tabs);
if (_depth >= 3)
for (auto f : getFeatureList())
f->print(_depth, _constr_by, _metric, _state_blocks, _stream, _tabs + " ");
}
} // namespace wolf