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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <angles/angles.h>
00040
00041 #include <urdf_parser/urdf_parser.h>
00042
00043 #include <joint_limits_interface/joint_limits_urdf.h>
00044 #include <joint_limits_interface/joint_limits_rosparam.h>
00045
00046 #include <pluginlib/class_list_macros.h>
00047
00048 #include <steer_bot_hardware_gazebo/steer_bot_hardware_gazebo.h>
00049
00050 namespace steer_bot_hardware_gazebo
00051 {
00052 using namespace hardware_interface;
00053
00054 SteerBotHardwareGazebo::SteerBotHardwareGazebo()
00055 : gazebo_ros_control::RobotHWSim()
00056 , ns_("steer_bot_hardware_gazebo/")
00057 , log_cnt_(0)
00058 {}
00059
00060
00061 bool SteerBotHardwareGazebo::initSim(const std::string& robot_namespace,
00062 ros::NodeHandle nh,
00063 gazebo::physics::ModelPtr model,
00064 const urdf::Model* const urdf_model,
00065 std::vector<transmission_interface::TransmissionInfo> transmissions)
00066 {
00067 using gazebo::physics::JointPtr;
00068
00069 nh_ = nh;
00070
00071
00072 sim_joints_ = model->GetJoints();
00073 n_dof_ = sim_joints_.size();
00074
00075 this->CleanUp();
00076 this->GetJointNames(nh_);
00077 this->RegisterHardwareInterfaces();
00078
00079 nh_.getParam(ns_ + "wheel_separation_w", wheel_separation_w_);
00080 nh_.getParam(ns_ + "wheel_separation_h", wheel_separation_h_);
00081 ROS_INFO_STREAM("wheel_separation_w = " << wheel_separation_w_);
00082 ROS_INFO_STREAM("wheel_separation_h = " << wheel_separation_h_);
00083
00084 nh_.getParam(ns_ + "enable_ackermann_link", enable_ackermann_link_);
00085 ROS_INFO_STREAM("enable_ackermann_link = " << (enable_ackermann_link_ ? "true" : "false"));
00086
00087
00088 std::vector<std::string> cmd_handle_names = front_steer_jnt_pos_cmd_interface_.getNames();
00089 for (size_t i = 0; i < cmd_handle_names.size(); ++i)
00090 {
00091 const std::string name = cmd_handle_names[i];
00092
00093
00094 if(name != virtual_front_steer_jnt_names_[INDEX_RIGHT] && name != virtual_front_steer_jnt_names_[INDEX_LEFT])
00095 continue;
00096
00097 JointHandle cmd_handle = front_steer_jnt_pos_cmd_interface_.getHandle(name);
00098
00099 using namespace joint_limits_interface;
00100 boost::shared_ptr<const urdf::Joint> urdf_joint = urdf_model->getJoint(name);
00101 JointLimits limits;
00102 SoftJointLimits soft_limits;
00103 if (!getJointLimits(urdf_joint, limits) || !getSoftJointLimits(urdf_joint, soft_limits))
00104 {
00105 ROS_WARN_STREAM("Joint limits won't be enforced for joint '" << name << "'.");
00106 }
00107 else
00108 {
00109 jnt_limits_interface_.registerHandle(
00110 PositionJointSoftLimitsHandle(cmd_handle, limits, soft_limits));
00111
00112 ROS_DEBUG_STREAM("Joint limits will be enforced for joint '" << name << "'.");
00113 }
00114 }
00115
00116
00117 const int virtual_jnt_cnt_ = virtual_rear_wheel_jnt_names_.size();
00118 pids_.resize(virtual_jnt_cnt_);
00119
00120 for (size_t i = 0; i < virtual_jnt_cnt_; ++i)
00121 {
00122 const std::string jnt_name = virtual_rear_wheel_jnt_names_[i];
00123 const ros::NodeHandle joint_nh(nh, "gains/" + jnt_name);
00124
00125 ROS_INFO_STREAM("Trying to set pid param of '" << jnt_name << " ' at PID proc in init()");
00126 if (!pids_[i].init(joint_nh))
00127 {
00128 ROS_INFO_STREAM("Faied to set pid param of '" << jnt_name << " ' at PID proc in init()");
00129 return false;
00130 }
00131 ROS_INFO_STREAM("Succeeded to set pid param of '" << jnt_name << " ' at PID proc in init()");
00132 }
00133
00134 return true;
00135 }
00136
00137 void SteerBotHardwareGazebo::readSim(ros::Time time, ros::Duration period)
00138 {
00139 for(int i = 0; i < sim_joints_.size(); i++)
00140 {
00141 std::string gazebo_jnt_name;
00142 gazebo_jnt_name = sim_joints_[i]->GetName();
00143
00144 if(gazebo_jnt_name == virtual_rear_wheel_jnt_names_[INDEX_RIGHT])
00145 {
00146 GetCurrentState(virtual_rear_wheel_jnt_pos_, virtual_rear_wheel_jnt_vel_, virtual_rear_wheel_jnt_eff_, INDEX_RIGHT, i);
00147 }
00148 else if(gazebo_jnt_name == virtual_rear_wheel_jnt_names_[INDEX_LEFT])
00149 {
00150 GetCurrentState(virtual_rear_wheel_jnt_pos_, virtual_rear_wheel_jnt_vel_, virtual_rear_wheel_jnt_eff_, INDEX_LEFT, i);
00151 }
00152 else if(gazebo_jnt_name == virtual_front_wheel_jnt_names_[INDEX_RIGHT])
00153 {
00154 GetCurrentState(virtual_front_wheel_jnt_pos_, virtual_front_wheel_jnt_vel_, virtual_front_wheel_jnt_eff_, INDEX_RIGHT, i);
00155 }
00156 else if(gazebo_jnt_name == virtual_front_wheel_jnt_names_[INDEX_LEFT])
00157 {
00158 GetCurrentState(virtual_front_wheel_jnt_pos_, virtual_front_wheel_jnt_vel_, virtual_front_wheel_jnt_eff_, INDEX_LEFT, i);
00159 }
00160 else if(gazebo_jnt_name == virtual_front_steer_jnt_names_[INDEX_RIGHT])
00161 {
00162 GetCurrentState(virtual_front_steer_jnt_pos_, virtual_front_steer_jnt_vel_, virtual_front_steer_jnt_eff_, INDEX_RIGHT, i);
00163 }
00164 else if(gazebo_jnt_name == virtual_front_steer_jnt_names_[INDEX_LEFT])
00165 {
00166 GetCurrentState(virtual_front_steer_jnt_pos_, virtual_front_steer_jnt_vel_, virtual_front_steer_jnt_eff_, INDEX_LEFT, i);
00167 }
00168 else
00169 {
00170
00171 }
00172 }
00173
00174 front_steer_jnt_pos_ = (virtual_front_steer_jnt_pos_[INDEX_RIGHT] + virtual_front_steer_jnt_pos_[INDEX_LEFT]) / virtual_front_steer_jnt_pos_.size();
00175 front_steer_jnt_vel_ = (virtual_front_steer_jnt_vel_[INDEX_RIGHT] + virtual_front_steer_jnt_vel_[INDEX_LEFT]) / virtual_front_steer_jnt_vel_.size();
00176 front_steer_jnt_eff_ = (virtual_front_steer_jnt_eff_[INDEX_RIGHT] + virtual_front_steer_jnt_eff_[INDEX_LEFT]) / virtual_front_steer_jnt_eff_.size();
00177 }
00178
00179 void SteerBotHardwareGazebo::writeSim(ros::Time time, ros::Duration period)
00180 {
00181
00182 jnt_limits_interface_.enforceLimits(period);
00183
00184 log_cnt_++;
00185 for(int i = 0; i < sim_joints_.size(); i++)
00186 {
00187 std::string gazebo_jnt_name;
00188 gazebo_jnt_name = sim_joints_[i]->GetName();
00189
00190
00191 if(gazebo_jnt_name == virtual_rear_wheel_jnt_names_[INDEX_RIGHT])
00192 {
00193 const double eff_cmd = ComputeEffCommandFromVelError(INDEX_RIGHT, period);
00194 sim_joints_[i]->SetForce(0u, eff_cmd);
00195
00196 if(log_cnt_ % 500 == 0)
00197 {
00198 ROS_DEBUG_STREAM("rear_wheel_jnt_vel_cmd_ = " << rear_wheel_jnt_vel_cmd_);
00199 ROS_DEBUG_STREAM("virtual_rear_wheel_jnt_vel_[INDEX_RIGHT] = " << virtual_rear_wheel_jnt_vel_[INDEX_RIGHT]);
00200 ROS_DEBUG_STREAM("error[INDEX_RIGHT] " << rear_wheel_jnt_vel_cmd_ - virtual_rear_wheel_jnt_vel_[INDEX_RIGHT]);
00201 ROS_DEBUG_STREAM("command[INDEX_RIGHT] = " << eff_cmd);
00202 }
00203 }
00204 else if(gazebo_jnt_name == virtual_rear_wheel_jnt_names_[INDEX_LEFT])
00205 {
00206 const double eff_cmd = ComputeEffCommandFromVelError(INDEX_LEFT, period);
00207 sim_joints_[i]->SetForce(0u, eff_cmd);
00208
00209 if(log_cnt_ % 500 == 0)
00210 {
00211 ROS_DEBUG_STREAM("rear_wheel_jnt_vel_cmd_ = " << rear_wheel_jnt_vel_cmd_);
00212 ROS_DEBUG_STREAM("virtual_rear_wheel_jnt_vel_[INDEX_LEFT] = " << virtual_rear_wheel_jnt_vel_[INDEX_LEFT]);
00213 ROS_DEBUG_STREAM("error[INDEX_LEFT] " << rear_wheel_jnt_vel_cmd_ - virtual_rear_wheel_jnt_vel_[INDEX_LEFT]);
00214 ROS_DEBUG_STREAM("command[INDEX_LEFT] = " << eff_cmd);
00215 }
00216 }
00217
00218 else if(gazebo_jnt_name == front_steer_jnt_name_)
00219 {
00220 front_steer_jnt_pos_ = front_steer_jnt_pos_cmd_;
00221 ROS_INFO_STREAM("front_steer_jnt_pos_ '" << front_steer_jnt_pos_ << " ' at writeSim()");
00222 }
00223 else if(gazebo_jnt_name == virtual_front_steer_jnt_names_[INDEX_RIGHT])
00224 {
00225 double pos_cmd = 0.0;
00226 if(enable_ackermann_link_)
00227 {
00228 const double h = wheel_separation_h_;
00229 const double w = wheel_separation_w_;
00230 pos_cmd = atan2(2*h*tan(front_steer_jnt_pos_cmd_), 2*h + w/2.0*tan(front_steer_jnt_pos_cmd_));
00231 ROS_DEBUG_STREAM("ackermann steer angle: " << pos_cmd << " at RIGHT");
00232 }
00233 else
00234 {
00235 pos_cmd = front_steer_jnt_pos_cmd_;
00236 }
00237 sim_joints_[i]->SetAngle(0, pos_cmd);
00238 }
00239 else if(gazebo_jnt_name == virtual_front_steer_jnt_names_[INDEX_LEFT])
00240 {
00241 double pos_cmd = 0.0;
00242 if(enable_ackermann_link_)
00243 {
00244 const double h = wheel_separation_h_;
00245 const double w = wheel_separation_w_;
00246 pos_cmd = atan2(2*h*tan(front_steer_jnt_pos_cmd_), 2*h - w/2.0*tan(front_steer_jnt_pos_cmd_));
00247 ROS_DEBUG_STREAM("ackermann steer angle: " << pos_cmd << " at LEFT");
00248 }
00249 else
00250 {
00251 pos_cmd = front_steer_jnt_pos_cmd_;
00252 }
00253 sim_joints_[i]->SetAngle(0, pos_cmd);
00254 }
00255 else
00256 {
00257
00258 }
00259 }
00260
00261
00262 front_steer_jnt_pos_ = front_steer_jnt_pos_cmd_;
00263 if(log_cnt_ % 500 == 0)
00264 {
00265 ROS_DEBUG_STREAM("front_steer_jnt_pos_ '" << front_steer_jnt_pos_ << " ' at writeSim()");
00266 }
00267
00268 rear_wheel_jnt_pos_ = 0.5 * (virtual_rear_wheel_jnt_pos_[INDEX_RIGHT] + virtual_rear_wheel_jnt_pos_[INDEX_LEFT]);
00269 rear_wheel_jnt_vel_ = 0.5 * (virtual_rear_wheel_jnt_vel_[INDEX_RIGHT] + virtual_rear_wheel_jnt_vel_[INDEX_LEFT]);
00270 if(log_cnt_ % 500 == 0)
00271 {
00272 ROS_DEBUG_STREAM("rear_wheel_jnt_pos_ '" << rear_wheel_jnt_pos_ << " ' at writeSim()");
00273 ROS_DEBUG_STREAM("rear_wheel_jnt_vel_ '" << rear_wheel_jnt_vel_ << " ' at writeSim()");
00274 }
00275 }
00276
00277 void SteerBotHardwareGazebo::CleanUp()
00278 {
00279
00280
00281 rear_wheel_jnt_name_.empty();
00282 virtual_rear_wheel_jnt_names_.clear();
00283
00284 rear_wheel_jnt_pos_ = 0;
00285 rear_wheel_jnt_vel_ = 0;
00286 rear_wheel_jnt_eff_ = 0;
00287 rear_wheel_jnt_vel_cmd_ = 0;
00288
00289 virtual_rear_wheel_jnt_pos_.clear();
00290 virtual_rear_wheel_jnt_vel_.clear();
00291 virtual_rear_wheel_jnt_eff_.clear();
00292 virtual_rear_wheel_jnt_vel_cmd_.clear();
00293
00294 virtual_front_wheel_jnt_pos_.clear();
00295 virtual_front_wheel_jnt_vel_.clear();
00296 virtual_front_wheel_jnt_eff_.clear();
00297 virtual_front_wheel_jnt_vel_cmd_.clear();
00298
00299
00300
00301 front_steer_jnt_name_.empty();
00302 virtual_front_steer_jnt_names_.clear();
00303
00304 front_steer_jnt_pos_ = 0;
00305 front_steer_jnt_vel_ = 0;
00306 front_steer_jnt_eff_ = 0;
00307 front_steer_jnt_pos_cmd_ = 0;
00308
00309 virtual_front_steer_jnt_pos_.clear();
00310 virtual_front_steer_jnt_vel_.clear();
00311 virtual_front_steer_jnt_eff_.clear();
00312 virtual_front_steer_jnt_pos_cmd_.clear();
00313 }
00314
00315 void SteerBotHardwareGazebo::GetJointNames(ros::NodeHandle &_nh)
00316 {
00317 this->GetWheelJointNames(_nh);
00318 this->GetSteerJointNames(_nh);
00319 }
00320
00321 void SteerBotHardwareGazebo::GetWheelJointNames(ros::NodeHandle &_nh)
00322 {
00323
00324 _nh.getParam(ns_ + "rear_wheel", rear_wheel_jnt_name_);
00325
00326
00327 _nh.getParam(ns_ + "virtual_rear_wheels", virtual_rear_wheel_jnt_names_);
00328 int dof = virtual_rear_wheel_jnt_names_.size();
00329 virtual_rear_wheel_jnt_pos_.resize(dof);
00330 virtual_rear_wheel_jnt_vel_.resize(dof);
00331 virtual_rear_wheel_jnt_eff_.resize(dof);
00332 virtual_rear_wheel_jnt_vel_cmd_.resize(dof);
00333
00334 _nh.getParam(ns_ + "virtual_front_wheels", virtual_front_wheel_jnt_names_);
00335 dof = virtual_front_wheel_jnt_names_.size();
00336 virtual_front_wheel_jnt_pos_.resize(dof);
00337 virtual_front_wheel_jnt_vel_.resize(dof);
00338 virtual_front_wheel_jnt_eff_.resize(dof);
00339 virtual_front_wheel_jnt_vel_cmd_.resize(dof);
00340
00341 }
00342
00343 void SteerBotHardwareGazebo::GetSteerJointNames(ros::NodeHandle &_nh)
00344 {
00345
00346 _nh.getParam(ns_ + "front_steer", front_steer_jnt_name_);
00347
00348
00349 _nh.getParam(ns_ + "virtual_front_steers", virtual_front_steer_jnt_names_);
00350
00351 const int dof = virtual_front_steer_jnt_names_.size();
00352 virtual_front_steer_jnt_pos_.resize(dof);
00353 virtual_front_steer_jnt_vel_.resize(dof);
00354 virtual_front_steer_jnt_eff_.resize(dof);
00355 virtual_front_steer_jnt_pos_cmd_.resize(dof);
00356 }
00357
00358 void SteerBotHardwareGazebo::RegisterHardwareInterfaces()
00359 {
00360 this->RegisterSteerInterface();
00361 this->RegisterWheelInterface();
00362
00363
00364 registerInterface(&jnt_state_interface_);
00365 registerInterface(&rear_wheel_jnt_vel_cmd_interface_);
00366 registerInterface(&front_steer_jnt_pos_cmd_interface_);
00367 }
00368
00369 void SteerBotHardwareGazebo::RegisterInterfaceHandles(
00370 hardware_interface::JointStateInterface& _jnt_state_interface,
00371 hardware_interface::JointCommandInterface& _jnt_cmd_interface,
00372 const std::string _jnt_name, double& _jnt_pos, double& _jnt_vel, double& _jnt_eff, double& _jnt_cmd)
00373 {
00374
00375 this->RegisterJointStateInterfaceHandle(_jnt_state_interface, _jnt_name,
00376 _jnt_pos, _jnt_vel, _jnt_eff);
00377 this->RegisterCommandJointInterfaceHandle(_jnt_state_interface, _jnt_cmd_interface,
00378 _jnt_name, _jnt_cmd);
00379 }
00380
00381 void SteerBotHardwareGazebo::RegisterWheelInterface()
00382 {
00383
00384 this->RegisterInterfaceHandles(
00385 jnt_state_interface_, rear_wheel_jnt_vel_cmd_interface_,
00386 rear_wheel_jnt_name_, rear_wheel_jnt_pos_, rear_wheel_jnt_vel_, rear_wheel_jnt_eff_, rear_wheel_jnt_vel_cmd_);
00387
00388
00389 for (int i = 0; i < virtual_rear_wheel_jnt_names_.size(); i++)
00390 {
00391 this->RegisterInterfaceHandles(
00392 jnt_state_interface_, rear_wheel_jnt_vel_cmd_interface_,
00393 virtual_rear_wheel_jnt_names_[i], virtual_rear_wheel_jnt_pos_[i], virtual_rear_wheel_jnt_vel_[i], virtual_rear_wheel_jnt_eff_[i], virtual_rear_wheel_jnt_vel_cmd_[i]);
00394 }
00395
00396 for (int i = 0; i < virtual_front_wheel_jnt_names_.size(); i++)
00397 {
00398 this->RegisterInterfaceHandles(
00399 jnt_state_interface_, front_wheel_jnt_vel_cmd_interface_,
00400 virtual_front_wheel_jnt_names_[i], virtual_front_wheel_jnt_pos_[i], virtual_front_wheel_jnt_vel_[i], virtual_front_wheel_jnt_eff_[i], virtual_front_wheel_jnt_vel_cmd_[i]);
00401 }
00402 }
00403
00404 void SteerBotHardwareGazebo::RegisterSteerInterface()
00405 {
00406
00407 this->RegisterInterfaceHandles(
00408 jnt_state_interface_, front_steer_jnt_pos_cmd_interface_,
00409 front_steer_jnt_name_, front_steer_jnt_pos_, front_steer_jnt_vel_, front_steer_jnt_eff_, front_steer_jnt_pos_cmd_);
00410
00411
00412 for (int i = 0; i < virtual_front_steer_jnt_names_.size(); i++)
00413 {
00414 this->RegisterInterfaceHandles(
00415 jnt_state_interface_, front_steer_jnt_pos_cmd_interface_,
00416 virtual_front_steer_jnt_names_[i], virtual_front_steer_jnt_pos_[i], virtual_front_steer_jnt_vel_[i], virtual_front_steer_jnt_eff_[i], virtual_front_steer_jnt_pos_cmd_[i]);
00417 }
00418 }
00419
00420 void SteerBotHardwareGazebo::RegisterJointStateInterfaceHandle(
00421 hardware_interface::JointStateInterface& _jnt_state_interface,
00422 const std::string _jnt_name, double& _jnt_pos, double& _jnt_vel, double& _jnt_eff)
00423 {
00424 hardware_interface::JointStateHandle state_handle(_jnt_name,
00425 &_jnt_pos,
00426 &_jnt_vel,
00427 &_jnt_eff);
00428 _jnt_state_interface.registerHandle(state_handle);
00429
00430 ROS_INFO_STREAM("Registered joint '" << _jnt_name << " ' in the JointStateInterface");
00431 }
00432
00433 void SteerBotHardwareGazebo::RegisterCommandJointInterfaceHandle(
00434 hardware_interface::JointStateInterface& _jnt_state_interface,
00435 hardware_interface::JointCommandInterface& _jnt_cmd_interface,
00436 const std::string _jnt_name, double& _jnt_cmd)
00437 {
00438
00439 hardware_interface::JointHandle _handle(_jnt_state_interface.getHandle(_jnt_name),
00440 &_jnt_cmd);
00441 _jnt_cmd_interface.registerHandle(_handle);
00442
00443 ROS_INFO_STREAM("Registered joint '" << _jnt_name << " ' in the CommandJointInterface");
00444 }
00445
00446
00447 double SteerBotHardwareGazebo::ComputeEffCommandFromVelError(const int _index, ros::Duration _period)
00448 {
00449 double vel_error = rear_wheel_jnt_vel_cmd_ - virtual_rear_wheel_jnt_vel_[_index];
00450 ROS_DEBUG_STREAM("vel_error = " << vel_error);
00451 if(fabs(vel_error) < 0.1)
00452 {
00453 vel_error = 0.0;
00454 ROS_DEBUG_STREAM("too small. vel_error <- 0");
00455 }
00456 else
00457 ROS_DEBUG_STREAM("not small. ");
00458
00459 const double command = pids_[_index].computeCommand(vel_error, _period);
00460 ROS_DEBUG_STREAM("command =" << command);
00461
00462 const double effort_limit = 10.0;
00463 const double effort = clamp(command,
00464 -effort_limit, effort_limit);
00465 return effort;
00466 }
00467
00468 void SteerBotHardwareGazebo::GetCurrentState(std::vector<double>& _jnt_pos, std::vector<double>& _jnt_vel, std::vector<double>& _jnt_eff,
00469 const int _if_index, const int _sim_jnt_index)
00470 {
00471 _jnt_pos[_if_index] +=
00472 angles::shortest_angular_distance(_jnt_pos[_if_index], sim_joints_[_sim_jnt_index]->GetAngle(0u).Radian());
00473 _jnt_vel[_if_index] = sim_joints_[_sim_jnt_index]->GetVelocity(0u);
00474 _jnt_eff[_if_index] = sim_joints_[_sim_jnt_index]->GetForce(0u);
00475 }
00476
00477 }
00478
00479 PLUGINLIB_EXPORT_CLASS(steer_bot_hardware_gazebo::SteerBotHardwareGazebo, gazebo_ros_control::RobotHWSim)