pinocchio  UNKNOWN
lua.cpp
1 //
2 // Copyright (c) 2015-2016 CNRS
3 //
4 // This file is part of Pinocchio
5 // Pinocchio is free software: you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation, either version
8 // 3 of the License, or (at your option) any later version.
9 //
10 // Pinocchio is distributed in the hope that it will be
11 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Lesser Public License for more details. You should have
14 // received a copy of the GNU Lesser General Public License along with
15 // Pinocchio If not, see
16 // <http://www.gnu.org/licenses/>.
17 
18 #include "pinocchio/parsers/lua/lua_tables.hpp"
19 #include "pinocchio/parsers/lua.hpp"
20 
21 #include <lua.hpp>
22 #include <iostream>
23 #include <map>
24 #include <sstream>
25 
26 #include "pinocchio/spatial/se3.hpp"
27 #include "pinocchio/spatial/motion.hpp"
28 #include "pinocchio/spatial/inertia.hpp"
29 #include "pinocchio/multibody/model.hpp"
30 
31 typedef se3::SE3::Vector3 Vector3;
32 typedef se3::SE3::Matrix3 Matrix3;
33 
34 template<> Vector3 LuaTableNode::getDefault<Vector3> (const Vector3 & default_value)
35 {
36  Vector3 result (default_value);
37 
38  if (stackQueryValue()) {
39  LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
40 
41  if (vector_table.length() != 3) {
42  std::cerr << "LuaModel Error: invalid 3d vector!" << std::endl;
43  abort();
44  }
45 
46  result[0] = vector_table[1];
47  result[1] = vector_table[2];
48  result[2] = vector_table[3];
49  }
50 
51  stackRestore();
52 
53  return result;
54 }
55 
56 template<> Matrix3 LuaTableNode::getDefault<Matrix3> (const Matrix3 & default_value)
57 {
58  Matrix3 result (default_value);
59 
60  if (stackQueryValue()) {
61  LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
62 
63  if (vector_table.length() != 3) {
64  std::cerr << "LuaModel Error: invalid 3d matrix!" << std::endl;
65  abort();
66  }
67 
68  if (vector_table[1].length() != 3
69  || vector_table[2].length() != 3
70  || vector_table[3].length() != 3) {
71  std::cerr << "LuaModel Error: invalid 3d matrix!" << std::endl;
72  abort();
73  }
74 
75  result(0,0) = vector_table[1][1];
76  result(0,1) = vector_table[1][2];
77  result(0,2) = vector_table[1][3];
78 
79  result(1,0) = vector_table[2][1];
80  result(1,1) = vector_table[2][2];
81  result(1,2) = vector_table[2][3];
82 
83  result(2,0) = vector_table[3][1];
84  result(2,1) = vector_table[3][2];
85  result(2,2) = vector_table[3][3];
86  }
87 
88  stackRestore();
89 
90  return result;
91 }
92 
93 template<> se3::SE3 LuaTableNode::getDefault<se3::SE3> (const se3::SE3 & default_value)
94 {
95  se3::SE3 result (default_value);
96 
97  if (stackQueryValue()) {
98  LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
99 
100  result.translation() = vector_table["r"].getDefault<Vector3> (Vector3::Zero (3));
101  result.rotation().transpose() = vector_table["E"].getDefault<Matrix3> (Matrix3::Identity (3,3));
102  }
103 
104  stackRestore();
105 
106  return result;
107 }
108 
109 template<> se3::Inertia LuaTableNode::getDefault<se3::Inertia> (const se3::Inertia & default_value)
110 {
111  se3::Inertia result (default_value);
112 
113  if (stackQueryValue()) {
114  LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
115 
116  double mass = 0.;
117  Vector3 com;
118  Matrix3 inertia_matrix;
119 
120  mass = vector_table["mass"];
121  com = vector_table["com"].getDefault<Vector3> (Vector3::Zero ());
122  inertia_matrix = vector_table["inertia"].getDefault<Matrix3> (Matrix3::Identity ());
123 
124  result = se3::Inertia (mass, com, inertia_matrix);
125  }
126 
127  stackRestore();
128 
129  return result;
130 }
131 
132 namespace se3
133 {
134  namespace lua
135  {
136 
137  template<typename JointModel>
138  Model::JointIndex addJointAndBody(Model & model, const JointModelBase<JointModel> & jmodel, const Model::JointIndex parent_id,
139  const SE3 & joint_placement, const std::string & joint_name, const Inertia & Y, const std::string & body_name)
140  {
141  Model::JointIndex idx;
142 
143  idx = model.addJoint(parent_id,jmodel,
144  joint_placement,joint_name);
145  model.addJointFrame(idx);
146  model.appendBodyToJoint(idx,Y);
147  model.addBodyFrame(body_name, idx);
148 
149  return idx;
150  }
151 
152  bool LuaModelReadFromTable (LuaTable & model_table, Model & model, bool freeFlyer, bool verbose)
153  {
154  typedef std::map<std::string, Model::Index> mapStringIndex_t;
155  mapStringIndex_t body_table_id_map;
156  mapStringIndex_t fixed_body_table_id_map;
157 
158  typedef std::map<std::string, SE3> mapStringSE3_t;
159  mapStringSE3_t fixed_placement_map;
160 
161  if (model_table["gravity"].exists())
162  {
163  model.gravity.linear() = model_table["gravity"].get<Vector3> ();
164 
165  if (verbose)
166  std::cout << "gravity = " << model.gravity.linear().transpose() << std::endl;
167  }
168 
169  if (! model_table["frames"].exists())
170  {
171  std::cerr << "Frames table missing from model table - Abort" << std::endl;
172  abort();
173  }
174 
175  size_t frame_count = model_table["frames"].length();
176 
177  body_table_id_map["ROOT"] = 0;
178 
179  for (int i = 1; i <= (int) frame_count; i++) {
180 
181  std::stringstream body_name_default;
182  body_name_default << "body " << i;
183  std::string body_name = model_table["frames"][i]["name"].getDefault<std::string> (body_name_default.str());
184 
185  std::string parent_name;
186  if (model_table["frames"][i]["parent"].exists ())
187  {
188  parent_name = model_table["frames"][i]["parent"].get<std::string> ();
189  }
190  else if (i == 1) // first body of the tree
191  {
192  parent_name = "ROOT";
193  }
194  else // no parent defined
195  {
196  std::cerr << "Parent not defined for frame " << i << "." << std::endl;
197  abort();
198  }
199 
200  Model::JointIndex parent_id;
201  SE3 fixed_placement_offset (SE3::Identity());;
202 
203  if (body_table_id_map.find (parent_name) != body_table_id_map.end ())
204  {
205  parent_id = body_table_id_map[parent_name];
206  }
207  else if (fixed_body_table_id_map.find(parent_name) != fixed_body_table_id_map.end ()) // the parent is fixed in the kinematic tree
208  {
209  parent_id = fixed_body_table_id_map[parent_name];
210  fixed_placement_offset = fixed_placement_map[parent_name];
211  }
212  else
213  {
214  std::cerr << parent_name << " is not in the tree." << std::endl;
215  abort ();
216  }
217 
218  std::stringstream joint_name_default;
219  joint_name_default << "joint " << i;
220  std::string joint_name = model_table["frames"][i]["joint_name"].getDefault<std::string> (joint_name_default.str());
221 
222  SE3 joint_placement = model_table["frames"][i]["joint_frame"].getDefault<SE3> (SE3::Identity ());
223  SE3 global_placement (fixed_placement_offset * joint_placement); // placement due to the existence of fixed bodies
224 
225  if (! model_table["frames"][i]["body"].exists()) {
226  std::cerr << "body field not defined for frame " << i << "." << std::endl;
227  abort();
228  }
229 
230  Inertia Y = model_table["frames"][i]["body"].getDefault<Inertia> (Inertia::Identity ());
231 
232  std::string joint_type;
233  if (model_table["frames"][i]["joint"].exists())
234  {
235  if (model_table["frames"][i]["joint"].length() == 0)
236  joint_type = "JointTypeFixed";
237  else if (model_table["frames"][i]["joint"].length() == 1)
238  joint_type = model_table["frames"][i]["joint"][1].getDefault<std::string> ("");
239  else
240  {
241  joint_type = model_table["frames"][i]["joint"][1].getDefault<std::string> ("");
242  std::cerr << "Joint compouned not yet implemented. Take only the first joint." << std::endl;
243  }
244  }
245  else if (i == 1) // first body of the tree
246  {
247  if (freeFlyer)
248  joint_type = "JointTypeFloatbase";
249  else
250  {
251  std::cerr << "The first segment is defined without any definition of joint type relatily to the world." << std::endl;
252  abort ();
253  }
254  }
255  else
256  {
257  std::cerr << "joint field not defined for frame " << i << "." << std::endl;
258  abort();
259  }
260 
261  Model::JointIndex joint_id;
262  if (joint_type == "JointTypeRevoluteX")
263  {
264  joint_id = addJointAndBody(model,JointModelRX(),parent_id,global_placement,joint_name,Y,body_name);
265  }
266  else if (joint_type == "JointTypeRevoluteY")
267  {
268  joint_id = addJointAndBody(model,JointModelRY(),parent_id,global_placement,joint_name,Y,body_name);
269  }
270  else if (joint_type == "JointTypeRevoluteZ")
271  {
272  joint_id = addJointAndBody(model,JointModelRZ(),parent_id,global_placement,joint_name,Y,body_name);
273  }
274  else if (joint_type == "JointTypePrismaticX")
275  {
276  joint_id = addJointAndBody(model,JointModelPX(),parent_id,global_placement,joint_name,Y,body_name);
277  }
278  else if (joint_type == "JointTypePrismaticY")
279  {
280  joint_id = addJointAndBody(model,JointModelPY(),parent_id,global_placement,joint_name,Y,body_name);
281  }
282  else if (joint_type == "JointTypePrismaticZ")
283  {
284  joint_id = addJointAndBody(model,JointModelPZ(),parent_id,global_placement,joint_name,Y,body_name);
285  }
286  else if (joint_type == "JointTypeFloatingBase" || joint_type == "JointTypeFloatbase")
287  {
288  joint_id = addJointAndBody(model,JointModelFreeFlyer(),parent_id,global_placement,joint_name,Y,body_name);
289  }
290  else if (joint_type == "JointTypeSpherical")
291  {
292  joint_id = addJointAndBody(model,JointModelSpherical(),parent_id,global_placement,joint_name,Y,body_name);
293  }
294  else if (joint_type == "JointTypeEulerZYX")
295  {
296  joint_id = addJointAndBody(model,JointModelSphericalZYX(),parent_id,global_placement,joint_name,Y,body_name);
297  }
298  else if (joint_type == "JointTypeFixed")
299  {
300  model.appendBodyToJoint(parent_id, Y, global_placement);
301  // TODO Why not
302  // model.addBodyFrame(body_name, parent_id, global_placement);
303  // ???
304  model.addBodyFrame(randomStringGenerator(8), parent_id, global_placement);
305 
306  joint_id = (Model::JointIndex)model.njoints;
307 
308  fixed_body_table_id_map[body_name] = parent_id;
309  fixed_placement_map[body_name] = global_placement;
310  }
311  else
312  {
313  std::cerr << joint_type << " is not supported.." << std::endl;
314  abort ();
315  }
316 
317  body_table_id_map[body_name] = joint_id;
318 
319  if (verbose) {
320  std::cout << "==== Added Body ====" << std::endl;
321  std::cout << " joint name : " << joint_type << std::endl;
322  std::cout << " joint id : " << joint_id << std::endl;
323  std::cout << " joint parent id : " << parent_id << std::endl;
324  std::cout << " joint placement (wrt its parent):\n" << joint_placement << std::endl;
325  std::cout << " joint type : " << joint_type << std::endl;
326  std::cout << " body name : " << body_name << std::endl;
327  std::cout << " body inertia:\n" << Y << std::endl;
328  }
329  }
330 
331  return true;
332  }
333 
334  Model buildModel (const std::string & filename, bool freeFlyer, bool verbose)
335  {
336  Model model;
337 
338  LuaTable model_table = LuaTable::fromFile (filename.c_str ());
339  LuaModelReadFromTable (model_table, model, freeFlyer, verbose);
340 
341  return model;
342  }
343 
344  } // namespace lua
345 
346 } // namespace se3
std::string randomStringGenerator(const int len)
Generate a random string composed of alphanumeric symbols of a given length.