Main Page · Modules · All Classes · Class Hierarchy
MAHeadController.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 "MAHeadController.hpp"
23 
24 #include "core/MACameraDevice.hpp"
25 #include "core/MADevice.hpp"
26 #include "core/MAMicrophoneDevice.hpp"
27 #include "core/MARandomness.hpp"
28 #include "types/skits/MAMotionSkit.hpp"
29 #include "types/MAAudio.hpp"
30 #include "types/MAHead.hpp"
31 #include "types/MARobotState.hpp"
32 
33 #include <MCContainers.hpp>
34 #include <MCLog.hpp>
35 
36 namespace MA
37 {
39 }
40 
41 MAHeadTransitionGenerators::MAHeadTransitionGenerators() : NeckTilt1(nullptr), NeckTilt2(nullptr),
42  NeckPan(nullptr)
43 {
44 }
45 
46 
47 void MAHeadTransitionGenerators::AddGeneratorToNeckTilt1(MAGeneratorBase& generator)
48 {
49  if (!NeckTilt1)
50  {
51  NeckTilt1 = new MAGeneratorContainer(generator);
52  } else {
53  NeckTilt1->AddGenerator(generator);
54  }
55 }
56 
57 
58 void MAHeadTransitionGenerators::AddGeneratorToNeckTilt2(MAGeneratorBase& generator)
59 {
60  if (!NeckTilt2)
61  {
62  NeckTilt2 = new MAGeneratorContainer(generator);
63  } else {
64  NeckTilt2->AddGenerator(generator);
65  }
66 }
67 
68 
69 void MAHeadTransitionGenerators::AddGeneratorToNeckPan(MAGeneratorBase& generator)
70 {
71  if (!NeckPan)
72  {
73  NeckPan = new MAGeneratorContainer(generator);
74  } else {
75  NeckPan->AddGenerator(generator);
76  }
77 }
78 
79 
80 void MAHeadTransitionGenerators::AddDelayToNeckJoints(int duration)
81 {
82  AddGeneratorToNeckPan(*new MADelayGenerator(duration));
83  AddGeneratorToNeckTilt1(*new MADelayGenerator(duration));
84  AddGeneratorToNeckTilt2(*new MADelayGenerator(duration));
85 }
86 
87 
88 void MAHeadTransitionGenerators::Normalize()
89 {
90  if (!NeckTilt1 && !NeckTilt2 && !NeckPan)
91  {
92  return;
93  }
94  if ((NeckTilt1 && !NeckTilt1->IsFinite()) ||
95  (NeckTilt2 && !NeckTilt2->IsFinite()) ||
96  (NeckPan && !NeckPan->IsFinite()))
97  {
98  return;
99  }
100 
101  int Duration = 0;
102 
103  if (NeckTilt1 && NeckTilt1->IsFinite())
104  Duration = Duration > NeckTilt1->GetDuration() ? Duration : NeckTilt1->GetDuration();
105  if (NeckTilt2 && NeckTilt2->IsFinite())
106  Duration = Duration > NeckTilt2->GetDuration() ? Duration : NeckTilt2->GetDuration();
107  if (NeckPan && NeckPan->IsFinite())
108  Duration = Duration > NeckPan->GetDuration() ? Duration : NeckPan->GetDuration();
109 
110  bool Ret = true;
111 
112  Ret = Ret && (!NeckTilt1 || NeckTilt1->GetDuration() == Duration);
113  Ret = Ret && (!NeckTilt2 || NeckTilt2->GetDuration() == Duration);
114  Ret = Ret && (!NeckPan || NeckPan->GetDuration() == Duration);
115 
116  if (Ret)
117  {
118  return;
119  }
120 
121  if (NeckTilt1 && NeckTilt1->IsFinite())
122  {
123  AddGeneratorToNeckTilt1(*new MADelayGenerator(Duration-NeckTilt1->GetDuration()));
124  }
125  if (NeckTilt2 && NeckTilt2->IsFinite())
126  {
127  AddGeneratorToNeckTilt2(*new MADelayGenerator(Duration-NeckTilt2->GetDuration()));
128  }
129  if (NeckPan && NeckPan->IsFinite())
130  {
131  AddGeneratorToNeckPan(*new MADelayGenerator(Duration-NeckPan->GetDuration()));
132  }
133 }
134 
135 
137  RubbingCenterForeBack(MCFloatInfinity()), RubbingCenterLeftRight(MCFloatInfinity())
138 {
139  if (MA::Head.get())
140  {
141  MC_WARNING("The global head controller is overridden.");
142  MA::Head.release();
143  }
144  MA::Head.reset(this);
145 
146  MA_BIND_TRANSITION(MAHeadController, TurnDownAndAhead, IsTurnedDownAndAhead);
147  MA_BIND_TRANSITION(MAHeadController, TurnUp, IsTurnedUp);
148  MA_BIND_TRANSITION(MAHeadController, ToNormalAhead, IsNormalAhead);
149  MA_BIND_TRANSITION_ACTION(MAHeadController, GoRubbing);
150  MA_BIND_TRANSITION_ACTION(MAHeadController, RubToLeft);
151  MA_BIND_TRANSITION_ACTION(MAHeadController, RubToRight);
152  MA_BIND_TRANSITION_ACTION(MAHeadController, FinishRubbing);
153  MA_BIND_TRANSITION_ACTION(MAHeadController, DoCircle);
154  MA_BIND_TRANSITION_ACTION(MAHeadController, HappyMoveToUp);
155  MA_BIND_TRANSITION_ACTION(MAHeadController, LookAroundLying);
156  MA_BIND_TRANSITION_ACTION(MAHeadController, LookAroundSitting);
157  MA_BIND_TRANSITION_ACTION(MAHeadController, TurnLeftLying);
158  MA_BIND_TRANSITION_ACTION(MAHeadController, TurnRightLying);
159  MA_BIND_TRANSITION_ACTION(MAHeadController, TurnLeftSitting);
160  MA_BIND_TRANSITION_ACTION(MAHeadController, TurnRightSitting);
161 }
162 
163 
165 {
166  if (MA::Head.get() == this)
167  MA::Head.release();
168 }
169 
170 
172 {
173  state.Head->Pan = (int)NeckPan->GetSensorValue();
174  state.Head->PanForce = (int)NeckPan->GetForce();
175  state.Head->Tilt1 = (int)NeckTilt1->GetSensorValue();
176  state.Head->Tilt1Force = (int)NeckTilt1->GetForce();
177  state.Head->Tilt2 = (int)NeckTilt2->GetSensorValue();
178  state.Head->Tilt2Force = (int)NeckTilt2->GetForce();
179  state.Head->CameraBrightness = Camera->GetBrightness();
180  state.Head->EyePupilSize = Camera->GetPupilSize();
181  state.Head->LeftRight = (int)(float)LeftRightTurned.Value;
182  state.Head->UpDown = (int)HeadPosition.UpDownValue;
183  state.Head->ForeBack = (int)HeadPosition.ForeBackValue;
184  state.Head->ChinButton = (int)ChinButton->GetSensorValue();
185  state.Head->CrownButton = (int)CrownButton->GetSensorValue();
186  state.Head->Moving = NeckPan->HasGenerator() || NeckTilt1->HasGenerator() || NeckTilt2->HasGenerator();
187  state.Head->InMotion = NeckPan->IsInMotion() || NeckTilt1->IsInMotion() || NeckTilt2->IsInMotion();
188  state.Audio->LeftMicrophonePower = (int)Microphone->GetLeftChannelPower();
189  state.Audio->RightMicrophonePower = (int)Microphone->GetRightChannelPower();
190  state.Audio->BackgroundSoundPower = (int)Microphone->GetBackgroundSoundPower();
191  const MC::IntList& Votes = Microphone->GetSoundEventVotes();
192 
193  for (int i = 1; i < (int)Votes.size() && i < MA::MaxSoundEvents+1; ++i)
194  {
195  state.Audio->SoundEventVotes[i] = Votes[i];
196  }
197  state.Audio->CurrentSoundEvent = Microphone->GetDetectedSoundEvent();
198 }
199 
200 
201 MA::DeviceList MAHeadController::GetMotors() const
202 {
203  MA::DeviceList Motors;
204 
205  Motors.push_back(NeckTilt1.get());
206  Motors.push_back(NeckTilt2.get());
207  Motors.push_back(NeckPan.get());
208  return Motors;
209 }
210 
211 
212 MADevice* MAHeadController::GetMotor(const MA::HeadJointsType joint) const
213 {
214  if (joint == MA::NeckPan)
215  {
216  return NeckPan.get();
217  }
218  if (joint == MA::NeckTilt1)
219  {
220  return NeckTilt1.get();
221  }
222  return NeckTilt2.get();
223 }
224 
225 
226 MA::HeadJointsType MAHeadController::GetMotorType(const MADevice& motor) const
227 {
228  if (&motor == NeckPan.get())
229  {
230  return MA::NeckPan;
231  }
232  if (&motor == NeckTilt1.get())
233  {
234  return MA::NeckTilt1;
235  }
236  return MA::NeckTilt2;
237 }
238 
239 
240 void MAHeadController::SetPower(bool new_state)
241 {
242  // Clear the generators when switching off the joints
243  if (!new_state)
244  Stop();
245  SetPower(MA::NeckPan, new_state);
246  SetPower(MA::NeckTilt1, new_state);
247  SetPower(MA::NeckTilt2, new_state);
248 }
249 
250 
251 bool MAHeadController::IsPowerOn() const
252 {
253  return IsPowerOn(MA::NeckPan) && IsPowerOn(MA::NeckTilt1) && IsPowerOn(MA::NeckTilt2);
254 }
255 
256 
257 bool MAHeadController::IsMovingNeck() const
258 {
259  return NeckPan->HasGenerator() || NeckTilt1->HasGenerator() || NeckTilt2->HasGenerator();
260 }
261 
262 
263 bool MAHeadController::IsTurnedDown() const
264 {
265  bool Ret = true;
266 
267  Ret = Ret && (int)HeadPosition.ForeBackValue > 60;
268  Ret = Ret && (int)HeadPosition.UpDownValue < -20;
269  return Ret;
270 }
271 
272 
273 bool MAHeadController::IsTurnedAhead() const
274 {
275  bool Ret = true;
276 
277  Ret = Ret && MCAbs((int)LeftRightTurned.Value) < 30;
278  return Ret;
279 }
280 
281 
282 bool MAHeadController::IsUp() const
283 {
284  bool Ret = true;
285 
286  Ret = Ret && (int)HeadPosition.UpDownValue >= -20;
287  return Ret;
288 }
289 
290 
292 MA::DeviceGeneratorsMap MAHeadController::TurnDownAndAhead()
293 {
294  MALeftRightTurned LeftRight;
295  MAHeadPosition Position;
296  MAHeadTransitionGenerators Generators;
297 
298  LeftRight.Value = 0.0;
299  Position.ForeBackValue = 100.0;
300  Position.UpDownValue = -100.0;
301  CreateGenerators(Generators, LeftRight, 1500);
302  CreateGenerators(Generators, Position, 1500);
303  return ApplyGenerators(Generators, true);
304 }
305 
306 
307 bool MAHeadController::IsTurnedDownAndAhead() const
308 {
309  return IsTurnedDown() && IsTurnedAhead();
310 }
311 
312 
313 MA::DeviceGeneratorsMap MAHeadController::TurnUp()
314 {
315  MALeftRightTurned LeftRight;
316  MAHeadPosition Position;
317  MAHeadTransitionGenerators Generators;
318 
319  LeftRight.Value = 0.0;
320  Position.ForeBackValue = -100.0;
321  Position.UpDownValue = 10.0;
322  CreateGenerators(Generators, LeftRight, 1500);
323  CreateGenerators(Generators, Position, 1500);
324  return ApplyGenerators(Generators, true);
325 }
326 
327 
328 bool MAHeadController::IsTurnedUp() const
329 {
330  bool Ret = true;
331 
332  Ret = Ret && MCAbs((int)LeftRightTurned.Value) < 30;
333  Ret = Ret && (int)HeadPosition.ForeBackValue < 85;
334  Ret = Ret && MCAbs((int)HeadPosition.UpDownValue) < 25;
335  return Ret;
336 }
337 
338 
339 MA::DeviceGeneratorsMap MAHeadController::ToNormalAhead()
340 {
341  MALeftRightTurned LeftRight;
342  MAHeadPosition Position;
343  MAHeadTransitionGenerators Generators;
344 
345  LeftRight.Value = 0.0;
346  Position.ForeBackValue = 31.0;
347  Position.UpDownValue = 0.0;
348  CreateGenerators(Generators, LeftRight, 1500);
349  CreateGenerators(Generators, Position, 1500);
350  // The motors are not enough fast to finish the movements.
351  Generators.AddDelayToNeckJoints();
352  return ApplyGenerators(Generators, true);
353 }
354 
355 
356 bool MAHeadController::IsNormalAhead() const
357 {
358  bool Ret = true;
359 
360  Ret = Ret && MCAbs((int)LeftRightTurned.Value) < 10;
361  Ret = Ret && MCRangeCheck((int)HeadPosition.ForeBackValue, 25, 50);
362  Ret = Ret && MCRangeCheck((int)HeadPosition.UpDownValue, -20, 5);
363  return Ret;
364 }
365 
366 
367 MA::DeviceGeneratorsMap MAHeadController::GoRubbing()
368 {
369  MAHeadPosition NewPosition = HeadPosition;
370  MAHeadTransitionGenerators Generators;
371 
372  // We must force all joints now
373  SetPower(true);
374  // Set the center data of the rubbing
375  RubbingCenterForeBack = (float)HeadPosition.ForeBackValue+40.0;
376  RubbingCenterLeftRight = (float)LeftRightTurned.Value;
377 
378  NewPosition.ForeBackValue += 40;
379  CreateGenerators(Generators, NewPosition, 700);
380  return ApplyGenerators(Generators, false);
381 }
382 
383 
384 MA::DeviceGeneratorsMap MAHeadController::RubToLeft()
385 {
386  MAHeadPosition NewPosition;
387  MALeftRightTurned NewLeftRight;
388  MAHeadTransitionGenerators Generators;
389  MA_RANDOM_POINT_1(Speed1, 1, 10);
390  MA_RANDOM_POINT_1(Speed2, 1, 10);
391  MA_RANDOM_POINT_1(Speed3, 1, 10);
392  MA_RANDOM_POINT_1(Speed4, 1, 10);
393 
394  NewPosition.ForeBackValue = RubbingCenterForeBack;
395  NewPosition.ForeBackValue -= 25;
396  CreateGenerators(Generators, NewPosition, 400);
397  Generators.Normalize();
398  NewPosition.ForeBackValue += 25;
399  CreateGenerators(Generators, NewPosition, 200+Speed1*10);
400  NewPosition.ForeBackValue -= 25;
401  CreateGenerators(Generators, NewPosition, 300+Speed3*10);
402  NewPosition.ForeBackValue += 25;
403  CreateGenerators(Generators, NewPosition, 200+Speed2*10);
404  NewPosition.ForeBackValue -= 25;
405  CreateGenerators(Generators, NewPosition, 300+Speed4*10);
406  NewPosition.ForeBackValue += 25;
407  CreateGenerators(Generators, NewPosition, 400);
408 
409  NewLeftRight.Value = RubbingCenterLeftRight;
410  NewLeftRight.Value -= 15;
411  CreateGenerators(Generators, NewLeftRight, 200+Speed1*10);
412  NewLeftRight.Value += 15;
413  CreateGenerators(Generators, NewLeftRight, 300+Speed3*10);
414  NewLeftRight.Value -= 15;
415  CreateGenerators(Generators, NewLeftRight, 200+Speed1*10);
416  NewLeftRight.Value += 15;
417  CreateGenerators(Generators, NewLeftRight, 300+Speed4*10);
418  return ApplyGenerators(Generators, false);
419 }
420 
421 
422 MA::DeviceGeneratorsMap MAHeadController::RubToRight()
423 {
424  MAHeadPosition NewPosition;
425  MALeftRightTurned NewLeftRight;
426  MAHeadTransitionGenerators Generators;
427  MA_RANDOM_POINT_1(Speed1, 1, 10);
428  MA_RANDOM_POINT_1(Speed2, 1, 10);
429  MA_RANDOM_POINT_1(Speed3, 1, 10);
430  MA_RANDOM_POINT_1(Speed4, 1, 10);
431 
432  NewPosition.ForeBackValue = RubbingCenterForeBack;
433  NewPosition.ForeBackValue -= 25;
434  CreateGenerators(Generators, NewPosition, 200+Speed1*10);
435  NewPosition.ForeBackValue += 25;
436  CreateGenerators(Generators, NewPosition, 300+Speed3*10);
437  NewPosition.ForeBackValue -= 25;
438  CreateGenerators(Generators, NewPosition, 200+Speed2*10);
439  NewPosition.ForeBackValue += 25;
440  CreateGenerators(Generators, NewPosition, 300+Speed4*10);
441 
442  NewLeftRight.Value = RubbingCenterLeftRight;
443  NewLeftRight.Value += 15;
444  CreateGenerators(Generators, NewLeftRight, 200+Speed1*10);
445  NewLeftRight.Value -= 15;
446  CreateGenerators(Generators, NewLeftRight, 300+Speed3*10);
447  NewLeftRight.Value += 15;
448  CreateGenerators(Generators, NewLeftRight, 200+Speed1*10);
449  NewLeftRight.Value -= 15;
450  CreateGenerators(Generators, NewLeftRight, 300+Speed4*10);
451  return ApplyGenerators(Generators, false);
452 }
453 
454 
455 MA::DeviceGeneratorsMap MAHeadController::FinishRubbing()
456 {
457  MAHeadPosition NewPosition;
458  MALeftRightTurned NewLeftRight;
459  MAHeadTransitionGenerators Generators;
460 
461  NewPosition.ForeBackValue = RubbingCenterForeBack-40.0;
462  CreateGenerators(Generators, NewPosition, 700);
463 
464  NewLeftRight.Value = RubbingCenterLeftRight;
465  CreateGenerators(Generators, NewLeftRight, 700);
466 
467  // The motors are not enough fast to finish the movements.
468  Generators.AddDelayToNeckJoints();
469  // Clear the rubbing center data
471  RubbingCenterLeftRight = MCFloatInfinity(); // -V656 (PVS Studio suppression)
472  return ApplyGenerators(Generators, false);
473 }
474 
475 
476 MA::DeviceGeneratorsMap MAHeadController::DoCircle()
477 {
478  MAHeadPosition NewPosition = HeadPosition;
479  MALeftRightTurned NewLeftRight = LeftRightTurned;
480  MAHeadTransitionGenerators Generators;
481  MA_RANDOM_POINT_1(RadiusXDirection, 0, 1);
482  MA_RANDOM_POINT_1(RadiusX, 5, 15);
483  MA_RANDOM_POINT_1(CircleRadiusY, 10, 20);
484  int CircleRadiusX = RadiusXDirection == 1 ? RadiusX : -RadiusX;
485 
486  NewPosition.UpDownValue += CircleRadiusY;
487  CreateGenerators(Generators, NewPosition, 200, MAGeneratorBase::AcceleratingSines);
488  NewPosition.UpDownValue += CircleRadiusY;
489  CreateGenerators(Generators, NewPosition, 200, MAGeneratorBase::DeceleratingSines);
490  NewPosition.UpDownValue -= CircleRadiusY;
491  CreateGenerators(Generators, NewPosition, 200, MAGeneratorBase::AcceleratingSines);
492  NewPosition.UpDownValue -= CircleRadiusY;
493  CreateGenerators(Generators, NewPosition, 200, MAGeneratorBase::DeceleratingSines);
494 
495  NewLeftRight.Value -= CircleRadiusX;
496  CreateGenerators(Generators, NewLeftRight, 200, MAGeneratorBase::DeceleratingSines);
497  NewLeftRight.Value += CircleRadiusX;
498  CreateGenerators(Generators, NewLeftRight, 200, MAGeneratorBase::AcceleratingSines);
499  NewLeftRight.Value += CircleRadiusX;
500  CreateGenerators(Generators, NewLeftRight, 200, MAGeneratorBase::DeceleratingSines);
501  NewLeftRight.Value -= CircleRadiusX;
502  CreateGenerators(Generators, NewLeftRight, 200, MAGeneratorBase::AcceleratingSines);
503  return ApplyGenerators(Generators, true);
504 }
505 
506 
507 MA::DeviceGeneratorsMap MAHeadController::HappyMoveToUp()
508 {
509  MAHeadPosition NewPosition = HeadPosition;
510  MALeftRightTurned NewLeftRight = LeftRightTurned;
511  MAHeadTransitionGenerators Generators;
512  MA_RANDOM_POINT_1(RadiusXDirection, 0, 1);
513  MA_RANDOM_POINT_1(RadiusX, 4, 25);
514  MA_RANDOM_POINT_1(CircleRadiusY, 10, 30);
515  int CircleRadiusX = RadiusXDirection == 1 ? RadiusX : -RadiusX;
516 
517  NewPosition.UpDownValue += CircleRadiusY;
518  CreateGenerators(Generators, NewPosition, 400, MAGeneratorBase::AcceleratingSines);
519  NewPosition.UpDownValue -= CircleRadiusY;
520  CreateGenerators(Generators, NewPosition, 400, MAGeneratorBase::AcceleratingSines);
521 
522  NewLeftRight.Value -= CircleRadiusX;
523  CreateGenerators(Generators, NewLeftRight, 400, MAGeneratorBase::DeceleratingSines);
524  NewLeftRight.Value += CircleRadiusX;
525  CreateGenerators(Generators, NewLeftRight, 400, MAGeneratorBase::DeceleratingSines);
526  return ApplyGenerators(Generators, true);
527 }
528 
529 
530 std::string MAHeadController::DoHappyMovement()
531 {
532  std::string TransitionName;
533  MA_RANDOM_POINT_1(Movements, 1, 2);
534 
535  if (Movements == 1)
536  {
537  TransitionName = DoCircleStr;
538  }
539  if (Movements == 2)
540  {
541  TransitionName = HappyMoveToUpStr;
542  }
543  StartTransition(TransitionName);
544  return TransitionName;
545 }
546 
547 
548 MA::DeviceGeneratorsMap MAHeadController::LookAroundLying()
549 {
550  MAHeadTransitionGenerators Generators;
551  MA_RANDOM_POINT_1(Motions, 1, 5);
552  MA_RANDOM_POINT_N(Durations, Motions, 1500, 2500);
553  MA_RANDOM_POINT_N(DelayDurations, Motions, 10, 20000);
554  MA_RANDOM_POINT_N(LeftRightValues, Motions, -70, 70);
555  MA_RANDOM_POINT_N(ForeBackValues, Motions, -50, 50);
556  MA_RANDOM_POINT_N(UpDownValues, Motions, -20, 80);
557 
558  for (int i = 0; i < Motions; ++i)
559  {
560  MAHeadPosition Position;
561 
562  Generators.AddDelayToNeckJoints(DelayDurations[i]);
563  CreateGenerators(Generators, MALeftRightTurned(LeftRightValues[i]), Durations[i],
565  Position.ForeBackValue = (float)ForeBackValues[i];
566  Position.UpDownValue = (float)UpDownValues[i];
567  CreateGenerators(Generators, Position, Durations[i], MAGeneratorBase::GetRandomFunction());
568  }
569  return ApplyGenerators(Generators, true);
570 }
571 
572 
573 MA::DeviceGeneratorsMap MAHeadController::LookAroundSitting()
574 {
575  MAHeadTransitionGenerators Generators;
576  MA_RANDOM_POINT_1(Motions, 1, 5);
577  MA_RANDOM_POINT_N(Durations, Motions, 1500, 2500);
578  MA_RANDOM_POINT_N(DelayDurations, Motions, 10, 20000);
579  MA_RANDOM_POINT_N(LeftRightValues, Motions, -70, 70);
580  MA_RANDOM_POINT_N(ForeBackValues, Motions, -10, 30);
581  MA_RANDOM_POINT_N(UpDownValues, Motions, -40, 45);
582 
583  for (int i = 0; i < Motions; ++i)
584  {
585  MAHeadPosition Position;
586 
587  Generators.AddDelayToNeckJoints(DelayDurations[i]);
588  CreateGenerators(Generators, MALeftRightTurned(LeftRightValues[i]), Durations[i],
590  Position.ForeBackValue = (float)ForeBackValues[i];
591  Position.UpDownValue = (float)UpDownValues[i];
592  CreateGenerators(Generators, Position, Durations[i], MAGeneratorBase::GetRandomFunction());
593  }
594  return ApplyGenerators(Generators, true);
595 }
596 
597 
598 MA::DeviceGeneratorsMap MAHeadController::TurnLeftLying()
599 {
600  MAHeadTransitionGenerators Generators;
601  MALeftRightTurned LeftRight = LeftRightTurned;
602  MAHeadPosition Position = HeadPosition;
603 
604  LeftRight.Value = -95.0;
605  Position.UpDownValue = 40;
606  Position.ForeBackValue = 0;
607  CreateGenerators(Generators, LeftRight, 1800);
608  CreateGenerators(Generators, Position, 1800);
609  return ApplyGenerators(Generators, true);
610 }
611 
612 
613 MA::DeviceGeneratorsMap MAHeadController::TurnRightLying()
614 {
615  MAHeadTransitionGenerators Generators;
616  MALeftRightTurned LeftRight = LeftRightTurned;
617  MAHeadPosition Position = HeadPosition;
618 
619  LeftRight.Value = 95.0;
620  Position.UpDownValue = 40;
621  Position.ForeBackValue = 0;
622  CreateGenerators(Generators, LeftRight, 1800);
623  CreateGenerators(Generators, Position, 1800);
624  return ApplyGenerators(Generators, true);
625 }
626 
627 
628 MA::DeviceGeneratorsMap MAHeadController::TurnLeftSitting()
629 {
630  MAHeadTransitionGenerators Generators;
631  MALeftRightTurned LeftRight = LeftRightTurned;
632  MAHeadPosition Position = HeadPosition;
633 
634  LeftRight.Value = -95.0;
635  Position.UpDownValue = 20;
636  Position.ForeBackValue = 0;
637  CreateGenerators(Generators, LeftRight, 1800);
638  CreateGenerators(Generators, Position, 1800);
639  return ApplyGenerators(Generators, true);
640 }
641 
642 
643 MA::DeviceGeneratorsMap MAHeadController::TurnRightSitting()
644 {
645  MAHeadTransitionGenerators Generators;
646  MALeftRightTurned LeftRight = LeftRightTurned;
647  MAHeadPosition Position = HeadPosition;
648 
649  LeftRight.Value = 95.0;
650  Position.UpDownValue = 20;
651  Position.ForeBackValue = 0;
652  CreateGenerators(Generators, LeftRight, 1800);
653  CreateGenerators(Generators, Position, 1800);
654  return ApplyGenerators(Generators, true);
655 }
657 
658 
659 void MAHeadController::Stop()
660 {
661  Stop(MA::NeckPan);
662  Stop(MA::NeckTilt1);
663  Stop(MA::NeckTilt2);
664 }
665 
666 
667 void MAHeadController::PrintFeatures()
668 {
669  MC_LOG("Head: LeftRight: %1.2f ForeBack: %1.2f UpDown: %1.2f",
670  (float)LeftRightTurned.Value, (float)HeadPosition.ForeBackValue,
671  (float)HeadPosition.UpDownValue);
672 }
673 
674 
675 bool MAHeadController::IsPowerOn(MA::HeadJointsType joint) const
676 {
677  MADevice* Device = nullptr;
678 
679  if (joint == MA::NeckPan)
680  Device = NeckPan.get();
681  if (joint == MA::NeckTilt1)
682  Device = NeckTilt1.get();
683  if (joint == MA::NeckTilt2)
684  Device = NeckTilt2.get();
685 
686  if (unlikely(!Device))
687  {
688  MC_ERROR("The motor device has not been created!");
689  return false;
690  }
691  return Device->IsPowerOn();
692 }
693 
694 
695 void MAHeadController::SetPower(MA::HeadJointsType joint, bool new_state)
696 {
697  if (joint == MA::EarLeft || joint == MA::EarRight)
698  {
699  MC_WARNING("The ear motors do not have power on/off states.");
700  return;
701  }
702  MADevice* Device = nullptr;
703 
704  if (joint == MA::NeckPan)
705  Device = NeckPan.get();
706  if (joint == MA::NeckTilt1)
707  Device = NeckTilt1.get();
708  if (joint == MA::NeckTilt2)
709  Device = NeckTilt2.get();
710 
711  if (unlikely(!Device))
712  {
713  MC_ERROR("The motor device has not been created!");
714  return;
715  }
716  // Set the appropriate power state
717  if (Device->IsPowerOn() != new_state)
718  {
719  Device->SetPower(new_state);
720  }
721 }
722 
723 
724 void MAHeadController::RegisterDeviceUpdates()
725 {
726  MA_SIGNAL_CONNECT(NeckPan->DeviceValueChangeSignal, MAHeadController::NotifyDeviceUpdate);
727  MA_SIGNAL_CONNECT(NeckTilt1->DeviceValueChangeSignal, MAHeadController::NotifyDeviceUpdate);
728  MA_SIGNAL_CONNECT(NeckTilt2->DeviceValueChangeSignal, MAHeadController::NotifyDeviceUpdate);
729 }
730 
731 
732 void MAHeadController::NotifyDeviceUpdate(MADevice& device)
733 {
734  if (!device.HasSensorValue())
735  return;
736 
737  if (&device == NeckPan.get())
738  {
739  // Recalculate the left-right state
740  LeftRightTurned.FromJointDegree((int)device.GetSensorValue());
741  }
742  if (&device == NeckTilt1.get() || &device == NeckTilt2.get())
743  {
744  // Recalculate the for-back and up-down state
745  HeadPosition.FromJointDegrees((int)NeckTilt1->GetSensorValue(), (int)NeckTilt2->GetSensorValue());
746  }
747 }
748 
749 
750 void MAHeadController::Stop(MA::HeadJointsType joint)
751 {
752  MADevice* Device = nullptr;
753 
754  if (joint == MA::NeckPan)
755  Device = NeckPan.get();
756  if (joint == MA::NeckTilt1)
757  Device = NeckTilt1.get();
758  if (joint == MA::NeckTilt2)
759  Device = NeckTilt2.get();
760 
761  if (!Device)
762  {
763  MC_ERROR("The device has not been created!");
764  return;
765  }
766  Device->ClearGenerators();
767 }
768 
769 
770 void MAHeadController::CreateGenerators(MAHeadTransitionGenerators& generators, const MABodyPartFeature& feature,
771  int msec, MAGeneratorBase::FunctionType function)
772 {
773  MAGeneratorBase* Generator = nullptr;
774 
775  if (dynamic_cast<const MALeftRightTurned*>(&feature))
776  {
777  Generator = new MASimpleGenerator((float)feature.ToJointDegree(), msec);
778  Generator->SetTransferFunction(function);
779  generators.AddGeneratorToNeckPan(*Generator);
780  }
781  const MAHeadPosition* Position = dynamic_cast<const MAHeadPosition*>(&feature);
782 
783  if (Position)
784  {
785  Generator = new MASimpleGenerator((float)Position->ToNeckTilt1Degree(), msec);
786  Generator->SetTransferFunction(function);
787  generators.AddGeneratorToNeckTilt1(*Generator);
788  Generator = new MASimpleGenerator((float)Position->ToNeckTilt2Degree(), msec);
789  Generator->SetTransferFunction(function);
790  generators.AddGeneratorToNeckTilt2(*Generator);
791  }
792 }
793 
794 
795 MA::DeviceGeneratorsMap MAHeadController::GetSkitTransitionGenerators(MA::SkitBaseSPtr skit)
796 {
797  MAMotionSkit* MotionSkit = dynamic_cast<MAMotionSkit*>(skit.get());
798 
799  if (!MotionSkit)
800  return MA::DeviceGeneratorsMap();
801 
802  MA::DeviceGeneratorsMap DeviceGenerators;
803  MAGeneratorContainer* Container = nullptr;
804 
805  SetPower(true);
806  // Neck tilt1
807  NeckTilt1->ClearGenerators();
808  Container = MotionSkit->GetGeneratorContainer(MA::NeckTilt1);
809  NeckTilt1->AddGeneratorContainer(*Container);
810  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, NeckTilt1.get(), Container);
811  // Neck tilt2
812  NeckTilt2->ClearGenerators();
813  Container = MotionSkit->GetGeneratorContainer(MA::NeckTilt2);
814  NeckTilt2->AddGeneratorContainer(*Container);
815  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, NeckTilt2.get(), Container);
816  // Neck pan
817  NeckPan->ClearGenerators();
818  Container = MotionSkit->GetGeneratorContainer(MA::NeckPan);
819  NeckPan->AddGeneratorContainer(*Container);
820  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, NeckPan.get(), Container);
821  return DeviceGenerators;
822 }
823 
824 
825 MA::DeviceGeneratorsMap MAHeadController::ApplyGenerators(MAHeadTransitionGenerators& generators, bool clear)
826 {
827  MA::DeviceGeneratorsMap DeviceGenerators;
828 
829  generators.Normalize();
830  if (generators.NeckPan)
831  {
832  SetPower(MA::NeckPan, true);
833 
834  if (clear)
835  {
836  NeckPan->ClearGenerators();
837  }
838  NeckPan->AddGeneratorContainer(*generators.NeckPan);
839  DeviceGenerators.insert(MA::DeviceGeneratorPair(NeckPan.get(), generators.NeckPan));
840  }
841 
842  if (generators.NeckTilt1)
843  {
844  SetPower(MA::NeckTilt1, true);
845 
846  if (clear)
847  {
848  NeckTilt1->ClearGenerators();
849  }
850  NeckTilt1->AddGeneratorContainer(*generators.NeckTilt1);
851  DeviceGenerators.insert(MA::DeviceGeneratorPair(NeckTilt1.get(), generators.NeckTilt1));
852  }
853 
854  if (generators.NeckTilt2)
855  {
856  SetPower(MA::NeckTilt2, true);
857 
858  if (clear)
859  {
860  NeckTilt2->ClearGenerators();
861  }
862  NeckTilt2->AddGeneratorContainer(*generators.NeckTilt2);
863  DeviceGenerators.insert(MA::DeviceGeneratorPair(NeckTilt2.get(), generators.NeckTilt2));
864  }
865  return DeviceGenerators;
866 }
MANum< float > Value
Current value.
Definition: MABodyTypes.hpp:86
Delay generator class.
virtual void UpdateRobotState(MARobotState &state) override
Update the robot state.
#define MA_RANDOM_POINT_1(_variable_name, _min, _max)
Set a random point with one value.
void SetTransferFunction(FunctionType function)
Set the transfer function.
bool MCRangeCheck(const T &value, const T &min, const T &max)
Range check of a value.
Definition: MCDefs.hpp:544
boost::shared_ptr< MADevice > NeckTilt1
Neck tilt1.
MANum< float > UpDownValue
Current up-down direction value.
Helper class to build head transition generators.
virtual MA::DeviceGeneratorsMap GetSkitTransitionGenerators(MA::SkitBaseSPtr skit) override
Get skit transition generators.
boost::shared_ptr< MAMicrophoneDevice > Microphone
Microphone.
virtual void FromJointDegree(int degree) override
Compute from a joint degree value.
boost::shared_ptr< MADevice > NeckTilt2
Neck tilt2.
#define MC_ERROR(...)
Error macro.
Definition: MCLog.hpp:45
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
Base class for the controllers.
T MCAbs(const T &value)
Calculate absolute value.
Definition: MCDefs.hpp:399
float RubbingCenterForeBack
Store the center (fore-back) position of the rubbing.
Device class.
Definition: MADevice.hpp:57
Simple generator class.
A base class for the limb features.
Definition: MABodyTypes.hpp:56
static FunctionType GetRandomFunction()
Get a random generator function type.
MAHeadController()
Class constructor.
The left-right turning feature of the head.
boost::shared_ptr< MADevice > NeckPan
Neck pan.
Generator container class.
virtual MA::DeviceList GetMotors() const override
Get the list of the motors.
boost::shared_ptr< MACameraDevice > Camera
Camera.
MAGeneratorContainer * GetGeneratorContainer(MA::Leg::LegTypes leg, MA::LegJointsType joint) const
Get generator container for a leg joint.
virtual ~MAHeadController()
Class destructor.
Motion sequence (motion skit) class.
boost::shared_ptr< MADevice > CrownButton
Crown sensor.
virtual int StartTransition(const std::string &name)
Start a transition.
Base class for generators.
Head controller class.
boost::scoped_ptr< MAAudio > Audio
Audio input/output.
float MCFloatInfinity()
Get float infinity.
Definition: MCDefs.cpp:110
float RubbingCenterLeftRight
Store the center (left-right) position of the rubbing.
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...
#define MC_LOG(...)
Debug macro.
Definition: MCLog.hpp:41
Robot state.
#define MA_RANDOM_POINT_N(_variable_name, _count, _min, _max)
Set a random point with a value list.
MANum< float > ForeBackValue
Current fore-back direction value.
boost::shared_ptr< MADevice > ChinButton
Chin sensor.
The fore-back, up-down position of the head.
virtual int ToJointDegree() const =0
Transform to a joint degree value.
boost::scoped_ptr< MAHead > Head
Head.