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