DoubleSupport.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019, CNRS-UM LIRMM
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "DoubleSupport.h"
29 
30 namespace lipm_walking
31 {
32 
34 {
35  auto & ctl = controller();
36 
37  double phaseDuration = ctl.doubleSupportDuration(); // careful! side effect here
38 
39  duration_ = phaseDuration;
40  initLeftFootRatio_ = ctl.leftFootRatio();
41  remTime_ = (phaseDuration > ctl.timeStep) ? phaseDuration : -ctl.timeStep;
42  stateTime_ = 0.;
43  stopDuringThisDSP_ = ctl.pauseWalking;
44  if(phaseDuration > ctl.timeStep)
45  {
46  timeSinceLastPreviewUpdate_ = 2 * PREVIEW_UPDATE_PERIOD; // update at transition...
47  }
48  else // ... unless DSP duration is zero
49  {
50  timeSinceLastPreviewUpdate_ = 0.;
51  }
52 
53  const std::string & targetSurfaceName = ctl.targetContact().surfaceName;
54  auto actualTargetPose = ctl.controlRobot().surfacePose(targetSurfaceName);
55  ctl.plan.goToNextFootstep(actualTargetPose);
56  if(ctl.isLastDSP()) // called after goToNextFootstep
57  {
58  stopDuringThisDSP_ = true;
59  }
60 
62  if(ctl.prevContact().surfaceName == "LeftFootCenter")
63  {
64  stabilizer().setContact(stabilizer().leftFootTask, ctl.prevContact());
65  stabilizer().setContact(stabilizer().rightFootTask, ctl.supportContact());
66  targetLeftFootRatio_ = 0.;
67  }
68  else // (ctl.prevContact().surfaceName == "RightFootCenter")
69  {
70  stabilizer().setContact(stabilizer().leftFootTask, ctl.supportContact());
71  stabilizer().setContact(stabilizer().rightFootTask, ctl.prevContact());
72  targetLeftFootRatio_ = 1.;
73  }
74  if(stopDuringThisDSP_)
75  {
76  targetLeftFootRatio_ = 0.5;
77  }
78  stabilizer().addTasks(ctl.solver());
79 
80  logger().addLogEntry("rem_phase_time", [this]() { return remTime_; });
81  logger().addLogEntry("support_xmax",
82  [&ctl]() { return std::max(ctl.prevContact().xmax(), ctl.supportContact().xmax()); });
83  logger().addLogEntry("support_xmin",
84  [&ctl]() { return std::min(ctl.prevContact().xmin(), ctl.supportContact().xmin()); });
85  logger().addLogEntry("support_ymax",
86  [&ctl]() { return std::max(ctl.prevContact().ymax(), ctl.supportContact().ymax()); });
87  logger().addLogEntry("support_ymin",
88  [&ctl]() { return std::min(ctl.prevContact().ymin(), ctl.supportContact().ymin()); });
89  logger().addLogEntry("support_zmax",
90  [&ctl]() { return std::max(ctl.prevContact().zmax(), ctl.supportContact().zmax()); });
91  logger().addLogEntry("support_zmin",
92  [&ctl]() { return std::min(ctl.prevContact().zmin(), ctl.supportContact().zmin()); });
93  logger().addLogEntry("walking_phase", []() { return 2.; });
94 
95  if(stopDuringThisDSP_)
96  {
97  ctl.pauseWalking = false;
98  }
99 
100  runState(); // don't wait till next cycle to update reference and tasks
101 }
102 
104 {
105  stabilizer().removeTasks(controller().solver());
106 
107  logger().removeLogEntry("rem_phase_time");
108  logger().removeLogEntry("support_xmax");
109  logger().removeLogEntry("support_xmin");
110  logger().removeLogEntry("support_ymax");
111  logger().removeLogEntry("support_ymin");
112  logger().removeLogEntry("support_zmax");
113  logger().removeLogEntry("support_zmin");
114  logger().removeLogEntry("walking_phase");
115 }
116 
118 {
119  auto & ctl = controller();
120  double dt = ctl.timeStep;
121 
122  if(remTime_ > 0 && timeSinceLastPreviewUpdate_ > PREVIEW_UPDATE_PERIOD
123  && !(stopDuringThisDSP_ && remTime_ < PREVIEW_UPDATE_PERIOD))
124  {
125  updatePreview();
126  }
127 
128  double x = clamp(remTime_ / duration_, 0., 1.);
129  ctl.leftFootRatio(x * initLeftFootRatio_ + (1. - x) * targetLeftFootRatio_);
130 
131  ctl.preview->integrate(pendulum(), dt);
132  pendulum().completeIPM(ctl.prevContact());
133  pendulum().resetCoMHeight(ctl.plan.comHeight(), ctl.prevContact());
134  stabilizer().run();
135 
136  remTime_ -= dt;
137  stateTime_ += dt;
138  timeSinceLastPreviewUpdate_ += dt;
139 }
140 
142 {
143  auto & ctl = controller();
144  if(!stopDuringThisDSP_ && remTime_ < 0.)
145  {
146  output("SingleSupport");
147  return true;
148  }
149  if(stopDuringThisDSP_ && remTime_ < -0.5)
150  {
151  if(!ctl.isLastDSP())
152  {
153  ctl.plan.restorePreviousFootstep(); // current one is for next SSP
154  }
155  output("Standing");
156  return true;
157  }
158  return false;
159 }
160 
162 {
163  auto & ctl = controller();
164  ctl.mpc().contacts(ctl.prevContact(), ctl.supportContact(), ctl.targetContact());
165  if(stopDuringThisDSP_)
166  {
167  ctl.mpc().phaseDurations(0., remTime_, 0.);
168  }
169  else
170  {
171  ctl.mpc().phaseDurations(0., remTime_, ctl.singleSupportDuration());
172  }
173  if(ctl.updatePreview())
174  {
175  timeSinceLastPreviewUpdate_ = 0.;
176  }
177  else
178  {
179  LOG_WARNING("No capture trajectory, resuming walking");
180  stopDuringThisDSP_ = false;
181  }
182 }
183 
184 } // namespace lipm_walking
185 
186 EXPORT_SINGLE_STATE("DoubleSupport", lipm_walking::states::DoubleSupport)
double clamp(double v, double vMin, double vMax)
Clamp a value in a given interval.
Definition: clamp.h:47
ContactState contactState()
Get contact state.
Definition: Stabilizer.h:200
Pendulum & pendulum()
Get pendulum reference.
Definition: State.h:82
void addTasks(mc_solver::QPSolver &solver)
Add tasks to QP solver.
Definition: Stabilizer.cpp:358
void updatePreview()
Update horizontal MPC preview.
void completeIPM(const Contact &plane)
Complete inverted pendulum inputs (ZMP and natural frequency) from contact plane. ...
Definition: Pendulum.cpp:88
void run()
Update QP task targets.
Definition: Stabilizer.cpp:490
Stabilizer & stabilizer()
Get stabilizer.
Definition: State.h:115
void runState() override
Main state function, called if no transition at this cycle.
void resetCoMHeight(double height, const Contact &contact)
Reset CoM height above a given contact plane.
Definition: Pendulum.cpp:79
constexpr double PREVIEW_UPDATE_PERIOD
Preview update period, same as MPC sampling period.
Definition: Controller.h:62
void start() override
Start state.
mc_rtc::Logger & logger()
Get logger.
Definition: State.h:72
void setContact(std::shared_ptr< mc_tasks::force::CoPTask > footTask, const Contact &contact)
Configure foot task for contact at a given location.
Definition: Stabilizer.cpp:372
Main controller namespace.
Definition: build.dox:1
void removeTasks(mc_solver::QPSolver &solver)
Remove tasks from QP solver.
Definition: Stabilizer.cpp:365
Controller & controller()
Get controller.
Definition: State.h:52
void teardown() override
Teardown state.
bool checkTransitions() override
Check transitions at beginning of control cycle.
Double support phase while walking.
Definition: DoubleSupport.h:45