#include "rbdl/rbdl.h" #include "luamodel.h" #include #include #include "luatables.h" extern "C" { #include #include #include } using namespace std; using namespace RigidBodyDynamics; using namespace RigidBodyDynamics::Math; template<> Vector3d LuaTableNode::getDefault(const Vector3d &default_value) { Vector3d result = default_value; if (stackQueryValue()) { LuaTable vector_table = LuaTable::fromLuaState (luaTable->L); if (vector_table.length() != 3) { cerr << "LuaModel Error: invalid 3d vector!" << endl; abort(); } result[0] = vector_table[1]; result[1] = vector_table[2]; result[2] = vector_table[3]; } stackRestore(); return result; } template<> SpatialVector LuaTableNode::getDefault( const SpatialVector &default_value ) { SpatialVector result = default_value; if (stackQueryValue()) { LuaTable vector_table = LuaTable::fromLuaState (luaTable->L); if (vector_table.length() != 6) { cerr << "LuaModel Error: invalid 6d vector!" << endl; abort(); } result[0] = vector_table[1]; result[1] = vector_table[2]; result[2] = vector_table[3]; result[3] = vector_table[4]; result[4] = vector_table[5]; result[5] = vector_table[6]; } stackRestore(); return result; } template<> Matrix3d LuaTableNode::getDefault(const Matrix3d &default_value) { Matrix3d result = default_value; if (stackQueryValue()) { LuaTable vector_table = LuaTable::fromLuaState (luaTable->L); if (vector_table.length() != 3) { cerr << "LuaModel Error: invalid 3d matrix!" << endl; abort(); } if (vector_table[1].length() != 3 || vector_table[2].length() != 3 || vector_table[3].length() != 3) { cerr << "LuaModel Error: invalid 3d matrix!" << endl; abort(); } result(0,0) = vector_table[1][1]; result(0,1) = vector_table[1][2]; result(0,2) = vector_table[1][3]; result(1,0) = vector_table[2][1]; result(1,1) = vector_table[2][2]; result(1,2) = vector_table[2][3]; result(2,0) = vector_table[3][1]; result(2,1) = vector_table[3][2]; result(2,2) = vector_table[3][3]; } stackRestore(); return result; } template<> SpatialTransform LuaTableNode::getDefault( const SpatialTransform &default_value ) { SpatialTransform result = default_value; if (stackQueryValue()) { LuaTable vector_table = LuaTable::fromLuaState (luaTable->L); result.r = vector_table["r"].getDefault(Vector3d::Zero(3)); result.E = vector_table["E"].getDefault(Matrix3d::Identity (3,3)); } stackRestore(); return result; } template<> Joint LuaTableNode::getDefault(const Joint &default_value) { Joint result = default_value; if (stackQueryValue()) { LuaTable vector_table = LuaTable::fromLuaState (luaTable->L); int joint_dofs = vector_table.length(); if (joint_dofs == 1) { string dof_string = vector_table[1].getDefault(""); if (dof_string == "JointTypeSpherical") { stackRestore(); return Joint(JointTypeSpherical); } else if (dof_string == "JointTypeEulerZYX") { stackRestore(); return Joint(JointTypeEulerZYX); } if (dof_string == "JointTypeEulerXYZ") { stackRestore(); return Joint(JointTypeEulerXYZ); } if (dof_string == "JointTypeEulerYXZ") { stackRestore(); return Joint(JointTypeEulerYXZ); } if (dof_string == "JointTypeTranslationXYZ") { stackRestore(); return Joint(JointTypeTranslationXYZ); } } if (joint_dofs > 0) { if (vector_table[1].length() != 6) { cerr << "LuaModel Error: invalid joint motion subspace description at " << this->keyStackToString() << endl; abort(); } } switch (joint_dofs) { case 0: result = Joint(JointTypeFixed); break; case 1: result = Joint (vector_table[1].get()); break; case 2: result = Joint( vector_table[1].get(), vector_table[2].get() ); break; case 3: result = Joint( vector_table[1].get(), vector_table[2].get(), vector_table[3].get() ); break; case 4: result = Joint( vector_table[1].get(), vector_table[2].get(), vector_table[3].get(), vector_table[4].get() ); break; case 5: result = Joint( vector_table[1].get(), vector_table[2].get(), vector_table[3].get(), vector_table[4].get(), vector_table[5].get() ); break; case 6: result = Joint( vector_table[1].get(), vector_table[2].get(), vector_table[3].get(), vector_table[4].get(), vector_table[5].get(), vector_table[6].get() ); break; default: cerr << "Invalid number of DOFs for joint." << endl; abort(); break; } } stackRestore(); return result; } template<> Body LuaTableNode::getDefault(const Body &default_value) { Body result = default_value; if (stackQueryValue()) { LuaTable vector_table = LuaTable::fromLuaState (luaTable->L); double mass = 0.; Vector3d com (Vector3d::Zero(3)); Matrix3d inertia (Matrix3d::Identity(3,3)); mass = vector_table["mass"]; com = vector_table["com"].getDefault(com); inertia = vector_table["inertia"].getDefault(inertia); result = Body (mass, com, inertia); } stackRestore(); return result; } namespace RigidBodyDynamics { namespace Addons { bool LuaModelReadFromTable (LuaTable &model_table, Model *model, bool verbose); bool LuaModelReadConstraintsFromTable ( LuaTable &model_table, Model *model, std::vector& constraint_sets, const std::vector& constraint_set_names, bool verbose ); typedef map StringIntMap; StringIntMap body_table_id_map; RBDL_DLLAPI bool LuaModelReadFromLuaState (lua_State* L, Model* model, bool verbose) { assert (model); LuaTable model_table = LuaTable::fromLuaState (L); return LuaModelReadFromTable (model_table, model, verbose); } RBDL_DLLAPI bool LuaModelReadFromFile (const char* filename, Model* model, bool verbose) { if(!model) { std::cerr << "Model not provided." << std::endl; assert(false); abort(); } LuaTable model_table = LuaTable::fromFile (filename); return LuaModelReadFromTable (model_table, model, verbose); } RBDL_DLLAPI std::vector LuaModelGetConstraintSetNames(const char* filename) { std::vector result; LuaTable model_table = LuaTable::fromFile (filename); std::vector constraint_keys; if (model_table["constraint_sets"].exists()) { constraint_keys = model_table["constraint_sets"].keys(); } if (constraint_keys.size() == 0) { return result; } for (size_t ci = 0; ci < constraint_keys.size(); ++ci) { if (constraint_keys[ci].type != LuaKey::String) { std::cerr << "Invalid constraint found in model.constraint_sets: no constraint set name was specified!" << std::endl; abort(); } result.push_back(constraint_keys[ci].string_value); } return result; } RBDL_DLLAPI bool LuaModelReadFromFileWithConstraints ( const char* filename, Model* model, std::vector& constraint_sets, const std::vector& constraint_set_names, bool verbose ) { if(!model) { std::cerr << "Model not provided." << std::endl; assert(false); abort(); } if(constraint_sets.size() != constraint_set_names.size()) { std::cerr << "Number of constraint sets different from the number of \ constraint set names." << std::endl; assert(false); abort(); } LuaTable model_table = LuaTable::fromFile (filename); bool modelLoaded = LuaModelReadFromTable (model_table, model, verbose); bool constraintsLoaded = LuaModelReadConstraintsFromTable (model_table, model , constraint_sets, constraint_set_names, verbose); for(size_t i = 0; i < constraint_sets.size(); ++i) { constraint_sets[i].Bind(*model); } return modelLoaded && constraintsLoaded; } bool LuaModelReadFromTable (LuaTable &model_table, Model* model, bool verbose) { if (model_table["gravity"].exists()) { model->gravity = model_table["gravity"].get(); if (verbose) cout << "gravity = " << model->gravity.transpose() << endl; } int frame_count = model_table["frames"].length(); body_table_id_map["ROOT"] = 0; for (int i = 1; i <= frame_count; i++) { if (!model_table["frames"][i]["parent"].exists()) { cerr << "Parent not defined for frame " << i << "." << endl; abort(); } string body_name = model_table["frames"][i]["name"].getDefault(""); string parent_name = model_table["frames"][i]["parent"].get(); unsigned int parent_id = body_table_id_map[parent_name]; SpatialTransform joint_frame = model_table["frames"][i]["joint_frame"].getDefault(SpatialTransform()); Joint joint = model_table["frames"][i]["joint"].getDefault(Joint(JointTypeFixed)); Body body = model_table["frames"][i]["body"].getDefault(Body()); unsigned int body_id = model->AddBody (parent_id, joint_frame, joint, body, body_name); body_table_id_map[body_name] = body_id; if (verbose) { cout << "==== Added Body ====" << endl; cout << " body_name : " << body_name << endl; cout << " body id : " << body_id << endl; cout << " parent_id : " << parent_id << endl; cout << " joint dofs : " << joint.mDoFCount << endl; for (unsigned int j = 0; j < joint.mDoFCount; j++) { cout << " " << j << ": " << joint.mJointAxes[j].transpose() << endl; } cout << " joint_frame: " << joint_frame << endl; } } return true; } bool LuaModelReadConstraintsFromTable ( LuaTable &model_table, Model *model, std::vector& constraint_sets, const std::vector& constraint_set_names, bool verbose ) { for(size_t i = 0; i < constraint_set_names.size(); ++i) { if (verbose) { std::cout << "==== Constraint Set: " << constraint_set_names[i] << std::endl; } if(!model_table["constraint_sets"][constraint_set_names[i].c_str()] .exists()) { cerr << "Constraint set not existing: " << constraint_set_names[i] << "." << endl; assert(false); abort(); } size_t num_constraints = model_table["constraint_sets"] [constraint_set_names[i].c_str()] .length(); for(size_t ci = 0; ci < num_constraints; ++ci) { if (verbose) { std::cout << "== Constraint " << ci << "/" << num_constraints << " ==" << std::endl; } if(!model_table["constraint_sets"] [constraint_set_names[i].c_str()][ci + 1]["constraint_type"].exists()) { cerr << "constraint_type not specified." << endl; assert(false); abort(); } string constraintType = model_table["constraint_sets"] [constraint_set_names[i].c_str()][ci + 1]["constraint_type"] .getDefault(""); std::string constraint_name = model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["name"].getDefault(""); if(constraintType == "contact") { if(!model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["body"].exists()) { cerr << "body not specified." << endl; assert(false); abort(); } constraint_sets[i].AddContactConstraint (model->GetBodyId(model_table["constraint_sets"] [constraint_set_names[i].c_str()][ci + 1]["body"] .getDefault("").c_str()) , model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["point"].getDefault(Vector3d::Zero()) , model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["normal"].getDefault(Vector3d::Zero()) , model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["name"].getDefault("").c_str() , model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["normal_acceleration"].getDefault(0.)); if(verbose) { cout << " type = contact" << endl; cout << " name = " << constraint_name << std::endl; cout << " body = " << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["body"].getDefault("") << endl; cout << " body point = " << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["point"].getDefault(Vector3d::Zero()).transpose() << endl; cout << " world normal = " << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["normal"].getDefault(Vector3d::Zero()).transpose() << endl; cout << " normal acceleration = " << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["normal_acceleration"].getDefault(0.) << endl; } } else if(constraintType == "loop") { if(!model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["predecessor_body"].exists()) { cerr << "predecessor_body not specified." << endl; assert(false); abort(); } if(!model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["successor_body"].exists()) { cerr << "successor_body not specified." << endl; assert(false); abort(); } // Add the loop constraint as a non-stablized constraint and compute // and set the actual stabilization cofficients for the Baumgarte // stabilization afterwards if enabled. unsigned int constraint_id; constraint_id = constraint_sets[i].AddLoopConstraint(model->GetBodyId (model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["predecessor_body"].getDefault("").c_str()) , model->GetBodyId(model_table["constraint_sets"] [constraint_set_names[i].c_str()][ci + 1]["successor_body"] .getDefault("").c_str()) , model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["predecessor_transform"].getDefault(SpatialTransform()) , model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["successor_transform"].getDefault(SpatialTransform()) , model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["axis"].getDefault(SpatialVector::Zero()) , false , 0.0 , constraint_name.c_str()); bool enable_stabilization = model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["enable_stabilization"].getDefault(false); double stabilization_parameter = 0.0; if (enable_stabilization) { stabilization_parameter = model_table["constraint_sets"][constraint_set_names[i].c_str()][ci + 1] ["stabilization_parameter"].getDefault(0.1); if (stabilization_parameter <= 0.0) { std::cerr << "Invalid stabilization parameter: " << stabilization_parameter << " must be > 0.0" << std::endl; abort(); } double stabilization_coefficient = 1.0 / stabilization_parameter; constraint_sets[i].baumgarteParameters[i] = Vector2d( stabilization_coefficient, stabilization_coefficient); } if(verbose) { cout << " type = loop" << endl; cout << " name = " << constraint_name << std::endl; cout << " predecessor body = " << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["predecessor_body"].getDefault("") << endl; cout << " successor body = " << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["successor_body"].getDefault("") << endl; cout << " predecessor body transform = " << endl << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["predecessor_transform"] .getDefault(SpatialTransform()) << endl; cout << " successor body transform = " << endl << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["successor_transform"] .getDefault(SpatialTransform()) << endl; cout << " constraint axis (in predecessor frame) = " << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["axis"].getDefault(SpatialVector::Zero()) .transpose() << endl; cout << " enable_stabilization = " << enable_stabilization << endl; if (enable_stabilization) { cout << " stabilization_parameter = " << stabilization_parameter << endl; } cout << " constraint name = " << model_table["constraint_sets"][constraint_set_names[i].c_str()] [ci + 1]["name"].getDefault("").c_str() << endl; } } else { cerr << "Invalid constraint type: " << constraintType << endl; abort(); } } } return true; } } }