pxmlw6n2f/Gazebo_Distributed_MPI/gazebo/sensors/LogicalCameraSensor.cc

216 lines
6.3 KiB
C++

/*
* Copyright (C) 2015 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 <boost/algorithm/string.hpp>
#include "gazebo/transport/transport.hh"
#include "gazebo/msgs/msgs.hh"
#include "gazebo/physics/World.hh"
#include "gazebo/physics/Model.hh"
#include "gazebo/sensors/SensorFactory.hh"
#include "gazebo/sensors/LogicalCameraSensorPrivate.hh"
#include "gazebo/sensors/LogicalCameraSensor.hh"
using namespace gazebo;
using namespace sensors;
GZ_REGISTER_STATIC_SENSOR("logical_camera", LogicalCameraSensor)
//////////////////////////////////////////////////
LogicalCameraSensor::LogicalCameraSensor()
: Sensor(sensors::OTHER),
dataPtr(new LogicalCameraSensorPrivate)
{
}
//////////////////////////////////////////////////
LogicalCameraSensor::~LogicalCameraSensor()
{
}
//////////////////////////////////////////////////
void LogicalCameraSensor::Load(const std::string &_worldName,
sdf::ElementPtr _sdf)
{
Sensor::Load(_worldName, _sdf);
// Get a pointer to the parent link. This will be used to adjust the
// orientation of the logical camera.
physics::EntityPtr parentEntity =
this->world->GetEntity(this->ParentName());
this->dataPtr->parentLink =
boost::dynamic_pointer_cast<physics::Link>(parentEntity);
// Store parent model's name for use in the UpdateImpl function.
this->dataPtr->modelName =
this->dataPtr->parentLink->GetModel()->GetScopedName();
}
//////////////////////////////////////////////////
std::string LogicalCameraSensor::GetTopic() const
{
return this->Topic();
}
//////////////////////////////////////////////////
std::string LogicalCameraSensor::Topic() const
{
std::string topicName = Sensor::Topic();
if (topicName.empty())
{
topicName = "~/" + this->ParentName() + "/" + this->Name() + "/models";
boost::replace_all(topicName, "::", "/");
}
return topicName;
}
//////////////////////////////////////////////////
void LogicalCameraSensor::Load(const std::string &_worldName)
{
Sensor::Load(_worldName);
// Create publisher of the logical camera images
this->dataPtr->pub =
this->node->Advertise<msgs::LogicalCameraImage>(this->Topic(), 50);
}
//////////////////////////////////////////////////
void LogicalCameraSensor::Init()
{
// Read configuration values
if (this->sdf->HasElement("logical_camera"))
{
sdf::ElementPtr cameraSdf =
this->sdf->GetElement("logical_camera");
// These values are required in SDF, so no need to check for their
// existence.
this->dataPtr->frustum.SetNear(cameraSdf->Get<double>("near"));
this->dataPtr->frustum.SetFar(cameraSdf->Get<double>("far"));
this->dataPtr->frustum.SetFOV(cameraSdf->Get<double>("horizontal_fov"));
this->dataPtr->frustum.SetAspectRatio(
cameraSdf->Get<double>("aspect_ratio"));
}
Sensor::Init();
}
//////////////////////////////////////////////////
void LogicalCameraSensor::Fini()
{
Sensor::Fini();
}
//////////////////////////////////////////////////
void LogicalCameraSensorPrivate::AddVisibleModels(
ignition::math::Pose3d &_myPose, const physics::Model_V &_models)
{
for (auto const &model : _models)
{
auto const &scopedName = model->GetScopedName();
auto const aabb = model->GetBoundingBox().Ign();
if (this->modelName != scopedName && this->frustum.Contains(aabb))
{
// Add new model msg
msgs::LogicalCameraImage::Model *modelMsg = this->msg.add_model();
// Set the name and pose reported by the sensor.
modelMsg->set_name(scopedName);
msgs::Set(modelMsg->mutable_pose(),
model->GetWorldPose().Ign() - _myPose);
}
// Check nested models
// Note, the model AABB does not necessarily contain the nested model
// so nested models must be searched even if the frustum does not contain
// the parent model.
AddVisibleModels(_myPose, model->NestedModels());
}
}
//////////////////////////////////////////////////
bool LogicalCameraSensor::UpdateImpl(const bool _force)
{
// Only compute if active, or the update is forced
if (_force || this->IsActive())
{
std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
this->dataPtr->msg.clear_model();
// Get the pose of the camera's parent.
ignition::math::Pose3d myPose = this->pose +
this->dataPtr->parentLink->GetWorldPose().Ign();
// Update the pose of the frustum.
this->dataPtr->frustum.SetPose(myPose);
// Set the camera's pose in the message.
msgs::Set(this->dataPtr->msg.mutable_pose(), myPose);
// Recursively check if models and nested models are in the frustum.
this->dataPtr->AddVisibleModels(myPose, this->world->GetModels());
// Send the message.
this->dataPtr->pub->Publish(this->dataPtr->msg);
}
return true;
}
//////////////////////////////////////////////////
bool LogicalCameraSensor::IsActive() const
{
return Sensor::IsActive() ||
(this->dataPtr->pub && this->dataPtr->pub->HasConnections());
}
//////////////////////////////////////////////////
double LogicalCameraSensor::Near() const
{
return this->dataPtr->frustum.Near();
}
//////////////////////////////////////////////////
double LogicalCameraSensor::Far() const
{
return this->dataPtr->frustum.Far();
}
//////////////////////////////////////////////////
ignition::math::Angle LogicalCameraSensor::HorizontalFOV() const
{
return this->dataPtr->frustum.FOV();
}
//////////////////////////////////////////////////
double LogicalCameraSensor::AspectRatio() const
{
return this->dataPtr->frustum.AspectRatio();
}
//////////////////////////////////////////////////
msgs::LogicalCameraImage LogicalCameraSensor::Image() const
{
std::lock_guard<std::mutex> lock(this->dataPtr->mutex);
return this->dataPtr->msg;
}