Go to the documentation of this file.
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>();
114 #undef check_deriving
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);
414 std::this_thread::get_id() == _module<ControlThread>().getControlThreadId();
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 <<
")";
bool isShuttingDown() const
Returns whether the RobotUnit is shutting down.
virtual void onConnectRobotUnit()
called in onConnectComponent
void onExitComponent() final override
void throwIfStateIs(const std::set< RobotUnitState > &stateSet, const std::string &fnc, bool onlyWarn=false) const
Throws an exception if the current state is in.
#define call_module_hook(Type)
#define cast_to_and_call(Type, fn, rethrow)
RobotUnitState getRobotUnitState() const
Returns the RobotUnit's State.
virtual void onInitRobotUnit()
called in onInitComponent
void checkDerivedClasses() const
Checks whether the implementing class derives all modules.
virtual void finishUnitInitialization()
Transition RobotUnitState::InitializingUnits -> RobotUnitState::WaitingForRTThreadInitialization.
for_each_module(check_base) void ModuleBase
bool inControlThread() const
Returns whether the current thread is the ControlThread.
void shutDown()
Requests the RobotUnit to shut down.
void onDisconnectComponent() final override
void componentPropertiesUpdated(const std::set< std::string > &changedProperties) override
void terminate(const Process &p)
virtual void finishControlThreadInitialization()
Transition RobotUnitState::InitializingControlThread -> RobotUnitState::Running.
GuardType getGuard() const
Returns a guard to the RobotUnits mutex.
static std::string CreateBackTrace(int linesToSkip=1)
virtual void onExitRobotUnit()
called in onExitComponent before calling finishRunning
virtual void onDisconnectRobotUnit()
called in onDisconnecComponent
virtual void finishRunning()
Transition RobotUnitState::Running -> RobotUnitState::Exiting.
const std::string & to_string(const std::string &s)
virtual void joinControlThread()=0
Implementations have to join their ControlThread in this hook. (used by RobotUnit::finishRunning())
@ InitializingControlThread
#define check_deriving(Type)
bool areDevicesReady() const
Returns whether Devices are ready.
void icePropertiesInitialized() override
std::unique_lock< MutexType > GuardType
void throwIfInControlThread(const std::string &fnc) const
Throws if the current thread is the ControlThread.
RobotUnitState
The current state of the multi step initialization of a RobotUnit.
void throwIfDevicesNotReady(const std::string &fnc) const
Throws if the Devices are not ready.
std::string getName() const
Retrieve name of object.
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.
virtual void finishComponentInitialization()
Transition RobotUnitState::InitializingComponent -> RobotUnitState::InitializingDevices.
void onInitComponent() final override
This Module holds all high-level data about the robot.
virtual void finishDeviceInitialization()
Transition RobotUnitState::InitializingDevices -> RobotUnitState::InitializingUnits.
double s(double t, double s0, double v0, double a0, double j)
This file offers overloads of toIce() and fromIce() functions for STL container types.
void onConnectComponent() final override