Skip to content
Snippets Groups Projects
frame_base.cpp 9.44 KiB

#include "frame_base.h"
#include "constraint_base.h"
#include "trajectory_base.h"
#include "capture_base.h"
#include "state_block.h"
#include "state_angle.h"
#include "state_quaternion.h"

namespace wolf {

unsigned int FrameBase::frame_id_count_ = 0;

FrameBase::FrameBase(const TimeStamp& _ts, StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, StateBlockPtr _v_ptr) :
            NodeBase("FRAME", "BASE"),
            trajectory_ptr_(),
            state_block_vec_(3), // allow for 6 state blocks by default. Resize in derived constructors if needed.
            is_removing_(false),
            frame_id_(++frame_id_count_),
            type_(NON_KEY_FRAME),
			status_(ST_ESTIMATED),
            time_stamp_(_ts)
{
    state_block_vec_[0] = _p_ptr;
    state_block_vec_[1] = _o_ptr;
    state_block_vec_[2] = _v_ptr;
    //
//    if (isKey())
//        std::cout << "constructed +KF" << id() << std::endl;
//    else
//        std::cout << "constructed  +F" << id() << std::endl;
}

FrameBase::FrameBase(const FrameType & _tp, const TimeStamp& _ts, StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, StateBlockPtr _v_ptr) :
            NodeBase("FRAME", "BASE"),
            trajectory_ptr_(),
            state_block_vec_(3), // allow for 3 state blocks by default. Resize in derived constructors if needed.
            is_removing_(false),
            frame_id_(++frame_id_count_),
            type_(_tp),
			status_(ST_ESTIMATED),
            time_stamp_(_ts)
{
    state_block_vec_[0] = _p_ptr;
    state_block_vec_[1] = _o_ptr;
    state_block_vec_[2] = _v_ptr;

//    if (isKey())
//        std::cout << "constructed +KF" << id() << std::endl;
//    else
//        std::cout << "constructed  +F" << id() << std::endl;
}
                
FrameBase::~FrameBase()
{
    removeStateBlocks();
}

void FrameBase::remove()
{
    if (!is_removing_)
    {
        is_removing_ = true;
        FrameBasePtr this_F = shared_from_this(); // keep this alive while removing it
        TrajectoryBasePtr T = trajectory_ptr_.lock();
        if (T)
        {
            T->getFrameList().remove(this_F); // remove from upstream
        }
        while (!capture_list_.empty())
        {
            capture_list_.front()->remove(); // remove downstream
        }
        while (!constrained_by_list_.empty())
        {
            constrained_by_list_.front()->remove(); // remove constrained
        }

        // Remove Frame State Blocks
        removeStateBlocks();

        if (getTrajectoryPtr()->getLastKeyFramePtr()->id() == this_F->id())
            getTrajectoryPtr()->setLastKeyFramePtr(getTrajectoryPtr()->findLastKeyFramePtr());

//        std::cout << "Removed       F" << id() << std::endl;
    }
}

void FrameBase::registerNewStateBlocks()
{
    if (getProblem() != nullptr)
    {
        for (StateBlockPtr sbp : getStateBlockVec())
            if (sbp != nullptr)
                getProblem()->addStateBlock(sbp);
    }
}

void FrameBase::removeStateBlocks()
{
    for (unsigned int i = 0; i < state_block_vec_.size(); i++)
    {
        StateBlockPtr sbp = getStateBlockPtr(i);
        if (sbp != nullptr)
        {
            if (getProblem() != nullptr && type_ == KEY_FRAME)
            {
                getProblem()->removeStateBlockPtr(sbp);
            }
            setStateBlockPtr(i, nullptr);
        }
    }
}

void FrameBase::setKey()
{
    if (type_ != KEY_FRAME)
    {
        type_ = KEY_FRAME;
        registerNewStateBlocks();

        if (getTrajectoryPtr()->getLastKeyFramePtr() == nullptr || getTrajectoryPtr()->getLastKeyFramePtr()->getTimeStamp() < time_stamp_)
            getTrajectoryPtr()->setLastKeyFramePtr(shared_from_this());

        getTrajectoryPtr()->sortFrame(shared_from_this());
    }
}

void FrameBase::setState(const Eigen::VectorXs& _st)
{
    int size = 0;
    for(unsigned int i = 0; i<state_block_vec_.size(); i++){
        size += (state_block_vec_[i]==nullptr ? 0 : state_block_vec_[i]->getSize());
    }
    
    assert(_st.size() == size && "In FrameBase::setState wrong state size");

    unsigned int index = 0;
    for (StateBlockPtr sb : state_block_vec_)
        if (sb)
        {
            sb->setState(_st.segment(index, sb->getSize()));
            index += sb->getSize();
        }
}

Eigen::VectorXs FrameBase::getState() const
{
    Size size = 0;
    for (StateBlockPtr sb : state_block_vec_)
        if (sb)
            size += sb->getSize();
    Eigen::VectorXs state(size);

    getState(state);

    return state;
}

void FrameBase::getState(Eigen::VectorXs& state) const
{
    Size size = 0;
    for (StateBlockPtr sb : state_block_vec_)
        if (sb)
            size += sb->getSize();

    assert(state.size() == size && "Wrong state vector size");

    unsigned int index = 0;

    for (StateBlockPtr sb : state_block_vec_)
        if (sb)
        {
            state.segment(index,sb->getSize()) = sb->getState();
            index += sb->getSize();
        }
}

unsigned int FrameBase::getSize() const
{
    unsigned int size = 0;
    for (auto st : state_block_vec_)
        if (st)
            size += st->getSize();
    return size;
}

FrameBasePtr FrameBase::getPreviousFrame() const
{
    //std::cout << "finding previous frame of " << this->frame_id_ << std::endl;
    if (getTrajectoryPtr() == nullptr)
        //std::cout << "This Frame is not linked to any trajectory" << std::endl;

    assert(getTrajectoryPtr() != nullptr && "This Frame is not linked to any trajectory");

    //look for the position of this node in the upper list (frame list of trajectory)
    for (auto f_it = getTrajectoryPtr()->getFrameList().rbegin(); f_it != getTrajectoryPtr()->getFrameList().rend(); f_it++ )
    {
        if ( this->frame_id_ == (*f_it)->id() )
        {
        	f_it++;
        	if (f_it != getTrajectoryPtr()->getFrameList().rend())
            {
                //std::cout << "previous frame found!" << std::endl;
                return *f_it;
            }
        	else
        	{
        	    //std::cout << "previous frame not found!" << std::endl;
        	    return nullptr;
        	}
        }
    }
    //std::cout << "previous frame not found!" << std::endl;
    return nullptr;
}

FrameBasePtr FrameBase::getNextFrame() const
{
    //std::cout << "finding next frame of " << this->frame_id_ << std::endl;
	auto f_it = getTrajectoryPtr()->getFrameList().rbegin();
	f_it++; //starting from second last frame

    //look for the position of this node in the frame list of trajectory
    while (f_it != getTrajectoryPtr()->getFrameList().rend())
    {
        if ( this->frame_id_ == (*f_it)->id())
        {
        	f_it--;
			return *f_it;
        }
    	f_it++;
    }
    std::cout << "next frame not found!" << std::endl;
    return nullptr;
}

void FrameBase::setStatus(StateStatus _st)
{

    status_ = _st;

    if (status_ == ST_FIXED)
    {
        for (StateBlockPtr sb : state_block_vec_)
            if (sb != nullptr)
            {
                sb->fix();
                if (getProblem() != nullptr)
                    getProblem()->updateStateBlockPtr(sb);
            }
    }
    else if (status_ == ST_ESTIMATED)
    {
        for (StateBlockPtr sb : state_block_vec_)
            if (sb != nullptr)
            {
                sb->unfix();
                if (getProblem() != nullptr)
                    getProblem()->updateStateBlockPtr(sb);
            }
    }
}

FrameBasePtr FrameBase::create_PO_2D(const FrameType & _tp,
                                     const TimeStamp& _ts,
                                     const Eigen::VectorXs& _x)
{
    assert(_x.size() == 3 && "Wrong state vector size. Should be 3 for 2D!");
    StateBlockPtr p_ptr ( std::make_shared<StateBlock>    (_x.head    <2> ( ) ) );
    StateBlockPtr o_ptr ( std::make_shared<StateAngle>    ((Scalar) _x(2) ) );
    StateBlockPtr v_ptr ( nullptr );
    FrameBasePtr f ( std::make_shared<FrameBase>(_tp, _ts, p_ptr, o_ptr, v_ptr) );
    f->setType("PO 2D");
    return f;
}
FrameBasePtr FrameBase::create_PO_3D(const FrameType & _tp,
                                     const TimeStamp& _ts,
                                     const Eigen::VectorXs& _x)
{
    assert(_x.size() == 7 && "Wrong state vector size. Should be 7 for 3D!");
    StateBlockPtr p_ptr ( std::make_shared<StateBlock>      (_x.head    <3> ( ) ) );
    StateBlockPtr o_ptr ( std::make_shared<StateQuaternion> (_x.tail    <4> ( ) ) );
    StateBlockPtr v_ptr ( nullptr );
    FrameBasePtr f ( std::make_shared<FrameBase>(_tp, _ts, p_ptr, o_ptr, v_ptr) );
    f->setType("PO 3D");
    return f;
}
FrameBasePtr FrameBase::create_POV_3D(const FrameType & _tp,
                                     const TimeStamp& _ts,
                                     const Eigen::VectorXs& _x)
{
    assert(_x.size() == 10 && "Wrong state vector size. Should be 10 for 3D!");
    StateBlockPtr p_ptr ( std::make_shared<StateBlock>      (_x.head    <3> ( ) ) );
    StateBlockPtr o_ptr ( std::make_shared<StateQuaternion> (_x.segment <4> (3) ) );
    StateBlockPtr v_ptr ( std::make_shared<StateBlock>      (_x.tail    <3> ( ) ) );
    FrameBasePtr f ( std::make_shared<FrameBase>(_tp, _ts, p_ptr, o_ptr, v_ptr) );
    f->setType("POV 3D");
    return f;
}

} // namespace wolf

#include "factory.h"
namespace wolf
{
namespace{ const bool Frame_PO_2D_Registered  = FrameFactory::get().registerCreator("PO 2D",  FrameBase::create_PO_2D ); }
namespace{ const bool Frame_PO_3D_Registered  = FrameFactory::get().registerCreator("PO 3D",  FrameBase::create_PO_3D ); }
namespace{ const bool Frame_POV_3D_Registered = FrameFactory::get().registerCreator("POV 3D", FrameBase::create_POV_3D); }
} // namespace wolf