Main Page · Modules · All Classes · Class Hierarchy
MABehaviorManager.cpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #include "MABehaviorManager.hpp"
23 
24 #include "core/MAMicrophoneDevice.hpp"
25 #include "types/skits/MASkitDatabase.hpp"
26 #include "sound/MASoundDatabase.hpp"
27 #include "controllers/MAController.hpp"
28 #include "ml/MAClassifierModels.hpp"
29 #include "ml/MADataCollector.hpp"
30 #include "MABatteryStatus.hpp"
31 #include "MABodyAngry.hpp"
32 #include "MABodyAwaking.hpp"
33 #include "MABodyHappy.hpp"
34 #include "MABodyPoked.hpp"
35 #include "MABodyStateMaster.hpp"
36 #include "MABodySleeping.hpp"
37 #include "MABodyStroked.hpp"
38 #include "MAChangeEyePupil.hpp"
39 #include "MAClientConnected.hpp"
40 #include "MADataUploadStatus.hpp"
41 #include "MAEyePupil.hpp"
42 #include "MAHeadLookAroundMaster.hpp"
43 #include "MAHeavyCalculations.hpp"
44 #include "MASkitterPlaybackMaster.hpp"
45 #include "MAMouthSpeakingMaster.hpp"
46 #include "MANoWritableStorage.hpp"
47 #include "MANumberGameMaster.hpp"
48 #include "MAHeadTurnMaster.hpp"
49 #include "MASoundEventMaster.hpp"
50 #include "MASpeakerVolume.hpp"
51 #include "MAStartUp.hpp"
52 #include "MASwitchSoundProfile.hpp"
53 #include "MASwitchVolumeControl.hpp"
54 #include "numbergame/MANumberGameMaster.hpp"
55 
56 #include <MCLog.hpp>
57 #include <MCTimer.hpp>
58 
59 namespace MA
60 {
61 MCThreadLocalData<MABehaviorManager> BehaviorManager(false);
62 MCThreadLocalData<MAClassifierModels> ClassifierModels(true);
63 }
64 
65 MABehaviorManager::MABehaviorManager() : Verbose(false)
66 {
67  if (MA::BehaviorManager.get())
68  {
69  MC_WARNING("The global behavior manager is overridden.");
70  }
71  MA::BehaviorManager.reset(this);
72  if (!MA::DataCollector.get())
73  {
74  MA::DataCollector.reset(new MADataCollector);
75  }
76  if (!MA::ClassifierModels.get())
77  {
78  MA::ClassifierModels.reset(new MAClassifierModels);
79  }
80 }
81 
82 
83 MABehaviorManager::~MABehaviorManager()
84 {
85  if (MA::BehaviorManager.get() == this)
86  {
87  MA::BehaviorManager.release();
88  }
90  if (MA::SkitDatabase.get())
91  {
92  MA::SkitDatabase.reset(nullptr);
93  }
94  if (MA::SoundDatabase.get())
95  {
96  MA::SoundDatabase.reset(nullptr);
97  }
98  if (MA::DataCollector.get())
99  {
100  MA::DataCollector.reset(nullptr);
101  }
102  if (MA::ClassifierModels.get())
103  {
104  MA::ClassifierModels.reset(nullptr);
105  }
106 }
107 
108 
109 void MABehaviorManager::SetVerbose(bool new_state)
110 {
111  Verbose = new_state;
112 }
113 
114 
116 {
117  // Clean behavior state events
119  // Let's create the behaviors here so we can make sure the initialization is done
120  // on the devices/controllers side.
122  {
124  }
125  MA::BehaviorList ProposedBehaviors;
126 
127  // Merge the new behaviors to the global list
128  if (Verbose)
129  {
130  MC_LOG("Merge the new behaviors to the global list");
131  }
133 
134  // Calculate and circulate the activations
135  if (Verbose)
136  {
137  MC_LOG("Calculate and circulate the activations");
138  }
140 
141  // Create the list of the proposed behavior list
142  if (Verbose)
143  {
144  MC_LOG("Create the list of the proposed behavior list");
145  }
146  const MA::BehaviorList& Behaviors = MABehavior::GetBehaviors();
147 
148  for (auto& behavior : Behaviors)
149  {
150  // The behavior has not been active before and it has the highest activation
151  if (behavior->GetState() != MABehavior::Failed &&
152  behavior->GetState() != MABehavior::Finished &&
153  behavior->GetActivationLevel() == 100)
154  {
155  ProposedBehaviors.push_back(behavior);
156  }
157  }
158 
159  // Execute the final behaviors
160  if (Verbose)
161  {
162  MC_LOG("Execute the final behaviors");
163  }
164  for (auto& behavior : ProposedBehaviors)
165  {
166  // Handle the case when a behavior is deleted during the activation of an other behavior
167  if (!MABehavior::Exists(behavior.get()))
168  continue;
169 
170  // The behavior has not been active before
171  if (behavior->GetState() != MABehavior::Activated)
172  ActiveBehaviors.push_back(behavior);
173 
174  behavior->SetState(MABehavior::Activated);
175  }
176 
177  // Remove the dirty behaviors (self-destroy)
178  if (Verbose)
179  {
180  MC_LOG("Remove the finished/failed behaviors (self-destroy)");
181  }
183 
184  // Remove the finished and failed behaviors
185  if (Verbose)
186  {
187  MC_LOG("Remove the finished or deleted behaviors");
188  }
189  for (auto iter = ActiveBehaviors.begin(); iter != ActiveBehaviors.end();)
190  {
191  if ((*iter)->GetState() != MABehavior::Activated)
192  {
193  iter = ActiveBehaviors.erase(iter);
194  // This safety check is required otherwise crash
195  if (iter == ActiveBehaviors.end())
196  {
197  break;
198  }
199  continue;
200  }
201  ++iter;
202  }
203  // Remove dirty activated behaviors
204  for (auto iter = ActiveBehaviors.begin(); iter != ActiveBehaviors.end();)
205  {
206  if (!MABehavior::Exists(iter->get()))
207  {
208  iter = ActiveBehaviors.erase(iter);
209  // This safety check is required otherwise crash
210  if (iter == ActiveBehaviors.end())
211  {
212  break;
213  }
214  continue;
215  }
216  ++iter;
217  }
218  // Update the data collector
219  MA::DataCollector->UpdateJobs();
220 }
221 
222 
224 {
226 }
227 
228 
230 {
232 }
233 
234 
236 {
238  if (MA::Microphone.get())
239  MA::Microphone->ResetListening();
240 }
241 
242 
244 {
245 #if !defined(__AIBO_BUILD__)
246  return MCGetDataFile("skits.db").toStdString();
247 #else
248  return "";
249 #endif
250 }
251 
252 
254 {
255 #if !defined(__AIBO_BUILD__)
256  return MCGetDataFile("sounds.db").toStdString();
257 #else
258  return "";
259 #endif
260 }
261 
262 
264 {
265  // Prevent to create the behaviors twice or more
267  return;
268 
269  // Do initialization steps
270  SetRandomSeed();
271  if (!MA::SkitDatabase.get())
272  {
273  MA::SkitDatabase.reset(MASkitDatabase::LoadFromFile(GetSkitDatabaseFileName()));
274  MA::SkitDatabase->CreateMirroredSkits();
275  }
276  if (!MA::SoundDatabase.get())
277  {
278  MA::SoundDatabase.reset(MASoundDatabase::LoadFromFile(GetSoundDatabaseFileName()));
279  }
280  // Create the default behaviors
281  MACreateBehavior<MABatteryStatus>(nullptr);
282  MACreateBehavior<MADataUploadStatus>(nullptr);
283  // TODO: We don't need writable memory stick yet...
284 // MACreateBehavior<MANoWritableStorage>(NULL);
285  MACreateBehavior<MAStartUp>(nullptr);
286  MACreateBehavior<MABodyAngry>(nullptr);
287  MACreateBehavior<MABodyHappy>(nullptr);
288  MACreateBehavior<MABodyPoked>(nullptr);
289  MACreateBehavior<MABodyAwaking>(nullptr);
290  MACreateBehavior<MABodySleeping>(nullptr);
291  MACreateBehavior<MABodyStroked>(nullptr);
292  MACreateBehavior<MAEyePupil>(nullptr);
293  MACreateBehavior<MAHeadLookAroundMaster>(nullptr);
294  MACreateBehavior<MAHeadTurnMaster>(nullptr);
295  MACreateBehavior<MASpeakerVolume>(nullptr);
296  MACreateBehavior<MASwitchSoundProfile>(nullptr);
297  MACreateBehavior<MASwitchVolumeControl>(nullptr);
298  MACreateBehavior<MAMouthSpeakingMaster>(nullptr);
299  MACreateBehavior<MABodyStateMaster>(nullptr);
300  MACreateBehavior<MASkitterPlaybackMaster>(nullptr);
301  MACreateBehavior<MAHeavyCalculations>(nullptr);
302  MACreateBehavior<MAClientConnected>(nullptr);
303  MACreateBehavior<MANumberGameMaster>(nullptr);
304  MACreateBehavior<MASoundEventMaster>(nullptr);
305  MACreateBehavior<MAChangeEyePupil>(nullptr);
306 }
void SetVerbose(bool new_state)
Set the verbosity level.
static void GarbageCollection()
Destroy the dirty behaviors.
Definition: MABehavior.cpp:296
static void ResumeSystem()
Resume the behavior system.
static bool Exists(const std::string &type_name, bool can_be_dying=false)
Check if a behavior exists.
Definition: MABehavior.cpp:175
Data collector.
bool Verbose
Whether the behavior manager is verbose.
virtual std::string GetSkitDatabaseFileName()
Get the skit database file name.
static void MergeNewBehaviors()
Merge all new behaviors to the existing behaviors.
Definition: MABehavior.cpp:363
static MASoundDatabase * LoadFromFile(const std::string &file_name)
Load sound database from file.
Classifier models class.
static const MA::BehaviorList & GetBehaviors()
Get all existing behaviors.
Definition: MABehavior.cpp:111
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
static void HibernateSystem()
Hibernate the behavior system.
static void CalculateActivations()
Calculate the current self-activation levels and send them out to the connected behaviors.
Definition: MABehavior.cpp:274
static void ResumeSystemTime()
Hibernate the system time.
Definition: MCTimer.cpp:146
QString MCGetDataFile(const QString &file_name)
Search a data file.
Definition: MCDefs.cpp:425
static void Cleanup()
Destroy all behaviors.
Definition: MABehavior.cpp:342
static void ClearBehaviorStateEvents()
Get the current behavior state events.
Definition: MABehavior.cpp:139
virtual std::string GetSoundDatabaseFileName()
Get the sound database file name.
virtual void SetRandomSeed()
Set random seed in a platform specific way.
static void SetNewSeed(int seed=(int) time(nullptr))
Set a new global random seed based on the system time.
Definition: MCDefs.cpp:72
static MASkitDatabase * LoadFromFile(const std::string &file_name)
Load skit database from file.
MA::BehaviorList ActiveBehaviors
Active behavior list.
static bool IsMergeNeeded()
Check if new behavior merge is needed.
Definition: MABehavior.cpp:445
static void HibernateSystemTime()
Hibernate the system time.
Definition: MCTimer.cpp:133
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...
virtual void UpdateBehaviors()
Update the behavior states in a cycle.
#define MC_LOG(...)
Debug macro.
Definition: MCLog.hpp:41
virtual void CreateDefaultBehaviors()
Create the default behaviors.