reemc_hardware_gazebo.cpp
Go to the documentation of this file.
00001 
00002 // Copyright (C) 2013, PAL Robotics S.L.
00003 //
00004 // Redistribution and use in source and binary forms, with or without
00005 // modification, are permitted provided that the following conditions are met:
00006 //   * Redistributions of source code must retain the above copyright notice,
00007 //     this list of conditions and the following disclaimer.
00008 //   * Redistributions in binary form must reproduce the above copyright
00009 //     notice, this list of conditions and the following disclaimer in the
00010 //     documentation and/or other materials provided with the distribution.
00011 //   * Neither the name of PAL Robotics S.L. nor the names of its
00012 //     contributors may be used to endorse or promote products derived from
00013 //     this software without specific prior written permission.
00014 //
00015 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00019 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025 // POSSIBILITY OF SUCH DAMAGE.
00027 
00028 #include <cassert>
00029 #include <boost/foreach.hpp>
00030 
00031 #include <gazebo/sensors/SensorManager.hh>
00032 
00033 #include <urdf_parser/urdf_parser.h>
00034 #include <pluginlib/class_list_macros.h>
00035 #include <angles/angles.h>
00036 
00037 #include <joint_limits_interface/joint_limits_urdf.h>
00038 
00039 #include <reemc_hardware_gazebo/reemc_hardware_gazebo.h>
00040 
00041 using std::vector;
00042 using std::string;
00043 
00044 namespace reemc_hardware_gazebo
00045 {
00046 
00047 using namespace hardware_interface;
00048 
00049 ReemcHardwareGazebo::ReemcHardwareGazebo()
00050   : gazebo_ros_control::RobotHWSim()
00051 {}
00052 
00053 bool ReemcHardwareGazebo::initSim(const std::string& robot_ns,
00054     ros::NodeHandle nh, gazebo::physics::ModelPtr model,
00055     const urdf::Model* const urdf_model,
00056     std::vector<transmission_interface::TransmissionInfo> transmissions)
00057 {
00058   using gazebo::physics::JointPtr;
00059 
00060   // Wait for robot model to become available
00061   const string robot_description_name = "robot_description";
00062   string robot_description;
00063   while (ros::ok() && !nh.getParam(robot_description_name, robot_description))
00064   {
00065     ROS_WARN_STREAM_ONCE("Waiting for robot description: parameter '" << robot_description_name << "' on namespace '" << nh.getNamespace() << "'.");
00066     ros::Duration(1.0).sleep();
00067   }
00068   ROS_INFO("Found robot description");
00069 
00070   boost::shared_ptr<urdf::ModelInterface> urdf = urdf::parseURDF(robot_description);
00071   if (!urdf)
00072   {
00073     throw std::runtime_error("Could not load robot description.");
00074   }
00075   ROS_DEBUG("Parsed robot description");
00076 
00077   // Cleanup
00078   sim_joints_.clear();
00079   jnt_pos_.clear();
00080   jnt_vel_.clear();
00081   jnt_eff_.clear();
00082   jnt_pos_cmd_.clear();
00083   jnt_curr_limit_cmd_.clear();
00084 
00085   // Simulation joints: All joints to control
00086   sim_joints_ = model->GetJoints();
00087   n_dof_ = sim_joints_.size();
00088 
00089   vector<string> jnt_names;
00090   for (size_t i = 0; i < n_dof_; ++i)
00091   {
00092     jnt_names.push_back(sim_joints_[i]->GetName());
00093   }
00094 
00095   // Raw data
00096   jnt_pos_.resize(n_dof_);
00097   jnt_vel_.resize(n_dof_);
00098   jnt_eff_.resize(n_dof_);
00099   jnt_pos_cmd_.resize(n_dof_);
00100   jnt_curr_limit_cmd_.resize(n_dof_, 1.0);
00102   jnt_max_effort_.resize(n_dof_);
00103   for(size_t j=0; j< n_dof_; ++j)
00104     jnt_max_effort_[j] = urdf->getJoint(sim_joints_[j]->GetName())->limits->effort;
00105 
00106   // Hardware interfaces: joints
00107   for (size_t i = 0; i < n_dof_; ++i)
00108   {
00109     jnt_state_interface_.registerHandle(JointStateHandle(jnt_names[i], &jnt_pos_[i], &jnt_vel_[i], &jnt_eff_[i]));
00110     jnt_pos_cmd_interface_.registerHandle(JointHandle(jnt_state_interface_.getHandle(jnt_names[i]), &jnt_pos_cmd_[i]));
00111     ROS_DEBUG_STREAM("Registered joint '" << jnt_names[i] << "' in the PositionJointInterface.");
00112 
00113     act_state_interface_.registerHandle(ActuatorStateHandle(jnt_names[i], &jnt_pos_[i], &jnt_vel_[i], &jnt_eff_[i]));
00114     jnt_curr_limit_cmd_interface_.registerHandle(ActuatorHandle(act_state_interface_.getHandle(jnt_names[i]), &jnt_curr_limit_cmd_[i]));
00115   }
00116   registerInterface(&jnt_state_interface_);
00117   registerInterface(&jnt_pos_cmd_interface_);
00118   registerInterface(&jnt_curr_limit_cmd_interface_);
00119 
00120   // Joint limits interface
00121   vector<string> cmd_handle_names = jnt_pos_cmd_interface_.getNames();
00122   for (unsigned int i = 0; i < cmd_handle_names.size(); ++i)
00123   {
00124     JointHandle cmd_handle = jnt_pos_cmd_interface_.getHandle(cmd_handle_names[i]);
00125     const string name = cmd_handle.getName();
00126 
00127     using namespace joint_limits_interface;
00128     boost::shared_ptr<const urdf::Joint> urdf_joint = urdf->getJoint(name);
00129     JointLimits limits;
00130     SoftJointLimits soft_limits;
00131     if (!getJointLimits(urdf_joint, limits) || !getSoftJointLimits(urdf_joint, soft_limits))
00132     {
00133       ROS_WARN_STREAM("Joint limits won't be enforced for joint '" << name << "'.");
00134       continue;
00135     }
00136     jnt_limits_interface_.registerHandle(PositionJointSoftLimitsHandle(cmd_handle, limits, soft_limits));
00137 
00138     ROS_DEBUG_STREAM("Joint limits will be enforced for joint '" << name << "'.");
00139   }
00140 
00141   // Hardware interfaces: Ankle force-torque sensors
00142   const string left_ankle_name  = "leg_left_6_joint";  // TODO: Make not hardcoded
00143   const string right_ankle_name = "leg_right_6_joint";
00144 
00145   left_ankle_  = model->GetJoint(left_ankle_name);
00146   right_ankle_ = model->GetJoint(right_ankle_name);
00147 
00148   if (!left_ankle_)
00149   {
00150     ROS_ERROR_STREAM("Could not find joint '" << left_ankle_name << "' to which a force-torque sensor is attached.");
00151     return false;
00152   }
00153   if (!right_ankle_)
00154   {
00155     ROS_ERROR_STREAM("Could not find joint '" << left_ankle_name << "' to which a force-torque sensor is attached.");
00156     return false;
00157   }
00158 
00159   ft_sensor_interface_.registerHandle(ForceTorqueSensorHandle("left_ft",         // TODO: Fetch from elsewhere?
00160                                                               "leg_left_6_link", // TODO: Fetch from URDF?
00161                                                               &left_force_[0],
00162                                                               &left_torque_[0]));
00163 
00164   ft_sensor_interface_.registerHandle(ForceTorqueSensorHandle("right_ft",         // TODO: Fetch from elsewhere?
00165                                                               "leg_right_6_link", // TODO: Fetch from URDF?
00166                                                               &right_force_[0],
00167                                                               &right_torque_[0]));
00168   registerInterface(&ft_sensor_interface_);
00169   ROS_DEBUG_STREAM("Registered ankle force-torque sensors.");
00170 
00171   // Hardware interfaces: Base IMU sensors
00172   imu_sensor_ =  boost::dynamic_pointer_cast<gazebo::sensors::ImuSensor>
00173       (gazebo::sensors::SensorManager::Instance()->GetSensor("imu_sensor")); // TODO: Fetch from URDF? /*reemc::reemc::base_link::imu_sensor*/
00174   if (!this->imu_sensor_)
00175   {
00176     ROS_ERROR_STREAM("Could not find base IMU sensor.");
00177     return false;
00178   }
00179 
00180   ImuSensorHandle::Data data;
00181   data.name = "base_imu";      // TODO: Fetch from elsewhere?
00182   data.frame_id = "base_link"; // TODO: Fetch from URDF?
00183   data.orientation = &base_orientation_[0];
00184   imu_sensor_interface_.registerHandle(ImuSensorHandle(data));
00185   registerInterface(&imu_sensor_interface_);
00186   ROS_DEBUG_STREAM("Registered IMU sensor.");
00187 
00188   // PID controllers
00189   pids_.resize(n_dof_);
00190   for (size_t i = 0; i < n_dof_; ++i)
00191   {
00192     ros::NodeHandle joint_nh(nh, "gains/" + jnt_names[i]);
00193     if (!pids_[i].init(joint_nh)) {return false;}
00194   }
00195 
00196   return true;
00197 }
00198 
00199 void ReemcHardwareGazebo::readSim(ros::Time time, ros::Duration period)
00200 {
00201   // Read joint state
00202   for(unsigned int j = 0; j < n_dof_; ++j)
00203   {
00204     // Gazebo has an interesting API...
00205     jnt_pos_[j] += angles::shortest_angular_distance
00206       (jnt_pos_[j], sim_joints_[j]->GetAngle(0u).Radian());
00207     jnt_vel_[j] = sim_joints_[j]->GetVelocity(0u);
00208     jnt_eff_[j] = sim_joints_[j]->GetForce(0u);
00209   }
00210 
00211   // Read force-torque sensors
00212   // Signs are coherent with FT sensor readings got from REEM-B
00213   gazebo::physics::JointWrench left_ft = left_ankle_->GetForceTorque(0u);
00214   left_force_[0]  = -left_ft.body1Force.y;
00215   left_force_[1]  = -left_ft.body1Force.z;
00216   left_force_[2]  =  left_ft.body1Force.x;
00217   left_torque_[0] = -left_ft.body1Torque.x;
00218   left_torque_[1] = -left_ft.body1Torque.z;
00219   left_torque_[2] =  left_ft.body1Torque.y;
00220 
00221   gazebo::physics::JointWrench right_ft = right_ankle_->GetForceTorque(0u);
00222   right_force_[0]  = -right_ft.body1Force.y;
00223   right_force_[1]  = -right_ft.body1Force.z;
00224   right_force_[2]  =  right_ft.body1Force.x;
00225   right_torque_[0] = -right_ft.body1Torque.x;
00226   right_torque_[1] = -right_ft.body1Torque.z;
00227   right_torque_[2] =  right_ft.body1Torque.y;
00228 
00229   // Read IMU sensor
00230   gazebo::math::Quaternion imu_quat = imu_sensor_->GetOrientation();
00231   base_orientation_[0] = imu_quat.x;
00232   base_orientation_[1] = imu_quat.y;
00233   base_orientation_[2] = imu_quat.z;
00234   base_orientation_[3] = imu_quat.w;
00235 
00236   gazebo::math::Vector3 imu_ang_vel = imu_sensor_->GetAngularVelocity();
00237   base_ang_vel_[0] = imu_ang_vel.x;
00238   base_ang_vel_[1] = imu_ang_vel.y;
00239   base_ang_vel_[2] = imu_ang_vel.z;
00240 
00241   gazebo::math::Vector3 imu_lin_acc = imu_sensor_->GetLinearAcceleration();
00242   base_lin_acc_[0] =  imu_lin_acc.x;
00243   base_lin_acc_[1] =  imu_lin_acc.y;
00244   base_lin_acc_[2] =  imu_lin_acc.z;
00245 }
00246 
00247 void ReemcHardwareGazebo::writeSim(ros::Time time, ros::Duration period)
00248 {
00249   // Enforce joint limits
00250 //   jnt_limits_interface_.enforceLimits(period); // TODO: Tune controllers to make this work?
00251 
00252   // Compute and send effort command
00253   for(unsigned int j = 0; j < n_dof_; ++j)
00254   {
00255     const double error = jnt_pos_cmd_[j] - jnt_pos_[j]; // NOTE: Assumes jnt_pos_ contains most recent value
00256     const double effort = pids_[j].computeCommand(error, period);
00257 
00258     const double max_effort = jnt_curr_limit_cmd_[j]*jnt_max_effort_[j];
00259     const double min_effort = -max_effort;
00260     double effort_modified = (effort - max_effort) > 1e-4  ? max_effort : effort;
00261     effort_modified = effort_modified - min_effort < -1e-4 ? min_effort : effort_modified;
00262 
00263     // Gazebo has an interesting API...
00264       sim_joints_[j]->SetForce(0u, effort_modified);
00265   }
00266 
00267 }
00268 
00269 } // reemc_hardware_gazebo
00270 
00271 PLUGINLIB_EXPORT_CLASS( reemc_hardware_gazebo::ReemcHardwareGazebo, gazebo_ros_control::RobotHWSim)


reemc_hardware_gazebo
Author(s): Adolfo Rodriguez Tsouroukdissian
autogenerated on Thu Aug 27 2015 14:40:15