Go to the documentation of this file.00001 #include <cassert>
00002 #include <boost/foreach.hpp>
00003
00004 #include <gazebo/sensors/SensorManager.hh>
00005
00006 #include <urdf_parser/urdf_parser.h>
00007
00008 #include <joint_limits_interface/joint_limits_urdf.h>
00009 #include <joint_limits_interface/joint_limits_rosparam.h>
00010
00011 #include <mrp2_hardware_gazebo/mrp2_hardware_gazebo.h>
00012
00013 using std::string;
00014 using std::vector;
00015
00016 namespace mrp2_hardware_gazebo
00017 {
00018 using namespace hardware_interface;
00019
00020 Mrp2HardwareGazebo::Mrp2HardwareGazebo()
00021 : gazebo_ros_control::RobotHWSim()
00022 {}
00023
00024
00025 bool Mrp2HardwareGazebo::initSim(const std::string& robot_namespace,
00026 ros::NodeHandle nh,
00027 gazebo::physics::ModelPtr model,
00028 const urdf::Model* const urdf_model,
00029 std::vector<transmission_interface::TransmissionInfo> transmissions)
00030 {
00031 using gazebo::physics::JointPtr;
00032
00033
00034 pos_sim_joints_.clear();
00035 vel_sim_joints_.clear();
00036 sim_joints_.clear();
00037 jnt_pos_.clear();
00038 jnt_vel_.clear();
00039 jnt_eff_.clear();
00040 jnt_pos_cmd_.clear();
00041 jnt_pos_cmd_curr_.clear();
00042 jnt_vel_cmd_.clear();
00043
00044
00045 std::vector<gazebo::physics::JointPtr> sim_joints_tmp = model->GetJoints();
00046
00047 std::vector<std::string> pos_jnt_names;
00048 std::vector<std::string> vel_jnt_names;
00049 std::vector<std::string> jnt_names;
00050 for (size_t i = 0; i < sim_joints_tmp.size(); ++i)
00051 {
00052
00053 const std::string unscoped_name = sim_joints_tmp[i]->GetName();
00054 if ( !(unscoped_name.size() >= 6 && 0 == unscoped_name.compare(0, 6, "caster")) )
00055 {
00056 if(0 == unscoped_name.compare(0, 5, "wheel"))
00057 {
00058 boost::shared_ptr<const urdf::Joint> joint(urdf_model->getJoint(unscoped_name));
00059 if(!joint)
00060 {
00061 ROS_ERROR_STREAM(unscoped_name
00062 << " couldn't be retrieved from model description");
00063 return false;
00064 }
00065
00066 sim_joints_tmp[i]->SetMaxForce(0u, joint->limits->effort);
00067 vel_sim_joints_.push_back(sim_joints_tmp[i]);
00068 vel_jnt_names.push_back(unscoped_name);
00069 }
00070 else
00071 {
00072 pos_sim_joints_.push_back(sim_joints_tmp[i]);
00073 pos_jnt_names.push_back(unscoped_name);
00074 }
00075 }
00076
00077 sim_joints_.push_back(sim_joints_tmp[i]);
00078 jnt_names.push_back(unscoped_name);
00079 }
00080
00081 pos_n_dof_ = pos_sim_joints_.size();
00082 vel_n_dof_ = vel_sim_joints_.size();
00083 n_dof_ = sim_joints_.size();
00084
00085
00086 jnt_pos_.resize(n_dof_);
00087 jnt_vel_.resize(n_dof_);
00088 jnt_eff_.resize(n_dof_);
00089 jnt_pos_cmd_.resize(pos_n_dof_);
00090 jnt_pos_cmd_curr_.resize(pos_n_dof_);
00091 jnt_vel_cmd_.resize(vel_n_dof_);
00092
00093
00094 for (size_t i = 0; i < n_dof_; ++i)
00095 {
00096
00097 jnt_state_interface_.registerHandle(JointStateHandle(jnt_names[i],
00098 &jnt_pos_[i],
00099 &jnt_vel_[i],
00100 &jnt_eff_[i]));
00101 }
00102 for (size_t i = 0; i < pos_n_dof_; ++i)
00103 {
00104
00105 jnt_pos_cmd_interface_.registerHandle(JointHandle(jnt_state_interface_.getHandle(pos_jnt_names[i]),
00106 &jnt_pos_cmd_[i]));
00107 ROS_DEBUG_STREAM("Registered joint '" << pos_jnt_names[i] << "' in the PositionJointInterface.");
00108 }
00109 for (size_t i = 0; i < vel_n_dof_; ++i)
00110 {
00111
00112 jnt_vel_cmd_interface_.registerHandle(JointHandle(jnt_state_interface_.getHandle(vel_jnt_names[i]),
00113 &jnt_vel_cmd_[i]));
00114 ROS_DEBUG_STREAM("Registered joint '" << pos_jnt_names[i] << "' in the VelocityJointInterface.");
00115 }
00116 registerInterface(&jnt_state_interface_);
00117 registerInterface(&jnt_pos_cmd_interface_);
00118 registerInterface(&jnt_vel_cmd_interface_);
00119
00120
00121 vector<string> pos_joints_with_limits, pos_joints_without_limits;
00122 for (size_t i = 0; i < pos_n_dof_; ++i)
00123 {
00124 JointHandle cmd_handle = jnt_pos_cmd_interface_.getHandle(pos_sim_joints_[i]->GetName());
00125 const string name = cmd_handle.getName();
00126
00127 using namespace joint_limits_interface;
00128 boost::shared_ptr<const urdf::Joint> urdf_joint = urdf_model->getJoint(name);
00129 JointLimits limits;
00130 SoftJointLimits soft_limits;
00131 if (!getJointLimits(urdf_joint, limits) || !getSoftJointLimits(urdf_joint, soft_limits))
00132 {
00133 pos_joints_without_limits.push_back(name);
00134 continue;
00135 }
00136 pos_jnt_limits_interface_.registerHandle(PositionJointSoftLimitsHandle(cmd_handle, limits, soft_limits));
00137 pos_joints_with_limits.push_back(name);
00138 }
00139 if (!pos_joints_with_limits.empty())
00140 {
00141 ROS_DEBUG_STREAM("Joint limits will be enforced for position-controlled joints:" <<
00142 containerToString(pos_joints_with_limits, "\n - "));
00143 }
00144 if (!pos_joints_without_limits.empty())
00145 {
00146 ROS_WARN_STREAM("Joint limits will not be enforced for position-controlled joints:" <<
00147 containerToString(pos_joints_without_limits, "\n - "));
00148 }
00149
00150
00151 vector<string> vel_joints_with_limits, vel_joints_without_limits;
00152 for (unsigned int i = 0; i < vel_n_dof_; ++i)
00153 {
00154 JointHandle cmd_handle = jnt_vel_cmd_interface_.getHandle(vel_sim_joints_[i]->GetName());
00155 const string name = cmd_handle.getName();
00156
00157 using namespace joint_limits_interface;
00158 boost::shared_ptr<const urdf::Joint> urdf_joint = urdf_model->getJoint(name);
00159 JointLimits limits;
00160 if (!getJointLimits(urdf_joint, limits) || !getJointLimits(name, nh, limits))
00161 {
00162 vel_joints_without_limits.push_back(name);
00163 continue;
00164 }
00165 vel_jnt_limits_interface_.registerHandle(VelocityJointSaturationHandle(cmd_handle, limits));
00166 vel_joints_with_limits.push_back(name);
00167 }
00168 if (!vel_joints_with_limits.empty())
00169 {
00170 ROS_DEBUG_STREAM("Joint limits will be enforced for velocity-controlled joints:" <<
00171 containerToString(vel_joints_with_limits, "\n - "));
00172 }
00173 if (!vel_joints_without_limits.empty())
00174 {
00175 ROS_WARN_STREAM("Joint limits will not be enforced for velocity-controlled joints:" <<
00176 containerToString(vel_joints_without_limits, "\n - "));
00177 }
00178
00179
00180 const string imu_name = "base_imu";
00181 imu_sensor_ = (gazebo::sensors::ImuSensor*)gazebo::sensors::SensorManager::Instance()->GetSensor(imu_name+"_sensor").get();
00182 if (!this->imu_sensor_)
00183 {
00184 ROS_ERROR_STREAM("Could not find base IMU sensor.");
00185 return false;
00186 }
00187
00188 ImuSensorHandle::Data data;
00189 data.name = imu_name;
00190 data.frame_id = imu_name + "_link";
00191 data.orientation = &base_orientation_[0];
00192 imu_sensor_interface_.registerHandle(ImuSensorHandle(data));
00193 registerInterface(&imu_sensor_interface_);
00194 ROS_DEBUG_STREAM("Registered IMU sensor.");
00195
00196
00197 pids_.resize(pos_n_dof_);
00198 for (size_t i = 0; i < pos_n_dof_; ++i)
00199 {
00200 ros::NodeHandle joint_nh(nh, "gains/" + pos_jnt_names[i]);
00201 if (!pids_[i].init(joint_nh)) {return false;}
00202 }
00203
00204 return true;
00205 }
00206
00207 void Mrp2HardwareGazebo::readSim(ros::Time time, ros::Duration period)
00208 {
00209 for(unsigned int j = 0; j < n_dof_; ++j)
00210 {
00211 jnt_pos_[j] += angles::shortest_angular_distance
00212 (jnt_pos_[j], sim_joints_[j]->GetAngle(0u).Radian());
00213 jnt_vel_[j] = sim_joints_[j]->GetVelocity(0u);
00214 jnt_eff_[j] = sim_joints_[j]->GetForce(0u);
00215 }
00216
00217 for(unsigned int j = 0; j < pos_n_dof_; ++j)
00218 {
00219 jnt_pos_cmd_curr_[j] += angles::shortest_angular_distance
00220 (jnt_pos_cmd_curr_[j], pos_sim_joints_[j]->GetAngle(0u).Radian());
00221 }
00222
00223
00224 gazebo::math::Quaternion imu_quat = imu_sensor_->GetOrientation();
00225 base_orientation_[0] = imu_quat.x;
00226 base_orientation_[1] = imu_quat.y;
00227 base_orientation_[2] = imu_quat.z;
00228 base_orientation_[3] = imu_quat.w;
00229
00230 gazebo::math::Vector3 imu_ang_vel = imu_sensor_->GetAngularVelocity();
00231 base_ang_vel_[0] = imu_ang_vel.x;
00232 base_ang_vel_[1] = imu_ang_vel.y;
00233 base_ang_vel_[2] = imu_ang_vel.z;
00234
00235 gazebo::math::Vector3 imu_lin_acc = imu_sensor_->GetLinearAcceleration();
00236 base_lin_acc_[0] = imu_lin_acc.x;
00237 base_lin_acc_[1] = imu_lin_acc.y;
00238 base_lin_acc_[2] = imu_lin_acc.z;
00239 }
00240
00241 void Mrp2HardwareGazebo::writeSim(ros::Time time, ros::Duration period)
00242 {
00243
00244 pos_jnt_limits_interface_.enforceLimits(period);
00245 vel_jnt_limits_interface_.enforceLimits(period);
00246
00247
00248 for(unsigned int j = 0; j < pos_n_dof_; ++j)
00249 {
00250 const double error = jnt_pos_cmd_[j] - jnt_pos_cmd_curr_[j];
00251 const double effort = pids_[j].computeCommand(error, period);
00252
00253 pos_sim_joints_[j]->SetForce(0u, effort);
00254 }
00255 for(unsigned int j = 0; j < vel_n_dof_; ++j)
00256 {
00257 vel_sim_joints_[j]->SetVelocity(0u, jnt_vel_cmd_[j]);
00258 }
00259 }
00260
00261 }
00262
00263 PLUGINLIB_EXPORT_CLASS( mrp2_hardware_gazebo::Mrp2HardwareGazebo, gazebo_ros_control::RobotHWSim)