Contact.h
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 #pragma once
29 
30 #include <mc_rbdyn/Robot.h>
31 #include <mc_rtc/Configuration.h>
32 #include <mc_rtc/logging.h>
33 
34 #include <SpaceVecAlg/SpaceVecAlg>
35 
36 #include <cmath>
37 #include <lipm_walking/Sole.h>
39 
40 namespace lipm_walking
41 {
42 
43 using HrepXd = std::pair<Eigen::MatrixXd, Eigen::VectorXd>;
44 
48 enum class ContactState
49 {
51  LeftFoot,
52  RightFoot
53 };
54 
58 struct Contact
59 {
60  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
61 
67  Contact() {}
68 
74  Contact(const sva::PTransformd & pose) : pose(pose) {}
75 
79  Eigen::Vector3d sagittal() const
80  {
81  return pose.rotation().row(0);
82  }
83 
87  Eigen::Vector3d lateral() const
88  {
89  return pose.rotation().row(1);
90  }
91 
95  Eigen::Vector3d normal() const
96  {
97  return pose.rotation().row(2);
98  }
99 
103  const Eigen::Vector3d & position() const
104  {
105  return pose.translation();
106  }
107 
111  const Eigen::Vector3d & p() const
112  {
113  return position();
114  }
115 
121  Eigen::Vector3d anklePos(const Sole & sole) const
122  {
123  if(surfaceName == "LeftFootCenter")
124  {
125  return p() + sole.leftAnkleOffset.x() * sagittal() + sole.leftAnkleOffset.y() * lateral();
126  }
127  else if(surfaceName == "RightFootCenter")
128  {
129  return p() + sole.leftAnkleOffset.x() * sagittal() - sole.leftAnkleOffset.y() * lateral();
130  }
131  else
132  {
133  LOG_ERROR("Cannot compute anklePos for surface " << surfaceName);
134  return p();
135  }
136  }
137 
143  sva::PTransformd anklePose(const Sole & sole) const
144  {
145  return {pose.rotation(), anklePos(sole)};
146  }
147 
151  double x() const
152  {
153  return position()(0);
154  }
155 
159  double y() const
160  {
161  return position()(1);
162  }
163 
167  double z() const
168  {
169  return position()(2);
170  }
171 
175  Eigen::Vector3d vertex0() const
176  {
177  return position() + halfLength * sagittal() + halfWidth * lateral();
178  }
179 
183  Eigen::Vector3d vertex1() const
184  {
185  return position() + halfLength * sagittal() - halfWidth * lateral();
186  }
187 
191  Eigen::Vector3d vertex2() const
192  {
193  return position() - halfLength * sagittal() - halfWidth * lateral();
194  }
195 
199  Eigen::Vector3d vertex3() const
200  {
201  return position() - halfLength * sagittal() + halfWidth * lateral();
202  }
203 
207  template<int i>
208  double minCoord() const
209  {
210  return std::min(std::min(vertex0()(i), vertex1()(i)), std::min(vertex2()(i), vertex3()(i)));
211  }
212 
216  template<int i>
217  double maxCoord() const
218  {
219  return std::max(std::max(vertex0()(i), vertex1()(i)), std::max(vertex2()(i), vertex3()(i)));
220  }
221 
225  double xmin() const
226  {
227  return minCoord<0>();
228  }
229 
233  double xmax() const
234  {
235  return maxCoord<0>();
236  }
237 
241  double ymin() const
242  {
243  return minCoord<1>();
244  }
245 
249  double ymax() const
250  {
251  return maxCoord<1>();
252  }
253 
257  double zmin() const
258  {
259  return minCoord<2>();
260  }
261 
265  double zmax() const
266  {
267  return maxCoord<2>();
268  }
269 
273  HrepXd hrep() const
274  {
275  Eigen::Matrix<double, 4, 2> localHrepMat, worldHrepMat;
276  Eigen::Matrix<double, 4, 1> localHrepVec, worldHrepVec;
277  // clang-format off
278  localHrepMat <<
279  +1, 0,
280  -1, 0,
281  0, +1,
282  0, -1;
283  localHrepVec <<
284  halfLength,
285  halfLength,
286  halfWidth,
287  halfWidth;
288  // clang-format on
289  if((normal() - world::vertical).norm() > 1e-3)
290  {
291  LOG_WARNING("Contact is not horizontal");
292  }
293  const sva::PTransformd & X_0_c = pose;
294  worldHrepMat = localHrepMat * X_0_c.rotation().topLeftCorner<2, 2>();
295  worldHrepVec = worldHrepMat * X_0_c.translation().head<2>() + localHrepVec;
296  return HrepXd(worldHrepMat, worldHrepVec);
297  }
298 
304  inline sva::PTransformd robotTransform(const mc_rbdyn::Robot & robot) const
305  {
306  const sva::PTransformd & X_0_c = pose;
307  const sva::PTransformd & X_0_fb = robot.posW();
308  sva::PTransformd X_s_0 = robot.surfacePose(surfaceName).inv();
309  sva::PTransformd X_s_fb = X_0_fb * X_s_0;
310  return X_s_fb * X_0_c;
311  }
312 
313 public:
314  Eigen::Vector3d refVel =
315  Eigen::Vector3d::Zero();
316  double halfLength = 0.;
317  double halfWidth = 0.;
318  mc_rtc::Configuration
320  std::string surfaceName = "";
321  sva::PTransformd pose;
322  unsigned id = 0;
323 };
324 
332 inline Contact operator*(const sva::PTransformd & X, const Contact & contact)
333 {
334  Contact result = contact;
335  result.pose = X * contact.pose;
336  return result;
337 }
338 } // namespace lipm_walking
339 
340 namespace mc_rtc
341 {
342 template<>
343 struct ConfigurationLoader<lipm_walking::Contact>
344 {
345  static lipm_walking::Contact load(const mc_rtc::Configuration & config)
346  {
347  lipm_walking::Contact contact;
348  contact.pose = config("pose");
349  config("half_length", contact.halfLength);
350  config("half_width", contact.halfWidth);
351  config("ref_vel", contact.refVel);
352  config("surface", contact.surfaceName);
353  if(config.has("swing"))
354  {
355  contact.swingConfig = config("swing");
356  }
357  return contact;
358  }
359 
360  static mc_rtc::Configuration save(const lipm_walking::Contact & contact)
361  {
362  mc_rtc::Configuration config;
363  config.add("half_length", contact.halfLength);
364  config.add("half_width", contact.halfWidth);
365  config.add("pose", contact.pose);
366  config.add("ref_vel", contact.refVel);
367  config.add("surface", contact.surfaceName);
368  if(!contact.swingConfig.empty())
369  {
370  config("swing") = contact.swingConfig;
371  }
372  return config;
373  }
374 };
375 
376 } // namespace mc_rtc
std::string surfaceName
Name of the contact surface in robot model.
Definition: Contact.h:320
HrepXd hrep() const
Halfspace representation of contact area in world frame.
Definition: Contact.h:273
const Eigen::Vector3d & p() const
Shorthand for position.
Definition: Contact.h:111
ContactState
Contact state: set of feet in contact.
Definition: Contact.h:48
double xmin() const
Minimum world x-coordinate of the contact area.
Definition: Contact.h:225
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Contact()
Empty constructor.
Definition: Contact.h:67
Eigen::Vector3d sagittal() const
Sagittal unit vector of the contact frame.
Definition: Contact.h:79
sva::PTransformd robotTransform(const mc_rbdyn::Robot &robot) const
Compute floating base transform that puts the robot in contact.
Definition: Contact.h:304
Eigen::Vector3d vertex3() const
Corner vertex of the contact area.
Definition: Contact.h:199
double z() const
Shorthand for world z-coordinate.
Definition: Contact.h:167
sva::PTransformd anklePose(const Sole &sole) const
Get frame rooted at the ankle.
Definition: Contact.h:143
Framework namespace, only used to add a configuration loader.
Definition: Contact.h:340
Eigen::Vector3d vertex0() const
Corner vertex of the contact area.
Definition: Contact.h:175
Eigen::Vector3d refVel
Desired CoM velocity when the robot is supporting itself on this contact.
Definition: Contact.h:314
double x() const
Shorthand for world x-coordinate.
Definition: Contact.h:151
double maxCoord() const
Maximum coordinate for vertices of the contact area.
Definition: Contact.h:217
static lipm_walking::Contact load(const mc_rtc::Configuration &config)
Definition: Contact.h:345
static mc_rtc::Configuration save(const lipm_walking::Contact &contact)
Definition: Contact.h:360
Eigen::Vector3d vertex2() const
Corner vertex of the contact area.
Definition: Contact.h:191
double halfWidth
Half-width of the contact rectangle in [m].
Definition: Contact.h:317
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Eigen::Vector2d leftAnkleOffset
Offset from center to ankle frames in the left sole frame.
Definition: Sole.h:42
Contact operator*(const sva::PTransformd &X, const Contact &contact)
Apply Plucker transform to contact frame.
Definition: Contact.h:332
double halfLength
Half-length of the contact rectangle in [m].
Definition: Contact.h:316
mc_rtc::Configuration swingConfig
Additional configuration for swing foot trajectories that originate from this contact.
Definition: Contact.h:319
Eigen::Vector3d anklePos(const Sole &sole) const
Position of ankle from foot center frame.
Definition: Contact.h:121
Main controller namespace.
Definition: build.dox:1
double xmax() const
Maximum world x-coordinate of the contact area.
Definition: Contact.h:233
double ymax() const
Maximum world y-coordinate of the contact area.
Definition: Contact.h:249
double zmin() const
Minimum world z-coordinate of the contact area.
Definition: Contact.h:257
double minCoord() const
Minimum coordinate for vertices of the contact area.
Definition: Contact.h:208
double ymin() const
Minimum world y-coordinate of the contact area.
Definition: Contact.h:241
double y() const
Shorthand for world y-coordinate.
Definition: Contact.h:159
Contacts wrap foot frames with extra info from the footstep plan.
Definition: Contact.h:58
Contact(const sva::PTransformd &pose)
Define from Plücker transform.
Definition: Contact.h:74
Foot sole properties.
Definition: Sole.h:38
Eigen::Vector3d lateral() const
Lateral unit vector of the contact frame.
Definition: Contact.h:87
std::pair< Eigen::MatrixXd, Eigen::VectorXd > HrepXd
Definition: Contact.h:43
const Eigen::Vector3d & position() const
World position of the contact frame.
Definition: Contact.h:103
const Eigen::Vector3d vertical
Definition: world.h:41
double zmax() const
Maximum world z-coordinate of the contact area.
Definition: Contact.h:265
Eigen::Vector3d vertex1() const
Corner vertex of the contact area.
Definition: Contact.h:183
sva::PTransformd pose
Plücker transform of the contact in the inertial frame.
Definition: Contact.h:321
Eigen::Vector3d normal() const
Normal unit vector of the contact frame.
Definition: Contact.h:95