Main Page · Modules · All Classes · Class Hierarchy
MAMouthController.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 "MAMouthController.hpp"
23 
24 #include "core/MADevice.hpp"
25 #include "core/MARandomness.hpp"
26 #include "types/skits/MAMotionSkit.hpp"
27 #include "types/MAHead.hpp"
28 #include "types/MARobotState.hpp"
29 
30 #include <MCLog.hpp>
31 
32 namespace MA
33 {
35 }
36 
38 {
39  if (MA::Mouth.get())
40  {
41  MC_WARNING("The global mouth controller is overridden.");
42  MA::Mouth.release();
43  }
44  MA::Mouth.reset(this);
45  MA_BIND_TRANSITION(MAMouthController, CloseMouth, IsMouthClosed);
46  MA_BIND_TRANSITION_ACTION(MAMouthController, Speaking);
47  MA_BIND_TRANSITION_ACTION(MAMouthController, Burp);
48 }
49 
50 
52 {
53  if (MA::Mouth.get() == this)
54  MA::Mouth.release();
55 }
56 
57 
59 {
60  state.Head->Mouth = (int)Mouth->GetSensorValue();
61  state.Head->MouthForce = (int)Mouth->GetForce();
62  state.Head->MouthMoving = Mouth->HasGenerator();
63  state.Head->MouthClosed = IsMouthClosed();
64 }
65 
66 
67 MA::DeviceList MAMouthController::GetMotors() const
68 {
69  MA::DeviceList Motors;
70 
71  Motors.push_back(Mouth.get());
72  return Motors;
73 }
74 
75 
76 bool MAMouthController::IsMovingMouth() const
77 {
78  return Mouth->HasGenerator();
79 }
80 
81 
83 MA::DeviceGeneratorsMap MAMouthController::CloseMouth()
84 {
86  MAGeneratorContainer* Container = nullptr;
87 
88  Container = new MAGeneratorContainer(*CreateGenerator(MAMouthOpened(0), 500, Function));
89  return ApplyGenerators(*Container, true);
90 }
91 
92 
93 bool MAMouthController::IsMouthClosed() const
94 {
95  return (int)MouthOpened.Value < 10;
96 }
97 
98 
99 MA::DeviceGeneratorsMap MAMouthController::Speaking()
100 {
101  MAGeneratorContainer* Container = nullptr;
102 
103  if ((int)MouthOpened.Value < 25 || (int)MouthOpened.Value > 35)
104  {
105  MA_RANDOM_POINT_1(MouthOpenedValue, 25, 35);
106 
107  Container = new MAGeneratorContainer(*CreateGenerator(MAMouthOpened(MouthOpenedValue), 400,
109  }
110  MA_RANDOM_POINT_N(MouthOpenedValues, 10, 0, 20);
111  MA_RANDOM_POINT_N(MouthOpenedDurations, 10, 0, 100);
112 
113  for (int i = 0; i < 5; ++i)
114  {
116  MAGeneratorBase* Generator = nullptr;
117 
118  Generator = CreateGenerator(MAMouthOpened(15+MouthOpenedValues[i]), 60+MouthOpenedDurations[i],
119  Function);
120  if (!Container)
121  {
122  Container = new MAGeneratorContainer(*Generator);
123  } else {
124  Container->AddGenerator(*Generator);
125  }
126  Generator = CreateGenerator(MAMouthOpened(15+20-MouthOpenedValues[i]), 60+100-MouthOpenedDurations[i],
127  Function);
128  Container->AddGenerator(*Generator);
129  }
130  return ApplyGenerators(*Container, true);
131 }
132 
133 
134 MA::DeviceGeneratorsMap MAMouthController::Burp()
135 {
136  MAGeneratorContainer* Container = nullptr;
137  MAGeneratorBase* Generator = nullptr;
138 
139  Generator = CreateGenerator(MAMouthOpened(70), 400, MAGeneratorBase::GetRandomFunction());
140  Container = new MAGeneratorContainer(*Generator);
141  Generator = CreateGenerator(MAMouthOpened(60), 100, MAGeneratorBase::GetRandomFunction());
142  Container->AddGenerator(*Generator);
143  Generator = CreateGenerator(MAMouthOpened(70), 100, MAGeneratorBase::GetRandomFunction());
144  Container->AddGenerator(*Generator);
145  Generator = CreateGenerator(MAMouthOpened(0), 400, MAGeneratorBase::GetRandomFunction());
146  Container->AddGenerator(*Generator);
147  return ApplyGenerators(*Container, true);
148 }
150 
151 
152 void MAMouthController::Stop()
153 {
154  Mouth->ClearGenerators();
155 }
156 
157 
158 bool MAMouthController::IsPowerOn() const
159 {
160  return Mouth->IsPowerOn();
161 }
162 
163 
164 void MAMouthController::SetPower(bool new_state)
165 {
166  // Set the appropriate power state
167  if (Mouth->IsPowerOn() != new_state)
168  {
169  Mouth->SetPower(new_state);
170  // Clear the generators when switching off the joints
171  if (!new_state)
172  Stop();
173  }
174 }
175 
176 
177 void MAMouthController::RegisterDeviceUpdates()
178 {
179  MA_SIGNAL_CONNECT(Mouth->DeviceValueChangeSignal, MAMouthController::NotifyDeviceUpdate);
180 }
181 
182 
183 void MAMouthController::NotifyDeviceUpdate(MADevice& device)
184 {
185  if (!device.HasSensorValue())
186  return;
187 
188  // Recalculate the mouth state
189  MouthOpened.FromJointDegree((int)Mouth->GetSensorValue());
190 }
191 
192 
193 MA::DeviceGeneratorsMap MAMouthController::GetSkitTransitionGenerators(MA::SkitBaseSPtr skit)
194 {
195  MAMotionSkit* MotionSkit = dynamic_cast<MAMotionSkit*>(skit.get());
196 
197  if (!MotionSkit)
198  return MA::DeviceGeneratorsMap();
199 
200  MA::DeviceGeneratorsMap DeviceGenerators;
201  MAGeneratorContainer* Container = nullptr;
202 
203  SetPower(true);
204  Container = MotionSkit->GetGeneratorContainer(MA::MouthJoint);
205  Mouth->ClearGenerators();
206  Mouth->AddGeneratorContainer(*Container);
207  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Mouth.get(), Container);
208  return DeviceGenerators;
209 }
210 
211 
212 MAGeneratorBase* MAMouthController::CreateGenerator(const MAMouthOpened& feature, int msec,
214 {
215  MAGeneratorBase* Generator = nullptr;
216 
217  Generator = new MASimpleGenerator((float)feature.ToJointDegree(), msec);
218  Generator->SetTransferFunction(function);
219  return Generator;
220 }
221 
222 
223 MA::DeviceGeneratorsMap MAMouthController::ApplyGenerators(MAGeneratorContainer& container, bool clear)
224 {
225  MA::DeviceGeneratorsMap DeviceGenerators;
226 
227  SetPower(true);
228  if (clear)
229  {
230  Mouth->ClearGenerators();
231  }
232  Mouth->AddGeneratorContainer(container);
233  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Mouth.get(), &container);
234  return DeviceGenerators;
235 }
MANum< float > Value
Current value.
Definition: MABodyTypes.hpp:86
#define MA_RANDOM_POINT_1(_variable_name, _min, _max)
Set a random point with one value.
void AddGenerator(MAGeneratorBase &generator, bool in_front=false)
Add a new generator after the last internal generator.
void SetTransferFunction(FunctionType function)
Set the transfer function.
MAMouthController()
Class constructor.
boost::shared_ptr< MADevice > Mouth
Mouth.
virtual ~MAMouthController()
Class destructor.
virtual MA::DeviceGeneratorsMap GetSkitTransitionGenerators(MA::SkitBaseSPtr skit) override
Get skit transition generators.
virtual void FromJointDegree(int degree) override
Compute from a joint degree value.
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
Base class for the controllers.
Device class.
Definition: MADevice.hpp:57
Simple generator class.
static FunctionType GetRandomFunction()
Get a random generator function type.
virtual int ToJointDegree() const override
Transform to a joint degree value.
Mouth controller class.
virtual void UpdateRobotState(MARobotState &state) override
Update the robot state.
Generator container class.
MAGeneratorContainer * GetGeneratorContainer(MA::Leg::LegTypes leg, MA::LegJointsType joint) const
Get generator container for a leg joint.
virtual MA::DeviceList GetMotors() const override
Get the list of the motors.
Motion sequence (motion skit) class.
Base class for generators.
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...
The opened-closed position of the mouth.
Robot state.
#define MA_RANDOM_POINT_N(_variable_name, _count, _min, _max)
Set a random point with a value list.
boost::scoped_ptr< MAHead > Head
Head.