22 #include "MAController.hpp" 24 #include "core/MADevice.hpp" 25 #include "core/MAValueGenerators.hpp" 26 #include "types/MARobotState.hpp" 27 #include "types/skits/MASkit.hpp" 28 #include "types/skits/MASkitDatabase.hpp" 29 #include "behaviors/MABehaviorManager.hpp" 32 #include <MCThreadLocalData.hpp> 34 #include <boost/algorithm/string/predicate.hpp> 35 #include <boost/algorithm/string.hpp> 43 typedef boost::unordered_map<MADevice*, int> DevicePtrIntMap;
50 void CheckStaticControllerVariables()
52 if (unlikely(!Verbose.get()))
54 Verbose.reset(
new bool);
56 ControllerRef.reset(
new int);
68 CheckStaticControllerVariables();
70 if (*ControllerRef == 1)
77 MAController::~MAController()
80 if (*ControllerRef == 0)
81 delete MA::RobotState.release();
87 MC::StringList TransitionList;
91 TransitionList.push_back(transition.first);
93 return TransitionList;
99 MC::StringList TransitionList;
103 const MA::DeviceGeneratorsMap& DeviceGenerators = transition.second.get<2>();
105 for (
auto& generator : DeviceGenerators)
107 if (generator.first == &device)
109 TransitionList.push_back(transition.first);
113 return TransitionList;
119 std::string Name(name);
120 std::string RealSkitName;
122 unsigned int InitialMovementDuration = 0;
124 if (boost::starts_with(Name, MA::SkitNamePrefix))
126 std::vector<std::string> NameSlices;
128 boost::split(NameSlices, Name, boost::is_any_of(
":"));
129 if (NameSlices.size() <= 1)
131 MC_WARNING(
"Invalid transition name was requested to start: %s", name.c_str());
134 Name = NameSlices[0]+
':'+NameSlices[1];
135 RealSkitName = NameSlices[1];
137 if (NameSlices.size() >= 3 && !NameSlices[2].empty())
138 Scale = MCStrConvert<float>(NameSlices[2]);
140 if (NameSlices.size() >= 4 && !NameSlices[3].empty())
141 InitialMovementDuration = MCStrConvert<unsigned int>(NameSlices[3]);
151 MC_WARNING(
"Unregistered transition name was requested to start: %s", Name.c_str());
157 MC_LOG(
"Start transition: %s", Name.c_str());
159 MA::DeviceGeneratorsMap& DeviceGenerators = Iter->second.get<2>();
160 int InitialMapSize = DeviceGenerators.size();
161 MA::DeviceGeneratorsMap NewDeviceGenerators;
163 if (boost::starts_with(Name, MA::SkitNamePrefix))
166 if (!MA::SkitDatabase.
get())
168 MC_WARNING(
"Skit database is missing to start a skit transition (%s)", Name.c_str());
171 MA::SkitSPtr Skit = MA::SkitDatabase->GetSkit(RealSkitName);
175 if (
Type == MA::MotorController)
177 MA::MotionSkitSPtr MotionSkit = Skit->GetMotionSkit();
179 if (!MotionSkit.get())
181 MC_WARNING(
"Skit (%s) does not contain any motion transition", Name.c_str());
186 if (
Type == MA::LedController)
188 MA::LedSkitSPtr LedSkit = Skit->GetLedSkit();
192 MC_WARNING(
"Skit (%s) does not contain any LED transition", Name.c_str());
198 MC_WARNING(
"Skit (%s) is not in the database to start a transition", Name.c_str());
202 if (Scale > 0 && Scale != 1.0)
204 for (
auto& generator : NewDeviceGenerators)
205 generator.second->ScaleDuration(Scale);
208 if (InitialMovementDuration > 0)
210 for (
auto& generator : NewDeviceGenerators)
214 Generator =
new MASimpleGenerator(generator.second->GetDesiredStartingValue(), InitialMovementDuration);
215 generator.second->AddGenerator(*Generator,
true);
220 NewDeviceGenerators = Iter->second.get<0>()();
225 for (
auto& generator : NewDeviceGenerators)
227 generator.second->SetTransitionName(Name);
231 MA_MERGE_DEVICEGENERATORS(DeviceGenerators, NewDeviceGenerators);
233 if (InitialMapSize == (
int)Iter->second.get<2>().size())
235 MC_WARNING(
"The transition did not register any generators: %s", Name.c_str());
251 MC_WARNING(
"Unregistered transition name was requested to stop: %s", name.c_str());
257 MC_LOG(
"Stop transition: %s", name.c_str());
259 MA::DeviceGeneratorsMap& DeviceGenerators = Iter->second.get<2>();
261 if (DeviceGenerators.size() == 0)
267 for (
auto& generator : DeviceGenerators)
271 if (Device->HasGeneratorContainer(*generator.second))
273 generator.second->BlockExpiredSignal();
274 Device->DeleteGeneratorContainer(*generator.second);
278 DeviceGenerators.clear();
292 MC_WARNING(
"Unregistered transition name was queried: %s", name.c_str());
296 return !Iter->second.get<2>().empty();
304 if (!transition.second.get<2>().empty())
315 if (boost::starts_with(transition.first, MA::SkitNamePrefix) && !transition.second.get<2>().empty())
331 MC_WARNING(
"Unregistered transition name was queried: %s", name.c_str());
335 MA::DeviceGeneratorsMap& DeviceGenerators = Iter->second.get<2>();
337 if (!DeviceGenerators.empty())
340 MA::GeneratorContainerList ExpiredContainers;
345 for (
auto& generator : DeviceGenerators)
349 generator.second->BlockExpiredSignal();
350 if (generator.second->IsExpired())
352 ExpiredContainers.push_back(generator.second);
356 generator.second->UnblockExpiredSignal();
359 for (
unsigned int i = 0; i < ExpiredContainers.size(); ++i)
361 ExpiredContainers[i]->IsExpired();
369 MA::BoolFuncPtr Func = Iter->second.get<1>();
388 MC_WARNING(
"Unregistered transition name was queried: %s", name.c_str());
392 MA::BoolFuncPtr Func = Iter->second.get<1>();
394 return !Func.empty();
408 MC_WARNING(
"Generator container with unregistered transition name: %s", TransitionName.c_str());
414 MA::DeviceGeneratorsMap& DeviceGenerators = Iter->second.get<2>();
415 bool Erasing =
false;
417 for (
auto gen_iter = DeviceGenerators.begin(); gen_iter != DeviceGenerators.end();)
421 if (gen_iter->second == &container)
424 DeviceGenerators.erase(gen_iter++);
429 if (*Verbose && Erasing && DeviceGenerators.empty())
431 MC_LOG(
"Finished transition: %s", TransitionName.c_str());
439 if (!boost::starts_with(skit_name, MA::SkitNamePrefix))
443 return Transitions.insert(std::make_pair(skit_name, MA::TransitionTuple())).first;
449 if (device_generators.empty())
452 DevicePtrIntMap Devices;
455 for (
auto& generator : device_generators)
458 if (Devices.find(generator.first) == Devices.end())
460 Devices[generator.first] = 0;
463 if (generator.first->HasGeneratorContainer(*generator.second))
465 int Duration = generator.second->GetDuration();
470 Devices[generator.first] += Duration;
476 for (
auto& device : Devices)
478 MaxDuration =
MCMax(MaxDuration, device.second);
486 CheckStaticControllerVariables();
487 *Verbose = new_state;
493 CheckStaticControllerVariables();
MAController(MA::ControllerType controller_type)
Class constructor.
bool IsAnyActiveSkitTransition()
Check if any skit transition is active.
static void SetVerbose(bool new_state)
Set the verbosity of the controller domain.
#define MC_WARNING(...)
Warning macro.
#define MA_CALL_CONTAINER_LOCKER_CTOR
Standard call for the MAContainerLocker ctor.
static bool IsVerbose()
Get the verbosity of the controller domain.
bool IsTransitionSuccessful(const std::string &name)
Whenever the transition is successful.
MC::StringList GetTransitionNames() const
Get the list of the transition names.
bool IsAnyActiveTransition()
Check if any transition is active.
static void RegisterUpdater(MARobotStateUpdater &updater)
Register a robot state updater.
virtual void StopTransition(const std::string &name)
Stop a transition.
bool TransitionHasCheck(const std::string &name)
Test if the transition has a check.
Generator container class.
Robot state updater base class.
MC::StringList GetActiveTransitionsByDevice(const MADevice &device)
Get a transition list by device.
std::string GetTransitionName() const
Get the transition name where the container belongs to.
virtual int StartTransition(const std::string &name)
Start a transition.
Base class for generators.
#define MA_GET_CONTAINER_LOCK_ID(_container)
Register a lock ID for a container.
void GeneratorContainerExpired(MAGeneratorContainer &container)
Slot for the expired generator containers.
bool IsTransitionActive(const std::string &name)
Whenever the transition is still active.
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...
MA::TransitionMap::iterator RegisterSkitTransition(const std::string &skit_name)
Register a skit transition if it has not been.
const T MCMax(const U &container)
Get the maximal value of a container.
virtual MA::DeviceGeneratorsMap GetSkitTransitionGenerators(MA::SkitBaseSPtr skit)=0
Get skit transition generators.
int GetDeviceGeneratorsDuration(MA::DeviceGeneratorsMap &device_generators)
Get the duration of the device generators.
#define MA_CONTAINER_LOCK(_container)
Lock a container.
#define MC_LOG(...)
Debug macro.
MA::ControllerType Type
Controller type.
MA::TransitionMap Transitions
The map of the transitions.