RcsPySim
A robot control and simulation library
ECBallOnPlate.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright (c) 2020, Fabio Muratore, Honda Research Institute Europe GmbH, and
3  Technical University of Darmstadt.
4  All rights reserved.
5 
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions are met:
8  1. Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10  2. Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13  3. Neither the name of Fabio Muratore, Honda Research Institute Europe GmbH,
14  or Technical University of Darmstadt, nor the names of its contributors may
15  be used to endorse or promote products derived from this software without
16  specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL FABIO MURATORE, HONDA RESEARCH INSTITUTE EUROPE GMBH,
22  OR TECHNICAL UNIVERSITY OF DARMSTADT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  POSSIBILITY OF SUCH DAMAGE.
29 *******************************************************************************/
30 
31 #include "ExperimentConfig.h"
35 #include "action/AMPlateAngPos.h"
36 #include "action/AMPlatePos5D.h"
40 #include "observation/OMBallPos.h"
41 #include "observation/OMCombined.h"
42 #include "observation/OMPartial.h"
47 #include "physics/ForceDisturber.h"
48 #include "util/string_format.h"
49 
50 #include <Rcs_macros.h>
51 #include <Rcs_typedef.h>
52 #include <Rcs_Mat3d.h>
53 #include <Rcs_Vec3d.h>
54 
55 #ifdef GRAPHICS_AVAILABLE
56 
57 #include <RcsViewer.h>
58 
59 #endif
60 
61 #include <sstream>
62 #include <stdexcept>
63 #include <cmath>
64 
65 namespace Rcs
66 {
67 
69 {
71 
73  {
74  std::string actionModelType = "unspecified";
75  properties->getProperty(actionModelType, "actionModelType");
76 
77  if (actionModelType == "joint_pos") {
78  return new AMJointControlPosition(graph);
79  }
80 
81  else if (actionModelType == "joint_acc") {
82  double maxAction = RCS_DEG2RAD(120); // [1/s^2]
83  properties->getProperty(maxAction, "maxAction");
84  return new AMIntegrate2ndOrder(new AMJointControlPosition(graph), maxAction);
85  }
86 
87  else if (actionModelType == "plate_angpos") {
88  return new AMPlateAngPos(graph);
89  }
90 
91  else if (actionModelType == "plate_angvel") {
92  double maxAction = RCS_DEG2RAD(120); // [1/s]
93  properties->getProperty(maxAction, "maxAction");
94  return new AMIntegrate1stOrder(new AMPlateAngPos(graph), maxAction);
95  }
96 
97  else if (actionModelType == "plate_angacc") {
98  double maxAction = RCS_DEG2RAD(120); // [1/s^2]
99  properties->getProperty(maxAction, "maxAction");
100  return new AMIntegrate2ndOrder(new AMPlateAngPos(graph), maxAction);
101  }
102 
103  else if (actionModelType == "plate_acc5d") {
104  MatNd* maxAction;
105  MatNd_fromStack(maxAction, 5, 1);
106  // Use different max action for linear/angular
107  double max_lin = 0.5; // [m/s^2]
108  double max_ang = RCS_DEG2RAD(120); // [1/s^2]
109 
110  maxAction->ele[0] = max_lin;
111  maxAction->ele[1] = max_lin;
112  maxAction->ele[2] = max_lin;
113  maxAction->ele[3] = max_ang;
114  maxAction->ele[4] = max_ang;
115 
116  return new AMIntegrate2ndOrder(new AMPlatePos5D(graph), maxAction);
117  }
118 
119  else {
120  std::ostringstream os;
121  os << "Unsupported action model type: " << actionModelType;
122  throw std::invalid_argument(os.str());
123  }
124  }
125 
127  {
128  RcsBody* plate = RcsGraph_getBodyByName(graph, "Plate");
129  RcsBody* plateOrigMarker = RcsGraph_getBodyByName(graph, "PlateOriginMarker");
130  RCHECK_MSG(plateOrigMarker, "PlateOriginMarker is missing, please update your xml.");
131  // Set origin marker position
132  HTr_copyOrRecreate(&plateOrigMarker->A_BP, plate->A_BI);
133  // Select observation model
134 
135  bool ballObsAngular = properties->getPropertyBool("ballObsAngular");
136 // bool ballObsInInertialFrame = properties->getPropertyBool(
137 // "ballObsInInertialFrame");
138 
139  std::string actionModelType = "joint_pos";
140  properties->getProperty(actionModelType, "actionModelType");
141  bool havePlateLinPos = actionModelType == "plate_acc5d";
142 
143  auto fullState = new OMCombined();
144 
145  // Add plate linear position if desired
146  if (havePlateLinPos) {
147  auto plin = new OMBodyStateLinear(graph, "Plate", "PlateOriginMarker");
148  plin->setMinState(-0.1);
149  plin->setMaxState(0.1);
150  plin->setMaxVelocity(2.0);
151  fullState->addPart(plin);
152  }
153 
154  // Plate angular position
155  auto pang = new OMBodyStateAngular(graph, "Plate", "PlateOriginMarker");
156  pang->setMinState(-45*M_PI/180);
157  pang->setMaxState(45*M_PI/180);
158  pang->setMaxVelocity(2*360*M_PI/180);
159  // Mask out Z since it's fixed
160  fullState->addPart(OMPartial::fromMask(pang, {true, true, false}));
161 
162  // Ball linear state
163  fullState->addPart(new OMBallPos(graph));
164 
165  if (ballObsAngular) {
166  // Add angular ball state
167  fullState->addPart(new OMBodyStateAngular(graph, "Ball", "Plate"));
168  }
169  return fullState;
170  }
171 
173  {
174  manager->addParam("Ball", new PPDSphereRadius("Plate"));
175  manager->addParam("Ball", new PPDMassProperties());
176  manager->addParam("Ball", new PPDMaterialProperties());
177  manager->addParam("Plate", new PPDMaterialProperties());
178  }
179 
181  {
182  return new ISSBallOnPlate(graph);
183  }
184 
186  {
187  RcsBody* ball = RcsGraph_getBodyByName(graph, "Ball");
188  RcsBody* plate = RcsGraph_getBodyByName(graph, "Plate");
189  return new ForceDisturber(ball, plate);
190  }
191 
192  virtual void initViewer(Rcs::Viewer* viewer)
193  {
194  initManipulability = 0;
195  // Compute initial manipulability
196  auto amIK = actionModel->unwrap<ActionModelIK>();
197  if (amIK != NULL) {
198  initManipulability = amIK->getController()->computeManipulabilityCost();
199  }
200 
201 #ifdef GRAPHICS_AVAILABLE
202  // Set camera above plate
203  RcsBody* plate = RcsGraph_getBodyByName(graph, "Plate");
204  RCHECK(plate);
205  std::string cameraView = "side";
206  properties->getProperty(cameraView, "cameraView");
207 
208  // The camera center is the plate center
209  double cameraCenter[3];
210  Vec3d_copy(cameraCenter, plate->A_BI->org);
211 
212  // The camera location - not specified yet
213  double cameraLocation[3];
214  Vec3d_setZero(cameraLocation);
215 
216  // Camera up vector defaults to z
217  double cameraUp[3];
218  Vec3d_setUnitVector(cameraUp, 2);
219 
220  if (cameraView == "topdown") {
221  // The camera looks down vertically
222  Vec3d_copy(cameraLocation, cameraCenter);
223  // The distance between camera and plate is configurable
224  double cameraToPlateDistanceZ = 1.6;
225  properties->getProperty(cameraToPlateDistanceZ, "cameraToPlateDistance");
226  cameraLocation[2] += cameraToPlateDistanceZ;
227  // The plate's y vector should point up on the view
228  Vec3d_setUnitVector(cameraUp, 1);
229  Vec3d_transRotateSelf(cameraUp, plate->A_BI->rot);
230 
231  }
232  else if (cameraView == "side") {
233  // Make camera center a bit lower, so we use the screen better
234  cameraCenter[2] -= 0.4;
235  // Shift camera pos in x dir
236  cameraLocation[0] = 2.9;
237  cameraLocation[2] = 1.3;
238 
239  // Rotate to world frame
240  Vec3d_transformSelf(cameraLocation, plate->A_BI);
241 
242  }
243  else {
244  RMSG("Unsupported camera view: %s", cameraView.c_str());
245  return;
246  }
247 
248  // Apply the camera position
249  viewer->setCameraHomePosition(osg::Vec3d(cameraLocation[0], cameraLocation[1], cameraLocation[2]),
250  osg::Vec3d(cameraCenter[0], cameraCenter[1], cameraCenter[2]),
251  osg::Vec3d(cameraUp[0], cameraUp[1], cameraUp[2]));
252 #endif
253  }
254 
256  std::vector<std::string>& linesOut, double currentTime, const MatNd* obs, const MatNd* currentAction,
257  PhysicsBase* simulator, PhysicsParameterManager* physicsManager, ForceDisturber* forceDisturber) override
258  {
259  // Obtain simulator name
260  const char* simName = "None";
261  if (simulator != NULL) {
262  simName = simulator->getClassName();
263  }
264 
265  linesOut.emplace_back(string_format(
266  "physics engine: %s simulation time: %2.3f s",
267  simName, currentTime));
268 
269  unsigned int numPosCtrlJoints = 0;
270  unsigned int numTrqCtrlJoints = 0;
271  // Iterate over unconstrained joints
272  RCSGRAPH_TRAVERSE_JOINTS(graph) {
273  if (JNT->jacobiIndex != -1) {
274  if (JNT->ctrlType == RCSJOINT_CTRL_TYPE::RCSJOINT_CTRL_POSITION) {
275  numPosCtrlJoints++;
276  }
277  else if (JNT->ctrlType == RCSJOINT_CTRL_TYPE::RCSJOINT_CTRL_TORQUE) {
278  numTrqCtrlJoints++;
279  }
280  }
281  }
282  linesOut.emplace_back(
283  string_format("num joints: %d total, %d pos ctrl, %d trq ctrl", graph->nJ, numPosCtrlJoints,
284  numTrqCtrlJoints));
285 
286  linesOut.emplace_back(string_format(
287  "plate angles: [% 3.2f,% 3.2f] deg",
288  RCS_RAD2DEG(obs->ele[0]), RCS_RAD2DEG(obs->ele[1])));
289 
290  const double* distForce = forceDisturber->getLastForce();
291  linesOut.emplace_back(string_format(
292  "disturbances: [% 3.1f,% 3.1f,% 3.1f] N",
293  distForce[0], distForce[1], distForce[2]));
294 
295  if (physicsManager != NULL) {
296  // Get the parameters that are not stored in the Rcs graph
297  BodyParamInfo* ball_bpi = physicsManager->getBodyInfo("Ball");
298  double* com = ball_bpi->body->Inertia->org;
299  double ball_radius = ball_bpi->body->shape[0]->extents[0];
300  double slip = 0;
301  ball_bpi->material.getDouble("slip", slip);
302 
303  linesOut.emplace_back(string_format(
304  "ball mass: %2.2f kg ball radius: %2.3f cm",
305  ball_bpi->body->m, ball_radius*100));
306 
307  linesOut.emplace_back(string_format(
308  "ball friction: %1.2f ball rolling friction: %1.3f",
309  ball_bpi->material.getFrictionCoefficient(),
310  ball_bpi->material.getRollingFrictionCoefficient()/ball_radius));
311 
312  linesOut.emplace_back(string_format(
313  "ball slip: %3.1f rad/(Ns) CoM offset:[% 2.1f, % 2.1f, % 2.1f] mm",
314  slip, com[0]*1000, com[1]*1000, com[2]*1000));
315  }
316 
317  // Compute manipulability cost if available
318  auto amIK = actionModel->unwrap<ActionModelIK>();
319  if (amIK != NULL) {
320  double manipulability = amIK->getController()->computeManipulabilityCost()/initManipulability;
321  linesOut.emplace_back(string_format(
322  "manipulability: %10.8f ",
323  manipulability));
324  }
325  }
326 };
327 
328 // Register
330 
331 }
virtual bool getProperty(std::string &out, const char *property)=0
virtual bool getPropertyBool(const char *property, bool def=false)=0
virtual InitStateSetter * createInitStateSetter()
RcsBody * body
The body.
Definition: BodyParamInfo.h:64
void getHUDText(std::vector< std::string > &linesOut, double currentTime, const MatNd *obs, const MatNd *currentAction, PhysicsBase *simulator, PhysicsParameterManager *physicsManager, ForceDisturber *forceDisturber) override
void addParam(const char *bodyName, PhysicsParameterDescriptor *desc)
const double * getLastForce() const
virtual ActionModel * createActionModel()
virtual ObservationModel * createObservationModel()
virtual void initViewer(Rcs::Viewer *viewer)
virtual void populatePhysicsParameters(PhysicsParameterManager *manager)
BodyParamInfo * getBodyInfo(const char *bodyName)
static ExperimentConfigRegistration< ECBallOnPlate > RegBallOnPlate("BallOnPlate")
virtual ForceDisturber * createForceDisturber()
static OMPartial * fromMask(ObservationModel *wrapped, const std::vector< bool > &mask, bool exclude=false)
Definition: OMPartial.cpp:116
std::string string_format(const std::string &format, Args ... args)
Definition: string_format.h:45
PropertySource * properties
Property source (owned)
const AM * unwrap() const
Definition: ActionModel.h:142
const ControllerBase * getController() const
Definition: ActionModelIK.h:76
ActionModel * actionModel
Action model (pluggable)
PhysicsMaterial material
Material of the body&#39;s first shape.
Definition: BodyParamInfo.h:70
RcsGraph * graph
Graph description.