pxmlw6n2f/Gazebo_Distributed_TCP/gazebo/rendering/JointVisual.cc

362 lines
11 KiB
C++

/*
* Copyright (C) 2014 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 "gazebo/rendering/ogre_gazebo.h"
#include "gazebo/rendering/DynamicLines.hh"
#include "gazebo/rendering/Scene.hh"
#include "gazebo/rendering/AxisVisual.hh"
#include "gazebo/rendering/ArrowVisual.hh"
#include "gazebo/rendering/JointVisualPrivate.hh"
#include "gazebo/rendering/JointVisual.hh"
using namespace gazebo;
using namespace rendering;
/////////////////////////////////////////////////
JointVisual::JointVisual(const std::string &_name, VisualPtr _vis)
: Visual(*new JointVisualPrivate, _name, _vis, false)
{
JointVisualPrivate *dPtr =
reinterpret_cast<JointVisualPrivate *>(this->dataPtr);
dPtr->type = VT_PHYSICS;
}
/////////////////////////////////////////////////
JointVisual::~JointVisual()
{
JointVisualPrivate *dPtr =
reinterpret_cast<JointVisualPrivate *>(this->dataPtr);
dPtr->axisVisual.reset();
}
/////////////////////////////////////////////////
void JointVisual::Load(ConstJointPtr &_msg)
{
JointVisualPrivate *dPtr =
reinterpret_cast<JointVisualPrivate *>(this->dataPtr);
Visual::Load();
dPtr->axisVisual.reset(
new AxisVisual(this->GetName() + "_AXIS", shared_from_this()));
dPtr->axisVisual->Load();
ignition::math::Pose3d pose;
if (_msg->has_pose())
pose = msgs::ConvertIgn(_msg->pose());
this->SetPosition(pose.Pos());
this->SetRotation(pose.Rot());
if (_msg->has_axis2())
{
// for hinge2 and universal joints:
// axis1 is attached to parent link and axis2 is attached to child link
// create extra joint visual for axis1
VisualPtr parentVis;
if (_msg->has_parent() && _msg->parent() == "world")
parentVis = this->GetScene()->WorldVisual();
else if (_msg->has_parent_id())
parentVis = this->GetScene()->GetVisual(_msg->parent_id());
JointVisualPtr jointVis;
jointVis.reset(new JointVisual(this->GetName() + "_parent_", parentVis));
jointVis->Load(_msg, pose + this->GetParent()->GetWorldPose().Ign());
// attach axis2 to this visual
msgs::Axis axis2Msg = _msg->axis2();
dPtr->arrowVisual = this->CreateAxis(msgs::ConvertIgn(axis2Msg.xyz()),
axis2Msg.use_parent_model_frame(), _msg->type());
dPtr->parentAxisVis = jointVis;
}
else if (_msg->has_axis1())
{
// for all other joint types:
// axis1 is attached to child link
msgs::Axis axis1Msg = _msg->axis1();
dPtr->arrowVisual = this->CreateAxis(msgs::ConvertIgn(axis1Msg.xyz()),
axis1Msg.use_parent_model_frame(), _msg->type());
}
// Scale according to the link it is attached to
double linkSize = std::max(0.1,
dPtr->parent->GetBoundingBox().GetSize().GetLength());
dPtr->scaleToLink = math::Vector3(linkSize * 0.7,
linkSize * 0.7,
linkSize * 0.7);
this->SetScale(dPtr->scaleToLink);
if (dPtr->parentAxisVis)
dPtr->parentAxisVis->SetScale(dPtr->scaleToLink);
this->GetSceneNode()->setInheritScale(false);
this->SetVisibilityFlags(GZ_VISIBILITY_GUI);
}
/////////////////////////////////////////////////
void JointVisual::Load(ConstJointPtr &_msg, const math::Pose &_worldPose)
{
JointVisualPrivate *dPtr =
reinterpret_cast<JointVisualPrivate *>(this->dataPtr);
Visual::Load();
msgs::Axis axis1Msg = _msg->axis1();
dPtr->arrowVisual = this->CreateAxis(msgs::ConvertIgn(axis1Msg.xyz()),
axis1Msg.use_parent_model_frame(), _msg->type());
// joint pose is always relative to the child link so update axis pose
this->SetWorldPose(_worldPose);
this->GetSceneNode()->setInheritScale(false);
this->SetVisibilityFlags(GZ_VISIBILITY_GUI);
}
/////////////////////////////////////////////////
ArrowVisualPtr JointVisual::CreateAxis(const math::Vector3 &_axis,
bool _useParentFrame, msgs::Joint::Type _type)
{
ArrowVisualPtr axis;
std::stringstream nameStr;
nameStr << this->GetName() << "_axis_" << this->GetChildCount() << "_AXIS";
axis.reset(new ArrowVisual(nameStr.str(), shared_from_this()));
axis->Load();
axis->SetMaterial("Gazebo/YellowTransparent");
this->UpdateAxis(axis, _axis, _useParentFrame, _type);
return axis;
}
/////////////////////////////////////////////////
void JointVisual::UpdateAxis(ArrowVisualPtr _arrowVisual,
const math::Vector3 &_axis, bool _useParentFrame, msgs::Joint::Type _type)
{
JointVisualPrivate *dPtr =
reinterpret_cast<JointVisualPrivate *>(this->dataPtr);
// Get rotation to axis vector
math::Vector3 axisDir = _axis;
math::Vector3 u = axisDir.Normalize();
math::Vector3 v = math::Vector3::UnitZ;
double cosTheta = v.Dot(u);
double angle = acos(cosTheta);
math::Quaternion quat;
// check the parallel case
if (math::equal(angle, M_PI))
quat.SetFromAxis(u.GetPerpendicular(), angle);
else
quat.SetFromAxis((v.Cross(u)).Normalize(), angle);
_arrowVisual->SetRotation(quat);
if (_useParentFrame)
{
VisualPtr linkVis = this->GetParent();
ignition::math::Pose3d linkInitPose = linkVis->InitialRelativePose();
// get rotation of joint visual in model frame
ignition::math::Quaterniond quatFromModel =
(this->GetPose().Ign() + linkInitPose).Rot();
// rotate arrow visual so that the axis vector applies to the model frame.
_arrowVisual->SetRotation(quatFromModel.Inverse() *
_arrowVisual->GetRotation().Ign());
}
_arrowVisual->ShowRotation(_type == msgs::Joint::REVOLUTE ||
_type == msgs::Joint::REVOLUTE2 ||
_type == msgs::Joint::UNIVERSAL ||
_type == msgs::Joint::GEARBOX);
if (dPtr->axisVisual)
{
_arrowVisual->SetVisible(true);
}
else
{
return;
}
// Hide existing arrow head if it overlaps with the axis
math::Quaternion axisWorldRotation = _arrowVisual->GetWorldPose().rot;
math::Quaternion jointWorldRotation = this->GetWorldPose().rot;
dPtr->axisVisual->ShowAxisHead(0, true);
dPtr->axisVisual->ShowAxisHead(1, true);
dPtr->axisVisual->ShowAxisHead(2, true);
_arrowVisual->ShowShaft(true);
math::Vector3 axisWorld = axisWorldRotation*math::Vector3::UnitZ;
if (axisWorld == jointWorldRotation*math::Vector3::UnitX)
{
dPtr->axisVisual->ShowAxisHead(0, false);
_arrowVisual->ShowShaft(false);
}
else if (axisWorld == jointWorldRotation*math::Vector3::UnitY)
{
dPtr->axisVisual->ShowAxisHead(1, false);
_arrowVisual->ShowShaft(false);
}
else if (axisWorld == jointWorldRotation*math::Vector3::UnitZ)
{
dPtr->axisVisual->ShowAxisHead(2, false);
_arrowVisual->ShowShaft(false);
}
}
/////////////////////////////////////////////////
void JointVisual::UpdateFromMsg(ConstJointPtr &_msg)
{
JointVisualPrivate *dPtr =
reinterpret_cast<JointVisualPrivate *>(this->dataPtr);
if (_msg->has_pose())
{
// Avoid position changing when parent is scaled
this->SetPosition(msgs::ConvertIgn(_msg->pose().position()) /
this->GetParent()->GetScale().Ign());
this->SetRotation(msgs::ConvertIgn(_msg->pose().orientation()));
}
ArrowVisualPtr axis2Visual = NULL;
if (dPtr->parentAxisVis)
{
axis2Visual = dPtr->parentAxisVis->GetArrowVisual();
}
// Show XYZ heads
if (dPtr->axisVisual)
{
dPtr->axisVisual->ShowAxisHead(0, true);
dPtr->axisVisual->ShowAxisHead(1, true);
dPtr->axisVisual->ShowAxisHead(2, true);
}
msgs::Axis axis1Msg;
msgs::Axis axis2Msg;
// Now has 2 axes
if (_msg->has_axis2())
{
axis1Msg = _msg->axis1();
axis2Msg = _msg->axis2();
// Previously already had 2 axes
if (axis2Visual)
{
this->UpdateAxis(dPtr->arrowVisual, msgs::ConvertIgn(axis1Msg.xyz()),
axis1Msg.use_parent_model_frame(), _msg->type());
this->UpdateAxis(axis2Visual, msgs::ConvertIgn(axis2Msg.xyz()),
axis2Msg.use_parent_model_frame(), _msg->type());
// joint pose is always relative to the child link
dPtr->parentAxisVis->SetWorldPose(msgs::ConvertIgn(_msg->pose()) +
this->GetParent()->GetWorldPose().Ign());
}
else
{
VisualPtr parentVis;
if (_msg->has_parent() && _msg->parent() == "world")
parentVis = this->GetScene()->WorldVisual();
else if (_msg->has_parent_id())
parentVis = this->GetScene()->GetVisual(_msg->parent_id());
JointVisualPtr jointVis;
jointVis.reset(new JointVisual(this->GetName() + "_parent_", parentVis));
jointVis->Load(_msg,
msgs::ConvertIgn(_msg->pose()) +
this->GetParent()->GetWorldPose().Ign());
dPtr->parentAxisVis = jointVis;
dPtr->parentAxisVis->SetScale(dPtr->scaleToLink);
// Previously had 1 axis, which becomes axis 2 now
if (dPtr->arrowVisual)
{
this->UpdateAxis(dPtr->arrowVisual, msgs::ConvertIgn(axis2Msg.xyz()),
axis2Msg.use_parent_model_frame(), _msg->type());
}
// Previously had no axis
else
{
dPtr->arrowVisual = this->CreateAxis(msgs::ConvertIgn(axis2Msg.xyz()),
axis2Msg.use_parent_model_frame(), _msg->type());
}
}
}
// Now has 1 axis
else if (_msg->has_axis1())
{
// Hide axis 2
if (axis2Visual)
axis2Visual->SetVisible(false);
axis1Msg = _msg->axis1();
// Previously had at least 1 axis
if (dPtr->arrowVisual)
{
this->UpdateAxis(dPtr->arrowVisual, msgs::ConvertIgn(axis1Msg.xyz()),
axis1Msg.use_parent_model_frame(), _msg->type());
}
// Previously had no axis
else
{
dPtr->arrowVisual = this->CreateAxis(msgs::ConvertIgn(axis1Msg.xyz()),
axis1Msg.use_parent_model_frame(), _msg->type());
}
}
// Now has no axis
else if (_msg->has_type())
{
// Hide axes 1 and 2
if (dPtr->arrowVisual)
dPtr->arrowVisual->SetVisible(false);
if (axis2Visual)
axis2Visual->SetVisible(false);
}
}
/////////////////////////////////////////////////
JointVisualPtr JointVisual::GetParentAxisVisual() const
{
JointVisualPrivate *dPtr =
reinterpret_cast<JointVisualPrivate *>(this->dataPtr);
return dPtr->parentAxisVis;
}
/////////////////////////////////////////////////
ArrowVisualPtr JointVisual::GetArrowVisual() const
{
JointVisualPrivate *dPtr =
reinterpret_cast<JointVisualPrivate *>(this->dataPtr);
return dPtr->arrowVisual;
}
/////////////////////////////////////////////////
void JointVisual::SetVisible(bool _visible, bool _cascade)
{
JointVisualPrivate *dPtr =
reinterpret_cast<JointVisualPrivate *>(this->dataPtr);
Visual::SetVisible(_visible, _cascade);
if (dPtr->parentAxisVis)
dPtr->parentAxisVis->SetVisible(_visible, _cascade);
}