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 #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
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
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
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
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
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
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
00142 const string left_ankle_name = "leg_left_6_joint";
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",
00160 "leg_left_6_link",
00161 &left_force_[0],
00162 &left_torque_[0]));
00163
00164 ft_sensor_interface_.registerHandle(ForceTorqueSensorHandle("right_ft",
00165 "leg_right_6_link",
00166 &right_force_[0],
00167 &right_torque_[0]));
00168 registerInterface(&ft_sensor_interface_);
00169 ROS_DEBUG_STREAM("Registered ankle force-torque sensors.");
00170
00171
00172 imu_sensor_ = boost::dynamic_pointer_cast<gazebo::sensors::ImuSensor>
00173 (gazebo::sensors::SensorManager::Instance()->GetSensor("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";
00182 data.frame_id = "base_link";
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
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
00202 for(unsigned int j = 0; j < n_dof_; ++j)
00203 {
00204
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
00212
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
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
00250
00251
00252
00253 for(unsigned int j = 0; j < n_dof_; ++j)
00254 {
00255 const double error = jnt_pos_cmd_[j] - jnt_pos_[j];
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
00264 sim_joints_[j]->SetForce(0u, effort_modified);
00265 }
00266
00267 }
00268
00269 }
00270
00271 PLUGINLIB_EXPORT_CLASS( reemc_hardware_gazebo::ReemcHardwareGazebo, gazebo_ros_control::RobotHWSim)