/* * 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 "gazebo/common/Assert.hh" #include "gazebo/common/Console.hh" #include "gazebo/common/Exception.hh" #include "gazebo/physics/Model.hh" #include "gazebo/physics/simbody/SimbodyLink.hh" #include "gazebo/physics/simbody/SimbodyPhysics.hh" #include "gazebo/physics/simbody/SimbodyHingeJoint.hh" using namespace gazebo; using namespace physics; ////////////////////////////////////////////////// SimbodyHingeJoint::SimbodyHingeJoint(SimTK::MultibodySystem * /*_world*/, BasePtr _parent) : HingeJoint(_parent) { this->physicsInitialized = false; } ////////////////////////////////////////////////// SimbodyHingeJoint::~SimbodyHingeJoint() { } ////////////////////////////////////////////////// void SimbodyHingeJoint::Load(sdf::ElementPtr _sdf) { HingeJoint::Load(_sdf); } ////////////////////////////////////////////////// void SimbodyHingeJoint::SetAxis(unsigned int /*_index*/, const math::Vector3 &/*_axis*/) { // Simbody seems to handle setAxis improperly. It readjust all the pivot // points gzdbg << "SetAxis: setting axis is not yet implemented. The axis are set " << " during joint construction in SimbodyPhysics.cc for now.\n"; } ////////////////////////////////////////////////// void SimbodyHingeJoint::SetVelocity(unsigned int _index, double _rate) { if (_index < this->GetAngleCount()) { this->mobod.setOneU( this->simbodyPhysics->integ->updAdvancedState(), SimTK::MobilizerUIndex(_index), _rate); this->simbodyPhysics->system.realize( this->simbodyPhysics->integ->getAdvancedState(), SimTK::Stage::Velocity); } else gzerr << "SetVelocity _index too large.\n"; } ////////////////////////////////////////////////// double SimbodyHingeJoint::GetVelocity(unsigned int _index) const { if (_index < this->GetAngleCount()) { if (this->physicsInitialized && this->simbodyPhysics->simbodyPhysicsInitialized) return this->mobod.getOneU( this->simbodyPhysics->integ->getState(), SimTK::MobilizerUIndex(_index)); else { gzdbg << "GetVelocity() simbody not yet initialized, " << "initial velocity should be zero until restart from " << "state has been implemented.\n"; return 0.0; } } else { gzerr << "Invalid index for joint, returning NaN\n"; return SimTK::NaN; } } ////////////////////////////////////////////////// void SimbodyHingeJoint::SetForceImpl(unsigned int _index, double _torque) { if (_index < this->GetAngleCount() && this->physicsInitialized) this->simbodyPhysics->discreteForces.setOneMobilityForce( this->simbodyPhysics->integ->updAdvancedState(), this->mobod, SimTK::MobilizerUIndex(_index), _torque); } ////////////////////////////////////////////////// math::Vector3 SimbodyHingeJoint::GetGlobalAxis(unsigned int _index) const { if (this->simbodyPhysics && this->simbodyPhysics->simbodyPhysicsStepped && _index < this->GetAngleCount()) { if (!this->mobod.isEmptyHandle()) { const SimTK::Transform &X_OM = this->mobod.getOutboardFrame( this->simbodyPhysics->integ->getState()); // express Z-axis of X_OM in world frame SimTK::Vec3 z_W(this->mobod.expressVectorInGroundFrame( this->simbodyPhysics->integ->getState(), X_OM.z())); return SimbodyPhysics::Vec3ToVector3(z_W); } else { gzerr << "Joint mobod not initialized correctly. Returning" << " initial axis vector in world frame (not valid if" << " joint frame has moved). Please file" << " a report on issue tracker.\n"; return this->GetAxisFrame(_index).RotateVector( this->GetLocalAxis(_index)); } } else { if (_index >= this->GetAngleCount()) { gzerr << "index out of bound\n"; return math::Vector3(SimTK::NaN, SimTK::NaN, SimTK::NaN); } else { gzdbg << "GetGlobalAxis() sibmody physics engine not initialized yet, " << "use local axis and initial pose to compute " << "global axis.\n"; // if local axis specified in model frame (to be changed) // switch to code below if issue #494 is to be addressed return this->GetAxisFrame(_index).RotateVector( this->GetLocalAxis(_index)); } } } ////////////////////////////////////////////////// math::Angle SimbodyHingeJoint::GetAngleImpl(unsigned int _index) const { if (_index < this->GetAngleCount()) { if (this->physicsInitialized && this->simbodyPhysics->simbodyPhysicsInitialized) { if (!this->mobod.isEmptyHandle()) { return math::Angle(this->mobod.getOneQ( this->simbodyPhysics->integ->getState(), _index)); } else { gzerr << "Joint mobod not initialized correctly. Please file" << " a report on issue tracker.\n"; return math::Angle(0.0); } } else { gzdbg << "GetAngleImpl() simbody not yet initialized, " << "initial angle should be zero until " << "is implemented.\n"; return math::Angle(0.0); } } else { gzerr << "index out of bound\n"; return math::Angle(SimTK::NaN); } } ////////////////////////////////////////////////// void SimbodyHingeJoint::SaveSimbodyState(const SimTK::State &_state) { if (!this->mobod.isEmptyHandle()) { if (this->simbodyQ.empty()) this->simbodyQ.resize(this->mobod.getNumQ(_state)); if (this->simbodyU.empty()) this->simbodyU.resize(this->mobod.getNumU(_state)); for (unsigned int i = 0; i < this->simbodyQ.size(); ++i) this->simbodyQ[i] = this->mobod.getOneQ(_state, i); for (unsigned int i = 0; i < this->simbodyU.size(); ++i) this->simbodyU[i] = this->mobod.getOneU(_state, i); } else { // gzerr << "debug: joint name: " << this->GetScopedName() << "\n"; } } ////////////////////////////////////////////////// void SimbodyHingeJoint::RestoreSimbodyState(SimTK::State &_state) { if (!this->mobod.isEmptyHandle()) { for (unsigned int i = 0; i < this->simbodyQ.size(); ++i) this->mobod.setOneQ(_state, i, this->simbodyQ[i]); for (unsigned int i = 0; i < this->simbodyU.size(); ++i) this->mobod.setOneU(_state, i, this->simbodyU[i]); } else { // gzerr << "restoring model [" << this->GetScopedName() // << "] failed due to uninitialized mobod\n"; } }