Skip to content

Commit

Permalink
[BeamActions] Add BeamActions and BeamActionController to manage cont…
Browse files Browse the repository at this point in the history
…rols (#63)

* backup work

* BAckup work on BeamActions and BeamAdapterActionController

* Add more actions support

* Fix BeamAdapaterAction behavior

* Fix compilation for gcc

* fix compilation for gcc and force true value for listening

* backup work on beam action as string

* [BeamActionController] Add writeMode support using keyboard

* [BeamActionCtrl] Add option to display actions only when exporting using key binding

* Clean & doc

* Fix compile and some warnings

* Fix compile and some warnings

Co-authored-by: Fred R <[email protected]>
Co-authored-by: Frederick Roy <[email protected]>
  • Loading branch information
3 people authored Dec 27, 2022
1 parent d90306a commit fec3eac
Show file tree
Hide file tree
Showing 7 changed files with 471 additions and 52 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ set(HEADER_FILES

${BEAMADAPTER_SRC}/component/controller/AdaptiveBeamController.h
${BEAMADAPTER_SRC}/component/controller/AdaptiveBeamController.inl
${BEAMADAPTER_SRC}/component/controller/BeamAdapterActionController.h
${BEAMADAPTER_SRC}/component/controller/BeamAdapterActionController.inl
${BEAMADAPTER_SRC}/component/controller/InterventionalRadiologyController.h
${BEAMADAPTER_SRC}/component/controller/InterventionalRadiologyController.inl
${BEAMADAPTER_SRC}/component/controller/SutureController.h
Expand All @@ -55,6 +57,7 @@ set(HEADER_FILES
${BEAMADAPTER_SRC}/component/mapping/MultiAdaptiveBeamMapping.inl

${BEAMADAPTER_SRC}/utils/BeamSection.h
${BEAMADAPTER_SRC}/utils/BeamActions.h
${BEAMADAPTER_SRC}/utils/deprecatedcomponent.h
)

Expand All @@ -68,6 +71,7 @@ set(SOURCE_FILES
${BEAMADAPTER_SRC}/component/constraint/AdaptiveBeamLengthConstraint.cpp

${BEAMADAPTER_SRC}/component/controller/AdaptiveBeamController.cpp
${BEAMADAPTER_SRC}/component/controller/BeamAdapterActionController.cpp
${BEAMADAPTER_SRC}/component/controller/InterventionalRadiologyController.cpp
${BEAMADAPTER_SRC}/component/controller/SutureController.cpp

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/******************************************************************************
* BeamAdapter plugin *
* (c) 2006 Inria, University of Lille, CNRS *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Authors: see Authors.md *
* *
* Contact information: [email protected] *
******************************************************************************/
#define SOFA_PLUGIN_BEAMADAPTER_ACTIONCONTROLLER_CPP

#include <sofa/core/ObjectFactory.h>
#include <sofa/defaulttype/VecTypes.h>
#include <sofa/defaulttype/RigidTypes.h>

#include <BeamAdapter/config.h>
#include <BeamAdapter/component/controller/BeamAdapterActionController.inl>

namespace sofa::component::controller
{

const static int BeamAdapterActionControllerClass = core::RegisterObject("BeamAdapterActionController")
.add< BeamAdapterActionController<sofa::defaulttype::Rigid3Types> >()
;

template class SOFA_BEAMADAPTER_API BeamAdapterActionController<sofa::defaulttype::Rigid3Types>;

} // namespace sofa::component::controller
86 changes: 86 additions & 0 deletions src/BeamAdapter/component/controller/BeamAdapterActionController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/******************************************************************************
* BeamAdapter plugin *
* (c) 2006 Inria, University of Lille, CNRS *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Authors: see Authors.md *
* *
* Contact information: [email protected] *
******************************************************************************/
#pragma once

#include <sofa/component/controller/MechanicalStateController.h>
#include <BeamAdapter/utils/BeamActions.h>
#include <BeamAdapter/component/controller/InterventionalRadiologyController.h>
#include <sofa/defaulttype/VecTypes.h>
#include <sofa/defaulttype/RigidTypes.h>
#include <sofa/core/objectmodel/MouseEvent.h>
#include <sofa/core/objectmodel/KeypressedEvent.h>

namespace sofa::component::controller
{

/***
* This class is a SOFA component inheriting from MechanicalStateController.
* It can be used to script the InterventionalRadiologyController using @sa BeamActions
* If @sa d_writeMode mode is on, each keyboard interaction used to control the Beam will be exported with key times.
* Otherwise, it will load a list of @sa BeamActions with their corresponding key times to replay a navigation.
*/
template<class DataTypes>
class BeamAdapterActionController : public MechanicalStateController<DataTypes>
{
public:
SOFA_CLASS(SOFA_TEMPLATE(BeamAdapterActionController, DataTypes), SOFA_TEMPLATE(MechanicalStateController, DataTypes));

using BeamAdapterAction = sofa::beamadapter::BeamAdapterAction;
using interventionCtrl = InterventionalRadiologyController<DataTypes>;
using Real = typename DataTypes::Real;

BeamAdapterActionController();
~BeamAdapterActionController() override = default;

/// Method to init the component. Will search for a InterventionalRadiologyController using link @sa l_interventionController
void init() override;

/// Method called at each timestep. Will check if an action has to be read or write
void onBeginAnimationStep(const double dt) override;

/// Method to control the Beam using keyboard and save the actions in @sa d_actions
void onKeyPressedEvent(core::objectmodel::KeypressedEvent* kev) override;

/// Unused metho for mouse event
void onMouseEvent(core::objectmodel::MouseEvent* ev) override { SOFA_UNUSED(ev);}

Data <bool> d_writeMode; ///< If true, will accumulate actions in @sa d_actions for export. Press key E for export.
Data <type::vector<int> > d_actions; ///< List of actions to import or export.
Data <type::vector<std::string> > d_actionString; ///< List of actions to import or export as string.
Data <type::vector<Real> > d_timeSteps; ///< List of key times corresponding to BeamActions in @sa d_actions or @sa d_actionString

/// Link to the InterventionalRadiologyController, controlling the Beam, to script.
SingleLink<BeamAdapterActionController<DataTypes>, InterventionalRadiologyController<DataTypes>, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_interventionController;

private:
int m_readStep = 0; ///< counter to the current action to read in @sa d_actions
BeamAdapterAction m_currAction = BeamAdapterAction::NO_ACTION; ///< Current action imported or to export
BeamAdapterAction m_lastAction = BeamAdapterAction::NO_ACTION; ///< Previous action imported or to export

bool m_exportActions = false; ///< Bool to dump actions, will be set to true if key 'E' is pressed
};

#if !defined(SOFA_PLUGIN_BEAMADAPTER_ACTIONCONTROLLER_CPP)
extern template class SOFA_BEAMADAPTER_API BeamAdapterActionController<sofa::defaulttype::Rigid3Types>;
#endif

} /// namespace sofa::component::controller
177 changes: 177 additions & 0 deletions src/BeamAdapter/component/controller/BeamAdapterActionController.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/******************************************************************************
* BeamAdapter plugin *
* (c) 2006 Inria, University of Lille, CNRS *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Authors: see Authors.md *
* *
* Contact information: [email protected] *
******************************************************************************/
#pragma once
#include <BeamAdapter/component/controller/BeamAdapterActionController.h>
#include <sofa/core/objectmodel/MouseEvent.h>
#include <sofa/core/objectmodel/KeypressedEvent.h>

namespace sofa::component::controller
{

using namespace sofa::beamadapter;

template <class DataTypes>
BeamAdapterActionController<DataTypes>::BeamAdapterActionController()
: d_writeMode(initData(&d_writeMode, false, "writeMode", "If true, will accumulate actions from keyboard and dump the actions and times when key 'E' is pressed."))
, d_actions(initData(&d_actions, "actions", "List of actions to script the BeamAdapter"))
, d_actionString(initData(&d_actionString, "actionString", "List of actions as string to script the BeamAdapter"))
, d_timeSteps(initData(&d_timeSteps, "timeSteps", "List of key times corresponding to the actions"))
, l_interventionController(initLink("interventionController", "Path to the InterventionalRadiologyController component on scene"))
{

}

template <class DataTypes>
void BeamAdapterActionController<DataTypes>::init()
{
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Loading);
if (!l_interventionController.get())
{
msg_error() << "No l_interventionController given. Component will be set to Invalid.";
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid);
}

// the controller must listen to the event (in particular BeginAnimationStep event)
this->f_listening.setValue(true);

this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Valid);
}


template <class DataTypes>
void BeamAdapterActionController<DataTypes>::onKeyPressedEvent(core::objectmodel::KeypressedEvent* kev)
{
if (!d_writeMode.getValue())
return;

/// Control keys for interventonal Radiology simulations:
switch (kev->getKey())
{
case 'E':
m_currAction = BeamAdapterAction::NO_ACTION;
m_exportActions = !m_exportActions;
break;
case 'D':
m_currAction = BeamAdapterAction::DROP_TOOL;
break;
case '2':
m_currAction = BeamAdapterAction::USE_TOOL_2;
break;
case '1':
m_currAction = BeamAdapterAction::USE_TOOL_1;
break;
case '0':
m_currAction = BeamAdapterAction::USE_TOOL_0;
break;
case 20: // droite = 20
if (m_currAction == BeamAdapterAction::SPIN_RIGHT)
m_currAction = BeamAdapterAction::NO_ACTION;
else
m_currAction = BeamAdapterAction::SPIN_RIGHT;

break;
case 18: // gauche = 18
if (m_currAction == BeamAdapterAction::SPIN_LEFT)
m_currAction = BeamAdapterAction::NO_ACTION;
else
m_currAction = BeamAdapterAction::SPIN_LEFT;

break;
case 19: // fleche haut = 19
if (m_currAction == BeamAdapterAction::MOVE_FORWARD)
m_currAction = BeamAdapterAction::NO_ACTION;
else
m_currAction = BeamAdapterAction::MOVE_FORWARD;

break;
case 21: // bas = 21
if (m_currAction == BeamAdapterAction::MOVE_BACKWARD)
m_currAction = BeamAdapterAction::NO_ACTION;
else
m_currAction = BeamAdapterAction::MOVE_BACKWARD;

break;
default:
m_currAction = BeamAdapterAction::NO_ACTION;
break;
}
}


template <class DataTypes>
void BeamAdapterActionController<DataTypes>::onBeginAnimationStep(const double /*dt*/)
{
const auto currentTime = this->getContext()->getTime();
if (d_writeMode.getValue())
{
interventionCtrl* ctrl = l_interventionController.get();
ctrl->applyAction(m_currAction);

if (m_lastAction != m_currAction)
{
auto times = sofa::helper::WriteAccessor(d_timeSteps);
auto actions = sofa::helper::WriteAccessor(d_actions);
times.push_back(currentTime);
actions.push_back(int(m_currAction));

if (m_exportActions)
{
std::cout << "timeSteps='" << times.wref() << "'" << std::endl;
std::cout << "actions='" << actions.wref() << "'" << std::endl;
}

m_lastAction = m_currAction;
}

if (m_currAction >= BeamAdapterAction::SWITCH_NEXT_TOOL) // action regarding tool needs only to be triggered once
{
m_currAction = BeamAdapterAction::NO_ACTION;
}
}
else
{
const type::vector<Real>& times = d_timeSteps.getValue();
if (!times.empty())
{
if (m_readStep < times.size())
{
Real time = times[m_readStep];
if (currentTime >= time) // check if another key time has been reached and change action
{
m_currAction = BeamAdapterAction(d_actions.getValue()[m_readStep]);
m_readStep++;
}
}

interventionCtrl* ctrl = l_interventionController.get();
ctrl->applyAction(m_currAction);

if (m_currAction >= BeamAdapterAction::SWITCH_NEXT_TOOL) // action regarding tool needs only to be triggered once
{
m_currAction = BeamAdapterAction::NO_ACTION;
}
}
}
}


} // namespace sofa::component::controller
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <sofa/component/collision/geometry/PointModel.h>
#include <sofa/component/collision/geometry/LineModel.h>

#include <BeamAdapter/utils/BeamActions.h>
#include <BeamAdapter/component/WireBeamInterpolation.h>
#include <sofa/component/topology/container/dynamic/EdgeSetGeometryAlgorithms.h>
#include <sofa/component/topology/container/dynamic/EdgeSetTopologyModifier.h>
Expand Down Expand Up @@ -108,8 +109,11 @@ class InterventionalRadiologyController : public MechanicalStateController<DataT
const type::vector< type::vector<int> >& get_id_instrument_curvAbs_table()const;
int getTotalNbEdges()const;

void applyAction(sofa::beamadapter::BeamAdapterAction action);

/// Getter to the tools curviline abscisses sorted @sa m_nodeCurvAbs at the current timestep.
[[nodiscard]] const type::vector<Real>& getCurrentCurvAbscisses() const { return m_nodeCurvAbs; }

public:

using Inherit1::f_printLog;
Expand Down
Loading

0 comments on commit fec3eac

Please sign in to comment.