/* * Copyright (C) 2012 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include "RubblePlugin.hh" using namespace gazebo; GZ_REGISTER_WORLD_PLUGIN(RubblePlugin) ///////////////////////////////////////////////// RubblePlugin::RubblePlugin() { } ///////////////////////////////////////////////// void RubblePlugin::Load(physics::WorldPtr _world, sdf::ElementPtr _sdf) { this->world = _world; math::Vector3 bottomRight = _sdf->Get("bottom_right"); math::Vector3 topLeft = _sdf->Get("top_left"); math::Vector3 minSize = _sdf->Get("min_size"); math::Vector3 maxSize = _sdf->Get("max_size"); double minMass = _sdf->Get("min_mass"); double maxMass = _sdf->Get("max_mass"); unsigned int count = _sdf->Get("count"); for (unsigned int i = 0; i < count; ++i) { int rubbleType = math::Rand::GetIntUniform(0, 1); double mass = math::Rand::GetDblUniform(minMass, maxMass); Obj obj; obj.pose.pos.x = math::Rand::GetDblUniform(bottomRight.x, topLeft.x); obj.pose.pos.y = math::Rand::GetDblUniform(bottomRight.y, topLeft.y); obj.pose.pos.z = math::Rand::GetDblUniform(bottomRight.z, topLeft.z); obj.pose.rot.SetFromEuler(math::Vector3( math::Rand::GetDblUniform(0.0, 3.1415), math::Rand::GetDblUniform(-0.1, 0.1), math::Rand::GetDblUniform(0.0, 3.1415))); obj.type = rubbleType; // Make a 2x4 if (rubbleType == 0) { // between 2 and 8 feet. obj.size.x = math::Rand::GetDblUniform(0.6096, 2.4384); // 4 inches obj.size.y = 0.1016; // 2 inches obj.size.z = 0.0508; } // Make a cinder block else if (rubbleType == 1) { // Standard US cinder block size obj.size.x = 0.2032; obj.size.y = 0.2032; obj.size.z = 0.4064; } // Make a cylinder else { obj.size.x = math::Rand::GetDblUniform(minSize.x, maxSize.x); obj.size.z = math::Rand::GetDblUniform(minSize.z, maxSize.z); obj.size.y = obj.size.x; } // Make sure the bottom of the rubble piece is above the bottomRight.z // This will prevent ground penetration. if (obj.pose.pos.z - obj.size.z * 0.5 < bottomRight.z) obj.pose.pos.z = bottomRight.z + obj.size.z * 0.5; std::ostringstream name; name << "rubble_" << i; if (rubbleType == 0) this->MakeBox(name.str(), obj.pose, obj.size, mass); else if (rubbleType == 1) this->MakeCinderBlock(name.str(), obj.pose, obj.size, mass); /*else this->MakeCylinder(name.str(), obj.pos, obj.size, mass); */ // Disable compound objects for now. // bool merged = false; /* std::vector objects; std::vector::iterator iter; for (iter = objects.begin(); iter != objects.end(); ++iter) { bool x = fabs(obj.pos.x - (*iter).pos.x) <= (*iter).size.x * 0.5 + obj.size.x * 0.5; bool y = fabs(obj.pos.y - (*iter).pos.y) <= (*iter).size.y * 0.5 + obj.size.y * 0.5; bool z = fabs(obj.pos.z - (*iter).pos.z) <= (*iter).size.z * 0.5 + obj.size.z * 0.5; if (x && y && z) { (*iter).objects.push_back(obj); std::vector::iterator objIter; (*iter).pos.Set(0, 0, 0); math::Vector3 min, max; min.x = min.y = min.z = std::numeric_limits::max(); max.x = max.y = max.z = std::numeric_limits::min(); for (objIter = (*iter).objects.begin(); objIter != (*iter).objects.end(); ++objIter) { (*iter).pos += (*objIter).pos; min.x = std::min(min.x, (*objIter).pos.x - (*objIter).size.x * 0.5); min.y = std::min(min.y, (*objIter).pos.y - (*objIter).size.y * 0.5); min.z = std::min(min.z, (*objIter).pos.z - (*objIter).size.z * 0.5); max.x = std::max(max.x, (*objIter).pos.x + (*objIter).size.x * 0.5); max.y = std::max(max.y, (*objIter).pos.y + (*objIter).size.y * 0.5); max.z = std::max(max.z, (*objIter).pos.z + (*objIter).size.z * 0.5); } // Recalculate the middle position of the compound object (*iter).pos /= (*iter).objects.size(); // Recalculate the total size of the compound object (*iter).size.Set(max.x - min.x, max.y - min.y, max.z - min.z); merged = true; break; } } if (!merged) { RubblePlugin::CompoundObj co; co.pos = obj.pos; co.size = obj.size; co.objects.push_back(obj); objects.push_back(co); }*/ } // Disable compound objects for now. /* int i =0; for (iter = objects.begin(); iter != objects.end(); ++iter, ++i) { std::ostringstream name; name << "rubble_" << i; this->MakeCompound(name.str(), *iter); }*/ } ///////////////////////////////////////////////// void RubblePlugin::Init() { } ///////////////////////////////////////////////// void RubblePlugin::MakeCinderBlock(const std::string &_name, math::Pose &_pose, math::Vector3 &_size, double _mass) { std::ostringstream newModelStr; float sx = _size.x; float sy = _size.y; float sz = _size.z; newModelStr << "" "" "" << _pose << "" "" "" "0.01" "0.01" "" "" << _mass << "" "" "" << (1.0/12.0) * _mass * (sy*sy + sz*sz) << "" "" << (1.0/12.0) * _mass * (sz*sz + sx*sx) << "" "" << (1.0/12.0) * _mass * (sx*sx + sy*sy) << "" "" << 0.0 << "" "" << 0.0 << "" "" << 0.0 << "" "" "" "" "" "" << _size << "" "" "" "" "" "" << _size << "" "" "" "" "" ""; this->world->InsertModelString(newModelStr.str()); } ///////////////////////////////////////////////// void RubblePlugin::MakeBox(const std::string &_name, math::Pose &_pose, math::Vector3 &_size, double _mass) { std::ostringstream newModelStr; float sx = _size.x; float sy = _size.y; float sz = _size.z; newModelStr << "" "" "true" "" << _pose << "" "" "" "0.01" "0.01" "" "" << _mass << "" "" "" << (1.0/12.0) * _mass * (sy*sy + sz*sz) << "" "" << (1.0/12.0) * _mass * (sz*sz + sx*sx) << "" "" << (1.0/12.0) * _mass * (sx*sx + sy*sy) << "" "" << 0.0 << "" "" << 0.0 << "" "" << 0.0 << "" "" "" "" "" "" << _size << "" "" "" "" "" "" << _size << "" "" "" "" "" ""; this->world->InsertModelString(newModelStr.str()); } ///////////////////////////////////////////////// /*void RubblePlugin::MakeCylinder(const std::string &_name, math::Vector3 &_pos, math::Vector3 &_size, double _mass) { std::ostringstream newModelStr; float r = _size.x * 0.5; float h = _size.z; newModelStr << "" "" "" << _pos << " 0 0 0" "" "" "0.01" "0.01" "" "" << _mass << "" "" "" << (1.0/12.0) * _mass * (3*r*r + h*h) << "" "" << (1.0/12.0) * _mass * (3*r*r + h*h) << "" "" << (1.0/2.0) * _mass * r * r << "" "" << 0.0 << "" "" << 0.0 << "" "" << 0.0 << "" "" "" "" "" "" << r << "" "" << h << "" "" "" "" "" "" << r << "" "" << h << "" "" "" "" "" ""; this->world->InsertModelString(newModelStr.str()); }*/ ///////////////////////////////////////////////// /*void RubblePlugin::MakeCompound(const std::string &_name, CompoundObj &_obj) { std::ostringstream newModelStr, geomStr, inertiaStr; newModelStr << "" << "" << " " << _obj.pos << " 0 0 0" << " "; float mass = 0.1; inertiaStr << "" << mass << ""; int i = 0; for (std::vector::iterator iter = _obj.objects.begin(); iter != _obj.objects.end(); ++iter, ++i) { if ((*iter).type == 0) { float h = (*iter).size.z; float w = (*iter).size.y; float d = (*iter).size.x; inertiaStr << "" << (1.0/12.0) * mass * (h*h + d*d) << "" << "" << (1.0/12.0) * mass * (w*w + d*d) << "" << "" << (1.0/12.0) * mass * (w*w + h*h) << ""; geomStr << "" << (*iter).size << ""; } else if ((*iter).type == 1) { float radius = (*iter).size.x * 0.5; inertiaStr << "" << (2.0/5.0)* mass * radius << "" << "" << (2.0/5.0)* mass * radius << "" << "" << (2.0/5.0)* mass * radius << ""; geomStr << "" << radius << ""; } else { float r = (*iter).size.x * 0.5; float h = (*iter).size.z; inertiaStr << "" << (1.0/12.0) * mass * (3*r*r + h*h) << "" << "" << (1.0/12.0) * mass * (3*r*r + h*h) << "" << "" << (1.0/12.0) * mass * r * r << ""; geomStr << "" << r << "" << "" << h << ""; } inertiaStr << "" << 0.0 << "" << "" << 0.0 << "" << "" << 0.0 << "" << ""; newModelStr << inertiaStr.str(); newModelStr << " " << " " << (*iter).pose << "" << " " << " " << geomStr.str() << " " << " " << " " << " " << (*iter).pose << "" << " " << " " << geomStr.str() << " " << " "; } newModelStr << " " << "" << ""; this->world->InsertModelString(newModelStr.str()); }*/