pxmlw6n2f/Gazebo_Distributed_TCP/gazebo/physics/Collision.cc

415 lines
10 KiB
C++

/*
* 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.
*
*/
#ifdef _WIN32
// Ensure that Winsock2.h is included before Windows.h, which can get
// pulled in by anybody (e.g., Boost).
#include <Winsock2.h>
#endif
#include <sstream>
#include "gazebo/msgs/msgs.hh"
#include "gazebo/msgs/MessageTypes.hh"
#include "gazebo/common/Events.hh"
#include "gazebo/common/Console.hh"
#include "gazebo/transport/TransportIface.hh"
#include "gazebo/transport/Publisher.hh"
#include "gazebo/physics/World.hh"
#include "gazebo/physics/ContactManager.hh"
#include "gazebo/physics/PhysicsIface.hh"
#include "gazebo/physics/Contact.hh"
#include "gazebo/physics/Shape.hh"
#include "gazebo/physics/SurfaceParams.hh"
#include "gazebo/physics/Model.hh"
#include "gazebo/physics/Link.hh"
#include "gazebo/physics/Collision.hh"
using namespace gazebo;
using namespace physics;
// Class used to initialize an sdf element pointer from "collision.sdf".
// This is then used in the Collision constructor to improve performance.
class SDFCollisionInitializer
{
// Constructor that create the collision sdf element
public: SDFCollisionInitializer()
{
sdf::initFile("collision.sdf", collisionSDF);
}
// Pointer the collision sdf element
public: sdf::ElementPtr collisionSDF = std::make_shared<sdf::Element>();
};
static SDFCollisionInitializer g_SDFInit;
//////////////////////////////////////////////////
Collision::Collision(LinkPtr _link)
: Entity(_link), maxContacts(1)
{
this->AddType(Base::COLLISION);
this->link = _link;
this->placeable = false;
this->sdf->Copy(g_SDFInit.collisionSDF);
this->collisionVisualId = physics::getUniqueId();
}
//////////////////////////////////////////////////
Collision::~Collision()
{
this->Fini();
}
//////////////////////////////////////////////////
void Collision::Fini()
{
if (this->requestPub)
{
msgs::Request *msg = msgs::CreateRequest("entity_delete",
this->GetScopedName()+"__COLLISION_VISUAL__");
this->requestPub->Publish(*msg, true);
}
this->link.reset();
this->shape.reset();
this->surface.reset();
Entity::Fini();
}
//////////////////////////////////////////////////
void Collision::Load(sdf::ElementPtr _sdf)
{
Entity::Load(_sdf);
this->maxContacts = _sdf->Get<unsigned int>("max_contacts");
this->SetMaxContacts(this->maxContacts);
if (this->sdf->HasElement("laser_retro"))
this->SetLaserRetro(this->sdf->Get<double>("laser_retro"));
this->SetRelativePose(this->sdf->Get<math::Pose>("pose"));
this->surface->Load(this->sdf->GetElement("surface"));
if (this->shape)
this->shape->Load(this->sdf->GetElement("geometry")->GetFirstElement());
else
gzwarn << "No shape has been specified. Error!!!\n";
}
//////////////////////////////////////////////////
void Collision::Init()
{
this->shape->Init();
this->SetRelativePose(
this->sdf->Get<math::Pose>("pose"));
}
//////////////////////////////////////////////////
void Collision::SetCollision(bool _placeable)
{
this->SetPlaceable(_placeable);
if (this->IsStatic())
{
this->SetCategoryBits(GZ_FIXED_COLLIDE);
this->SetCollideBits(~GZ_FIXED_COLLIDE);
}
else
{
// collide with all
this->SetCategoryBits(GZ_ALL_COLLIDE);
this->SetCollideBits(GZ_ALL_COLLIDE);
}
}
//////////////////////////////////////////////////
void Collision::SetPlaceable(const bool _placeable)
{
this->placeable = _placeable;
}
//////////////////////////////////////////////////
bool Collision::IsPlaceable() const
{
return this->placeable;
}
//////////////////////////////////////////////////
void Collision::SetLaserRetro(float _retro)
{
this->sdf->GetElement("laser_retro")->Set(_retro);
this->laserRetro = _retro;
}
//////////////////////////////////////////////////
float Collision::GetLaserRetro() const
{
return this->laserRetro;
}
//////////////////////////////////////////////////
LinkPtr Collision::GetLink() const
{
return this->link;
}
//////////////////////////////////////////////////
ModelPtr Collision::GetModel() const
{
return this->link->GetModel();
}
//////////////////////////////////////////////////
unsigned int Collision::GetShapeType() const
{
return this->shape->GetType();
}
//////////////////////////////////////////////////
void Collision::SetShape(ShapePtr _shape)
{
this->shape = _shape;
}
//////////////////////////////////////////////////
ShapePtr Collision::GetShape() const
{
return this->shape;
}
//////////////////////////////////////////////////
void Collision::SetScale(const math::Vector3 &_scale)
{
this->shape->SetScale(_scale);
}
//////////////////////////////////////////////////
math::Vector3 Collision::GetRelativeLinearVel() const
{
if (this->link)
return this->link->GetRelativeLinearVel();
else
return math::Vector3();
}
//////////////////////////////////////////////////
math::Vector3 Collision::GetWorldLinearVel() const
{
if (this->link)
return this->link->GetWorldLinearVel();
else
return math::Vector3();
}
//////////////////////////////////////////////////
math::Vector3 Collision::GetRelativeAngularVel() const
{
if (this->link)
return this->link->GetRelativeAngularVel();
else
return math::Vector3();
}
//////////////////////////////////////////////////
math::Vector3 Collision::GetWorldAngularVel() const
{
if (this->link)
return this->link->GetWorldAngularVel();
else
return math::Vector3();
}
//////////////////////////////////////////////////
math::Vector3 Collision::GetRelativeLinearAccel() const
{
if (this->link)
return this->link->GetRelativeLinearAccel();
else
return math::Vector3();
}
//////////////////////////////////////////////////
math::Vector3 Collision::GetWorldLinearAccel() const
{
if (this->link)
return this->link->GetWorldLinearAccel();
else
return math::Vector3();
}
//////////////////////////////////////////////////
math::Vector3 Collision::GetRelativeAngularAccel() const
{
if (this->link)
return this->link->GetRelativeAngularAccel();
else
return math::Vector3();
}
//////////////////////////////////////////////////
math::Vector3 Collision::GetWorldAngularAccel() const
{
if (this->link)
return this->link->GetWorldAngularAccel();
else
return math::Vector3();
}
//////////////////////////////////////////////////
void Collision::UpdateParameters(sdf::ElementPtr _sdf)
{
Entity::UpdateParameters(_sdf);
}
//////////////////////////////////////////////////
void Collision::FillMsg(msgs::Collision &_msg)
{
msgs::Set(_msg.mutable_pose(), this->GetRelativePose().Ign());
_msg.set_id(this->GetId());
_msg.set_name(this->GetScopedName());
_msg.set_laser_retro(this->GetLaserRetro());
this->shape->FillMsg(*_msg.mutable_geometry());
this->surface->FillMsg(*_msg.mutable_surface());
msgs::Set(this->visualMsg->mutable_pose(), this->GetRelativePose().Ign());
if (!this->HasType(physics::Base::SENSOR_COLLISION))
{
_msg.add_visual()->CopyFrom(*this->visualMsg);
// TODO remove the need to create the special collision visual msg and
// let the gui handle this.
_msg.add_visual()->CopyFrom(this->CreateCollisionVisual());
}
}
//////////////////////////////////////////////////
void Collision::ProcessMsg(const msgs::Collision &_msg)
{
if (_msg.id() != this->GetId())
{
gzerr << "Incorrect ID\n";
return;
}
this->SetName(_msg.name());
if (_msg.has_laser_retro())
this->SetLaserRetro(_msg.laser_retro());
if (_msg.has_pose())
{
this->link->SetEnabled(true);
this->SetRelativePose(msgs::ConvertIgn(_msg.pose()));
}
if (_msg.has_geometry())
{
this->link->SetEnabled(true);
this->shape->ProcessMsg(_msg.geometry());
}
if (_msg.has_surface())
{
this->link->SetEnabled(true);
this->surface->ProcessMsg(_msg.surface());
}
}
/////////////////////////////////////////////////
msgs::Visual Collision::CreateCollisionVisual()
{
msgs::Visual msg;
msg.set_name(this->GetScopedName()+"__COLLISION_VISUAL__");
// Put in a unique ID because this is a special visual.
msg.set_id(this->collisionVisualId);
msg.set_parent_name(this->parent->GetScopedName());
msg.set_parent_id(this->parent->GetId());
msg.set_is_static(this->IsStatic());
msg.set_cast_shadows(false);
msg.set_type(msgs::Visual::COLLISION);
msgs::Set(msg.mutable_pose(), this->GetRelativePose().Ign());
msg.mutable_material()->mutable_script()->add_uri(
"file://media/materials/scripts/gazebo.material");
msg.mutable_material()->mutable_script()->set_name(
"Gazebo/OrangeTransparent");
msgs::Geometry *geom = msg.mutable_geometry();
geom->CopyFrom(msgs::GeometryFromSDF(this->sdf->GetElement("geometry")));
return msg;
}
/////////////////////////////////////////////////
CollisionState Collision::GetState()
{
return this->state;
}
/////////////////////////////////////////////////
void Collision::SetState(const CollisionState &_state)
{
this->SetRelativePose(_state.GetPose());
}
/////////////////////////////////////////////////
void Collision::SetMaxContacts(unsigned int _maxContacts)
{
this->maxContacts = _maxContacts;
this->sdf->GetElement("max_contacts")->GetValue()->Set(_maxContacts);
}
/////////////////////////////////////////////////
unsigned int Collision::GetMaxContacts()
{
return this->maxContacts;
}
/////////////////////////////////////////////////
const math::Pose &Collision::GetWorldPose() const
{
// If true, compute a new world pose value.
//
if (this->worldPoseDirty)
{
this->worldPose = this->GetInitialRelativePose() +
this->link->GetWorldPose();
this->worldPoseDirty = false;
}
return this->worldPose;
}
/////////////////////////////////////////////////
void Collision::SetWorldPoseDirty()
{
// Tell the collision object that the next call to ::GetWorldPose should
// compute a new worldPose value.
this->worldPoseDirty = true;
}