27#include <VirtualRobot/Robot.h>
43 return "RobotUnitState::InitializingComponent";
45 return "RobotUnitState::InitializingDevices";
47 return "RobotUnitState::InitializingUnits";
49 return "RobotUnitState::InitializingControlThread";
51 return "RobotUnitState::Running";
53 return "RobotUnitState::Exiting";
55 throw std::invalid_argument{
"Unknown state " +
to_string(
static_cast<std::size_t
>(s)) +
65#define cast_to_and_call(Type, fn, rethrow) \
69 dynamic_cast<Type*>(this)->Type::fn; \
71 catch (Ice::Exception & e) \
73 ARMARX_ERROR << "exception in " << #Type "::" #fn << "!\nwhat:\n" \
74 << e.what() << "\n\tid : " << e.ice_id() << "\n\tfile : " << e.ice_file() \
75 << "\n\tline : " << e.ice_line() << "\n\tstack: " << e.ice_stackTrace(); \
81 catch (std::exception & e) \
83 ARMARX_ERROR << "exception in " << #Type "::" #fn << "!\nwhat:\n" << e.what(); \
91 ARMARX_ERROR << "exception in " << #Type "::" #fn << "!"; \
98#define for_each_module_apply(r, data, elem) data(elem)
99#define for_each_module(macro) \
100 BOOST_PP_SEQ_FOR_EACH(for_each_module_apply, macro, BOOST_PP_VARIADIC_TO_SEQ(RobotUnitModules))
102#define check_base(Type) \
103 static_assert(std::is_base_of<ModuleBase, Type>::value, \
104 "The RobotUnitModule '" #Type "' has to derived ModuleBase");
110#define check_deriving(Type) \
111 ARMARX_CHECK_NOT_NULL(dynamic_cast<const Type*>(this)) \
112 << "This class does not derive from " << GetTypeString<Type>();
129#define call_module_hook(Type) \
130 cast_to_and_call(::armarx::RobotUnitModule::Type, _preOnInitRobotUnit(), true)
132#undef call_module_hook
136#define call_module_hook(Type) \
137 cast_to_and_call(::armarx::RobotUnitModule::Type, _postOnInitRobotUnit(), true)
139#undef call_module_hook
150#define call_module_hook(Type) \
151 cast_to_and_call(::armarx::RobotUnitModule::Type, _preOnConnectRobotUnit(), true)
153#undef call_module_hook
157#define call_module_hook(Type) \
158 cast_to_and_call(::armarx::RobotUnitModule::Type, _postOnConnectRobotUnit(), true)
160#undef call_module_hook
169#define call_module_hook(Type) \
170 cast_to_and_call(::armarx::RobotUnitModule::Type, _preOnDisconnectRobotUnit(), true)
172#undef call_module_hook
176#define call_module_hook(Type) \
177 cast_to_and_call(::armarx::RobotUnitModule::Type, _postOnDisconnectRobotUnit(), true)
179#undef call_module_hook
191#define call_module_hook(Type) \
192 cast_to_and_call(::armarx::RobotUnitModule::Type, _preOnExitRobotUnit(), false)
194#undef call_module_hook
198#define call_module_hook(Type) \
199 cast_to_and_call(::armarx::RobotUnitModule::Type, _postOnExitRobotUnit(), false)
201#undef call_module_hook
209#define call_module_hook(Type) \
211 ::armarx::RobotUnitModule::Type, _componentPropertiesUpdated(changedProperties), true)
213#undef call_module_hook
219#define call_module_hook(Type) \
220 cast_to_and_call(::armarx::RobotUnitModule::Type, _icePropertiesInitialized(), true)
222#undef call_module_hook
235#define call_module_hook(Type) \
236 cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishComponentInitialization(), true)
238#undef call_module_hook
242#define call_module_hook(Type) \
243 cast_to_and_call(::armarx::RobotUnitModule::Type, _postFinishComponentInitialization(), true)
245#undef call_module_hook
256#define call_module_hook(Type) \
257 cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishDeviceInitialization(), true)
259#undef call_module_hook
263#define call_module_hook(Type) \
264 cast_to_and_call(::armarx::RobotUnitModule::Type, _postFinishDeviceInitialization(), true)
266#undef call_module_hook
277#define call_module_hook(Type) \
278 cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishUnitInitialization(), true)
280#undef call_module_hook
284#define call_module_hook(Type) \
285 cast_to_and_call(::armarx::RobotUnitModule::Type, _postFinishUnitInitialization(), true)
287#undef call_module_hook
298#define call_module_hook(Type) \
299 cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishControlThreadInitialization(), true)
301#undef call_module_hook
305#define call_module_hook(Type) \
307 ::armarx::RobotUnitModule::Type, _postFinishControlThreadInitialization(), true)
309#undef call_module_hook
325#define call_module_hook(Type) \
326 cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishRunning(), false)
328#undef call_module_hook
333#define call_module_hook(Type) \
334 cast_to_and_call(::armarx::RobotUnitModule::Type, _postFinishRunning(), false)
336#undef call_module_hook
339#undef for_each_module_apply
340#undef for_each_module
341#undef cast_to_and_call
346 const std::set<RobotUnitState> ModuleBase::DevicesReadyStates{
357 const auto transitionErrorMessage = [=,
this](
RobotUnitState expectedFrom)
360 "! The expected source state is " +
to_string(expectedFrom) +
".";
362 const auto transitionErrorThrow = [=,
this](
RobotUnitState expectedFrom)
364 if (state != expectedFrom)
366 const auto msg = transitionErrorMessage(expectedFrom);
368 throw std::invalid_argument{msg};
375 throw std::invalid_argument{
376 "Can't switch to state RobotUnitState::InitializingComponent"};
396 throw std::invalid_argument{
"setRobotUnitState: Unknown target state " +
397 to_string(
static_cast<std::size_t
>(to)) +
407 return DevicesReadyStates.count(state);
423 std::stringstream
str;
424 str <<
"Called function '" << fnc <<
"' in the Control Thread\nStack trace:\n"
427 throw LogicError{
str.str()};
437 throw LogicError{
"Attempted to lock mutex in Control Thread\nStack trace:\n" +
440 GuardType guard{dataMutex, std::defer_lock};
441 if (guard.try_lock())
445 while (!guard.try_lock_for(std::chrono::microseconds{100}))
449 throw LogicError{
"Attempting to lock mutex during shutdown\nStacktrace\n" +
459 const std::string& fnc,
463 if (!stateSet.count(state))
465 std::stringstream ss;
466 ss << fnc <<
": Can't be called if state is not in {";
483 throw LogicError{ss.str()};
496 const std::string& fnc,
500 if (stateSet.count(state))
502 std::stringstream ss;
503 ss << fnc <<
": Can't be called if state is in {";
520 throw LogicError{ss.str()};
537 std::atomic<ModuleBase*> ModuleBase::Instance_{
nullptr};
542 if (Instance_ &&
this != Instance_)
544 ARMARX_FATAL <<
"This class is a Singleton. It was already instantiated. (Instance = "
545 << Instance_ <<
", this = " <<
this <<
")";
#define check_deriving(Type)
#define call_module_hook(Type)
#define for_each_module(macro)
#define cast_to_and_call(Type, fn, rethrow)
static std::string CreateBackTrace(int linesToSkip=1)
std::string getName() const
Retrieve name of object.
virtual void finishDeviceInitialization()
Transition InitializingDevices -> InitializingUnits.
RobotUnitState getRobotUnitState() const
Returns the RobotUnit's State.
void shutDown()
Requests the RobotUnit to shut down.
void onConnectComponent() final override
void onExitComponent() final override
void componentPropertiesUpdated(const std::set< std::string > &changedProperties) override
virtual void finishRunning()
Transition Running -> Exiting.
T & _module()
Returns this as ref to the given type.
bool areDevicesReady() const
Returns whether Devices are ready.
void onDisconnectComponent() final override
virtual void finishUnitInitialization()
Transition InitializingUnits -> RobotUnitState::WaitingForRTThreadInitialization.
void checkDerivedClasses() const
Checks whether the implementing class derives all modules.
GuardType getGuard() const
Returns a guard to the RobotUnits mutex.
void throwIfInControlThread(const std::string &fnc) const
Throws if the current thread is the ControlThread.
virtual void finishControlThreadInitialization()
Transition InitializingControlThread -> Running.
void onInitComponent() final override
void throwIfStateIsNot(const std::set< RobotUnitState > &stateSet, const std::string &fnc, bool onlyWarn=false) const
Throws an exception if the current state is not in.
void throwIfStateIs(const std::set< RobotUnitState > &stateSet, const std::string &fnc, bool onlyWarn=false) const
Throws an exception if the current state is in.
virtual void onConnectRobotUnit()
called in onConnectComponent
virtual void onDisconnectRobotUnit()
called in onDisconnecComponent
bool inControlThread() const
Returns whether the current thread is the ControlThread.
virtual void onInitRobotUnit()
called in onInitComponent
virtual void onExitRobotUnit()
called in onExitComponent before calling finishRunning
virtual void joinControlThread()=0
Implementations have to join their ControlThread in this hook. (used by RobotUnit::finishRunning())
bool isShuttingDown() const
Returns whether the RobotUnit is shutting down.
void throwIfDevicesNotReady(const std::string &fnc) const
Throws if the Devices are not ready.
void icePropertiesInitialized() override
std::unique_lock< MutexType > GuardType
virtual void finishComponentInitialization()
Transition InitializingComponent -> InitializingDevices.
This Module holds all high-level data about the robot.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_FATAL
The logging level for unexpected behaviour, that will lead to a seriously malfunctioning program and ...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
This file offers overloads of toIce() and fromIce() functions for STL container types.
RobotUnitState
The current state of the multi step initialization of a RobotUnit.
@ InitializingControlThread
const std::string & to_string(const std::string &s)