Main Page · Modules · All Classes · Class Hierarchy
MABodyMotion.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 "MABodyMotion.hpp"
23 
24 #include "ml/MAClassifierModels.hpp"
25 #include "MAComplexIndicators.hpp"
26 #include "MARobotState.hpp"
27 #include "MATorso.hpp"
28 #include "MATypeRanges.hpp"
29 
30 #include <MCSampleStatistics.hpp>
31 
32 #include <boost/math/constants/constants.hpp>
33 
35 {
36  Raw.SetMinMax(MA::AccelRawMin, MA::AccelRawMax);
37  // Note: Real magnitude for value representation on diagrams
38  Raw.SetMagnitude(1000000.0);
39  Degree.SetMinMax(MA::AccelMin, MA::AccelMax);
40 }
41 
42 
43 std::string MAFloorSurfacesTypeStr(const MA::FloorSurfacesType surface)
44 {
45  if (surface == MA::WoodFlooring)
46  return "Wood flooring";
47  if (surface == MA::Field)
48  return "Field";
49  if (surface == MA::Carpet)
50  return "Carpet";
51  if (surface == MA::FoamMat)
52  return "Foam mat";
53  if (surface == MA::Vinyl)
54  return "Vinyl";
55  if (surface == MA::Tiles)
56  return "Tiles";
57  if (surface == MA::CarpetedFloor)
58  return "Carpeted floor";
59  if (surface == MA::UserDefinedFloor)
60  return "User defined";
61 
62  return "Unknown";
63 }
64 
65 
66 std::string MAFloorSurfaceSoftnessTypeStr(const MA::FloorSurfaceSoftnessType surface_softness)
67 {
68  if (surface_softness == MA::HardFlooring)
69  return "Hard floor surface";
70  if (surface_softness == MA::SoftFlooring)
71  return "Soft floor surface";
72 
73  return "Very soft floor surface";
74 }
75 
76 
77 MA::FloorSurfaceSoftnessType MAMapFloorSurfaceToSoftness(const MA::FloorSurfacesType surface)
78 {
79  if (surface == MA::WoodFlooring)
80  return MA::HardFlooring;
81  if (surface == MA::Field)
82  return MA::SoftFlooring;
83  if (surface == MA::Carpet)
84  return MA::VerySoftFlooring;
85  if (surface == MA::FoamMat)
86  return MA::SoftFlooring;
87  if (surface == MA::Vinyl)
88  return MA::HardFlooring;
89  if (surface == MA::Tiles)
90  return MA::HardFlooring;
91  if (surface == MA::CarpetedFloor)
92  return MA::SoftFlooring;
93 
94  return MA::HardFlooring;
95 }
96 
97 
98 MAFloorSurface::MAFloorSurface() : Surface(-500, -500, 3000), CurrentSurface(-500, -500, 3000),
99  OwnerFeedback(-500, -500, 3000)
100 {
101 }
102 
103 
104 MABodyMotion::MABodyMotion() : MARobotStateUpdater(MA::UpdateSensorIndicators),
105  BodyState((int)MA::UnknownBodyState, (int)MA::UnknownBodyState, (int)MA::Poked),
106  MotionControlAge(0, 0, 60),
107  BackStrokedFactor(0, 0, 2000),
108  LyingOnBackFactor(0, 0, 400),
109  LyingOnBackLeftSideFactor(0, 0, 3000),
110  LyingOnBackRightSideFactor(0, 0, 3000),
111  BodyOnLeftSideFactor(0, 0, 3000),
112  BodyOnRightSideFactor(0, 0, 3000),
113  LyingFactor(0, 0, 400),
114  LyingOnLeftSideFactor(0, 0, 3000),
115  LyingOnRightSideFactor(0, 0, 3000),
116  SittingFactor(0, 0, 800),
117  FlyingFactor(0, 0, 3000),
118  PokedFactor(0, 0, 600),
119  MotionControlTimer(MC::NoExpiration)
120 {
121  // Indicators
122  BodyPitch.SetMinMax(-MA::StandardRangeMax, MA::StandardRangeMax);
123  BodyRoll.SetMinMax(-MA::StandardRangeMax, MA::StandardRangeMax);
124  UpsideDown.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
125  LateralPosition.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
126  HeadStand.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
127  LyingOnBack.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
128  LyingOnBackLeftSide.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
129  LyingOnBackRightSide.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
130  BodyOnLeftSide.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
131  BodyOnRightSide.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
132  Lying.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
133  LyingOnLeftSide.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
134  LyingOnRightSide.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
135  Sitting.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
136  Flying.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
137  Poked.SetMinMax(MA::StandardRangeMin, MA::StandardRangeMax);
138 }
139 
140 
142 {
143  return BodyRoll >= -25 && BodyRoll <= 25;
144 }
145 
146 
148 {
150 }
151 
152 
154 {
156 }
157 
158 
160 {
161  // Sensor indicators
162  UpsideDown = (int)(((float)AccelZ.Degree+90) / 180.0*100.0);
163  LateralPosition = (int)(((float)AccelY.Degree+90) / 180.0*100.0);
164  HeadStand = (int)(((float)AccelX.Degree+90) / 180.0*100.0);
165  InMotion = state.LegLF->InMotion > 0 || state.LegLH->InMotion > 0 || state.LegRF->InMotion > 0 ||
166  state.LegRH->InMotion > 0 || state.Head->InMotion > 0;
168 
169  GenerateLyingOnBack(state);
170  GenerateLyingOnBackLeftSide(state);
171  GenerateLyingOnBackRightSide(state);
172  GenerateBodyOnLeftSide(state);
173  GenerateBodyOnRightSide(state);
174  GenerateLying(state);
175  GenerateLyingOnLeftSide(state);
176  GenerateLyingOnRightSide(state);
177  GenerateSitting(state);
178  GenerateFlying(state);
179  GeneratePoked(state);
180  // Note: The pitch and roll generation uses the smoothed accelerometer data
181  GenerateBodyPitchAndRoll();
182 }
183 
184 
185 void MABodyMotion::GenerateBodyPitchAndRoll()
186 {
187  float Alpha = atan2(-(float)AccelY.Raw / 10000.0, -(float)AccelZ.Raw / 10000.0);
188  float Beta = atan2(AccelX.Raw, -((float)AccelY.Raw / 10000.0*sin(Alpha)+(float)AccelZ.Raw / 10000.0*cos(Alpha)));
189 
190  BodyRoll = (int)(atan(Alpha)*180.0 / boost::math::constants::pi<float>());
191  BodyPitch = (int)(atan(Beta)*180.0 / boost::math::constants::pi<float>());
192 }
193 
194 
195 void MABodyMotion::GenerateLyingOnBack(MARobotState& state)
196 {
197  if (UpsideDown >= 75 &&
198  LateralPosition.GetValueChange() < 5 && UpsideDown.GetValueChange() < 10 &&
199  state.Torso->BackGrabbed == 0)
200  {
201  // Back lying "state" can be reached in 400 ms
202  LyingOnBackFactor += state.Torso->CycleTime;
203  } else {
204  LyingOnBackFactor -= state.Torso->CycleTime*3;
205  }
206  LyingOnBack = LyingOnBackFactor.GetScaledValue();
207 }
208 
209 
210 void MABodyMotion::GenerateLyingOnBackLeftSide(MARobotState& state)
211 {
212  if (UpsideDown >= 65 && LateralPosition < 25 &&
213  LateralPosition.GetValueChange() < 5 && UpsideDown.GetValueChange() < 10 &&
214  state.Torso->BackGrabbed == 0)
215  {
216  // Back lying on left side "state" can be reached in 3000 ms
217  LyingOnBackLeftSideFactor += state.Torso->CycleTime;
218  } else {
219  LyingOnBackLeftSideFactor -= state.Torso->CycleTime*3;
220  }
221  LyingOnBackLeftSide = LyingOnBackLeftSideFactor.GetScaledValue();
222 }
223 
224 
225 void MABodyMotion::GenerateLyingOnBackRightSide(MARobotState& state)
226 {
227  if (UpsideDown >= 65 && LateralPosition > 75 &&
228  LateralPosition.GetValueChange() < 5 && UpsideDown.GetValueChange() < 10 &&
229  state.Torso->BackGrabbed == 0)
230  {
231  // Back lying on right side "state" can be reached in 3000 ms
232  LyingOnBackRightSideFactor += state.Torso->CycleTime;
233  } else {
234  LyingOnBackRightSideFactor -= state.Torso->CycleTime*3;
235  }
236  LyingOnBackRightSide = LyingOnBackRightSideFactor.GetScaledValue();
237 }
238 
239 
240 void MABodyMotion::GenerateBodyOnLeftSide(MARobotState& state)
241 {
242  bool PawsFree = true;
243 
244  PawsFree = PawsFree && state.LegLF->Paw == 0;
245  PawsFree = PawsFree && state.LegLH->Paw == 0;
246  PawsFree = PawsFree && state.LegRF->Paw == 0;
247  PawsFree = PawsFree && state.LegRH->Paw == 0;
248 
249  if (UpsideDown > 20 && UpsideDown < 95 && LateralPosition < 10 &&
250  LateralPosition.GetValueChange() < 5 && UpsideDown.GetValueChange() < 10 &&
251  PawsFree && state.Torso->BackGrabbed == 0)
252  {
253  // Body on left side "state" can be reached in 3000 ms
254  BodyOnLeftSideFactor += state.Torso->CycleTime;
255  } else {
256  BodyOnLeftSideFactor -= state.Torso->CycleTime*3;
257  }
258  BodyOnLeftSide = BodyOnLeftSideFactor.GetScaledValue();
259 }
260 
261 
262 void MABodyMotion::GenerateBodyOnRightSide(MARobotState& state)
263 {
264  bool PawsFree = true;
265 
266  PawsFree = PawsFree && state.LegLF->Paw == 0;
267  PawsFree = PawsFree && state.LegLH->Paw == 0;
268  PawsFree = PawsFree && state.LegRF->Paw == 0;
269  PawsFree = PawsFree && state.LegRH->Paw == 0;
270 
271  if (UpsideDown > 20 && UpsideDown < 95 && LateralPosition > 90 &&
272  LateralPosition.GetValueChange() < 5 && UpsideDown.GetValueChange() < 10 &&
273  PawsFree && state.Torso->BackGrabbed == 0)
274  {
275  // Body on right side "state" can be reached in 3000 ms
276  BodyOnRightSideFactor += state.Torso->CycleTime;
277  } else {
278  BodyOnRightSideFactor -= state.Torso->CycleTime*3;
279  }
280  BodyOnRightSide = BodyOnRightSideFactor.GetScaledValue();
281 }
282 
283 
284 void MABodyMotion::GenerateLying(MARobotState& state)
285 {
286  bool Result = true;
287  int LegsMovedToStand = 0;
288 
289  LegsMovedToStand += (state.LegLF->Moving && state.LegLF->UpDown < -80);
290  LegsMovedToStand += (state.LegLH->Moving && state.LegLH->UpDown < -80);
291  LegsMovedToStand += (state.LegRF->Moving && state.LegRF->UpDown < -80);
292  LegsMovedToStand += (state.LegRH->Moving && state.LegRH->UpDown < -80);
293 
294  Result = Result && !state.BodyMotion->SkitPlayback;
295  Result = Result && UpsideDown < 15 && HeadStand >= 8;
296  Result = Result && Sitting <= 10;
297  Result = Result && LateralPosition.GetValueChange() < 5 && UpsideDown.GetValueChange() < 10;
298  Result = Result && !state.ComplexIndicators->IsStandingPosture && LegsMovedToStand < 4;
299  Result = Result && !state.ComplexIndicators->PoseTransition;
300  Result = Result && !state.ComplexIndicators->IsLocomotionActive();
301  if (Result)
302  {
303  // Lying "state" can be reached in 3000 msec
304  LyingFactor += state.Torso->CycleTime;
305  } else {
306  LyingFactor -= state.Torso->CycleTime;
307  }
308  Lying = LyingFactor.GetScaledValue();
309 }
310 
311 
312 void MABodyMotion::GenerateLyingOnLeftSide(MARobotState& state)
313 {
314  if (UpsideDown > 0 && UpsideDown < 15 && LateralPosition > 0 && LateralPosition < 15 &&
315  LateralPosition.GetValueChange() < 5 && UpsideDown.GetValueChange() < 10 &&
316  state.Torso->BackGrabbed == 0)
317  {
318  // Lying on left side "state" can be reached in 3000 ms
319  LyingOnLeftSideFactor += state.Torso->CycleTime;
320  } else {
321  LyingOnLeftSideFactor -= state.Torso->CycleTime*3;
322  }
323  LyingOnLeftSide = LyingOnLeftSideFactor.GetScaledValue();
324 }
325 
326 
327 void MABodyMotion::GenerateLyingOnRightSide(MARobotState& state)
328 {
329  if (UpsideDown > 0 && UpsideDown < 15 && LateralPosition > 80 && LateralPosition < 95 &&
330  LateralPosition.GetValueChange() < 5 && UpsideDown.GetValueChange() < 10 &&
331  state.Torso->BackGrabbed == 0)
332  {
333  // Lying on right side "state" can be reached in 3000 ms
334  LyingOnRightSideFactor += state.Torso->CycleTime;
335  } else {
336  LyingOnRightSideFactor -= state.Torso->CycleTime*3;
337  }
338  LyingOnRightSide = LyingOnRightSideFactor.GetScaledValue();
339 }
340 
341 
342 void MABodyMotion::GenerateSitting(MARobotState& state)
343 {
344  if (UpsideDown < 15 && HeadStand >= 0 && HeadStand <= 12 &&
345  LateralPosition.GetValueChange() < 5 && UpsideDown.GetValueChange() < 10 &&
346  (state.LegLF->Paw == 1 || state.LegRF->Paw == 1))
347  {
348  // Sitting "state" can be reached in 800 msec
349  SittingFactor += state.Torso->CycleTime;
350  } else {
351  SittingFactor -= state.Torso->CycleTime;
352  }
353  Sitting = SittingFactor.GetScaledValue();
354 }
355 
356 
357 void MABodyMotion::GenerateFlying(MARobotState& state)
358 {
359  int Multiplier = state.Torso->BackGrabbed > 80 ? 3 : 1;
360  bool PawsFree = true;
361 
362  PawsFree = PawsFree && state.LegLF->Paw == 0;
363  PawsFree = PawsFree && state.LegLH->Paw == 0;
364  PawsFree = PawsFree && state.LegRF->Paw == 0;
365  PawsFree = PawsFree && state.LegRH->Paw == 0;
366 
367  if ((int)BodyState == MA::PickupMode && PawsFree)
368  {
369  // Flying "state" can be reached in 1-3 seconds and moderated to zero
370  // after 3 seconds
371  FlyingFactor += (int)state.Torso->CycleTime*Multiplier;
372  } else {
373  FlyingFactor -= (int)state.Torso->CycleTime;
374  }
375  Flying = FlyingFactor.GetScaledValue();
376 }
377 
378 
379 void MABodyMotion::GeneratePoked(MARobotState& state)
380 {
381  // When any of the legs is moving, the robot does some locomotion or
382  // self-movements of the body, it is not taken into account as "poked" state.
383  if ((int)BodyState == MA::Poked && state.BodyMotion->Flying == 0 &&
384  !(bool)state.LegLF->Moving && !(bool)state.LegLH->Moving &&
385  !(bool)state.LegRF->Moving && !(bool)state.LegRH->Moving &&
386  !state.ComplexIndicators->IsLocomotionActive() && UpsideDown < 20)
387  {
388  // Poked "state" can be reached in 600 milliseconds
389  PokedFactor += state.Torso->CycleTime;
390  } else {
391  PokedFactor -= state.Torso->CycleTime*2;
392  }
393  Poked = PokedFactor.GetScaledValue();
394 }
void Start(int time_shift=0)
Start the timer.
Definition: MCTimer.cpp:183
bool IsBodyRollInWalkRange() const
Check if the body roll is in the acceptable walking range.
MAIntervalNum< int > LyingOnBackFactor
Indicator variable when the robot body is lying upside down.
MANum< int > Degree
Degree (-90°..90°)
MAIntervalNum< int > LyingOnBackRightSideFactor
Indicator variable when the robot body is lying upside down/right side.
virtual void UpdateRobotState(MARobotState &state) override
Update the robot state.
virtual void SetMinMax(T min_value, T max_value)
Set the minimal and maximal values.
Definition: MANum.hpp:235
MAIntervalNum< int > LyingOnBackLeftSideFactor
Indicator variable when the robot body is lying upside down/left side.
MANum< int > MotionControlAge
Elapsed time since the last motion control command (in seconds)
MANum< int > BodyRoll
Body roll.
MAIntervalNum< int > SittingFactor
Indicator variable for sitting position.
bool IsStarted() const
Check if the timer has been started.
Definition: MCTimer.cpp:177
void StopMotionControlTimer()
Stop the motion control timer.
boost::scoped_ptr< MAComplexIndicators > ComplexIndicators
Complex indicators.
MANum< int > InMotion
Any body part is in motion.
void Stop()
Stop the timer.
Definition: MCTimer.cpp:199
MAIntervalNum< int > LyingFactor
Indicator variable when the robot body is lying.
boost::scoped_ptr< MALeg > LegRH
LegRH.
MABodyMotion()
Struct constructor.
MANum< int > Raw
Raw data (-19613300..19613300)
MCTimer MotionControlTimer
Motion control command timer.
MAIntervalNum< int > LyingOnRightSideFactor
Indicator variable when the robot body is lying on its right side.
MAIntervalNum< int > FlyingFactor
Indicator variable to detect the flying (pick-up) mode.
MAFloorSurface()
Struct constructor.
MAIntervalNum< int > BodyOnRightSideFactor
Indicator variable when the robot body is on its right side.
MANum< int > BodyPitch
Body pitch.
MAAccelData AccelZ
Accelerometer (Z dimension, up-down)
boost::scoped_ptr< MABodyMotion > BodyMotion
Body motion.
boost::scoped_ptr< MALeg > LegLF
LegLF.
std::string MAFloorSurfacesTypeStr(const MA::FloorSurfacesType surface)
Get floor surface string.
int GetElapsedTime()
Get the elapsed time since the timer has been started or since the last timeout.
Definition: MCTimer.cpp:205
MAIntervalNum< int > BodyOnLeftSideFactor
Indicator variable when the robot body is on its left side.
Robot state updater base class.
boost::scoped_ptr< MALeg > LegRF
LegRF.
void SetMagnitude(float value)
Set the magnitude.
Definition: MANum.hpp:299
void StartMotionControlTimer()
Start the motion control timer.
MAIntervalNum< int > LyingOnLeftSideFactor
Indicator variable when the robot body is lying on its left side.
MA::FloorSurfaceSoftnessType MAMapFloorSurfaceToSoftness(const MA::FloorSurfacesType surface)
Map a floor surface to softness.
MAIntervalNum< int > PokedFactor
Indicator variable to detect the poked state.
std::string MAFloorSurfaceSoftnessTypeStr(const MA::FloorSurfaceSoftnessType surface_softness)
Get floor surface softness string.
boost::scoped_ptr< MATorso > Torso
Torso.
MAAccelData AccelY
Accelerometer (Y dimension, left-right)
boost::scoped_ptr< MALeg > LegLH
LegLH.
MAAccelData()
Struct constructor.
MANum< int > BodyState
Body state.
Robot state.
T GetValueChange() const
The last value change difference.
Definition: MANum.hpp:287
MAAccelData AccelX
Accelerometer (X dimension, front-back)
boost::scoped_ptr< MAHead > Head
Head.