LIPPlugin.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <stdio.h>
00003 
00004 #include <boost/bind.hpp>
00005 #include <gazebo/gazebo.hh>
00006 #include <gazebo/physics/physics.hh>
00007 #include <gazebo/common/common.hh>
00008 
00009 #include <ros/ros.h>
00010 #include <ros/callback_queue.h>
00011 #include <ros/advertise_options.h>
00012 #include <ros/subscribe_options.h>
00013 
00014 #include <geometry_msgs/Twist.h>
00015 #include <geometry_msgs/Pose.h>
00016 #include <geometry_msgs/Vector3.h>
00017 #include <geometry_msgs/Wrench.h>
00018 #include <std_msgs/String.h>
00019 #include "hrpsys_gazebo_msgs/LIPState.h"
00020 #include "hrpsys_gazebo_msgs/LIPSetState.h"
00021 #include "hrpsys_gazebo_msgs/LIPSwitchFoot.h"
00022 
00023 #include "PubQueue.h"
00024 
00025 namespace gazebo
00026 {
00027   class LIPPlugin : public ModelPlugin
00028   {
00029 
00030   public:
00031     // Initialize
00032     void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
00033     {
00034       // Store the pointer to the model
00035       this->model_ = _parent;
00036 
00037       // Make sure the ROS node for Gazebo has already been initialized
00038       if (!ros::isInitialized()) {
00039         gzerr << "A ROS node for Gazebo has not been initialized, unable to load plugin. "
00040               << "Load the Gazebo system plugin 'libgazebo_ros_api_plugin.so' in the gazebo_ros package)";
00041         return;
00042       }
00043       // ros node
00044       this->ros_node_ = new ros::NodeHandle("");
00045       // ros callback queue for processing subscription
00046       this->deferred_load_thread_ = boost::thread(boost::bind(&LIPPlugin::DeferredLoad, this));
00047     }
00048 
00049     void DeferredLoad() {
00050       // initialize variables
00051       std::string base_link_name = "LINK0_link";
00052       std::string mass_link_name = "LINK4_link";
00053       std::string root_x_joint_name = "JOINT0";
00054       std::string root_y_joint_name = "JOINT1";
00055       std::string linear_joint_name = "JOINT2";
00056       // base_link
00057       this->base_link_ = this->model_->GetLink(base_link_name);
00058       if(!this->base_link_) {
00059         gzerr << "Base link is not found. (link_name is "<< base_link_name << ")" << std::endl;
00060         return;
00061       }
00062       // mass_link
00063       this->mass_link_ = this->model_->GetLink(mass_link_name);
00064       if(!this->mass_link_) {
00065         gzerr << "Mass link is not found. (link_name is "<< mass_link_name << ")" << std::endl;
00066         return;
00067       }
00068       // root_x_joint
00069       this->root_x_joint_ = this->model_->GetJoint(root_x_joint_name);
00070       if(!this->root_x_joint_) {
00071         gzerr << "Root X joint is not found. (joint_name is "<< root_x_joint_name << ")" << std::endl;
00072         return;
00073       }
00074       // root_y_joint
00075       this->root_y_joint_ = this->model_->GetJoint(root_y_joint_name);
00076       if(!this->root_y_joint_) {
00077         gzerr << "Root Y joint is not found. (joint_name is "<< root_y_joint_name << ")" << std::endl;
00078         return;
00079       }
00080       // linear_joint
00081       this->linear_joint_ = this->model_->GetJoint(linear_joint_name);
00082       if(!this->linear_joint_) {
00083         gzerr << "Linear joint is not found. (joint_name is "<< linear_joint_name << ")" << std::endl;
00084         return;
00085       }
00086 
00087       // Publish multi queue
00088       this->pmq_.startServiceThread();
00089       this->state_pub_queue_ = this->pmq_.addPub<hrpsys_gazebo_msgs::LIPState>();
00090       this->state_pub_ = this->ros_node_->advertise<hrpsys_gazebo_msgs::LIPState>("LIP/state", 100, true);
00091 
00092       // Initialize service server
00093       ros::AdvertiseServiceOptions switch_foot_srv_option =
00094         ros::AdvertiseServiceOptions::create<hrpsys_gazebo_msgs::LIPSwitchFoot> ("LIP/switch_foot", boost::bind(&LIPPlugin::SwitchFootCallback, this, _1, _2),
00095                                                                                         ros::VoidPtr(), &this->service_queue_);
00096       this->switch_foot_srv_ = this->ros_node_->advertiseService(switch_foot_srv_option);
00097       ros::AdvertiseServiceOptions set_state_srv_option =
00098         ros::AdvertiseServiceOptions::create<hrpsys_gazebo_msgs::LIPSetState> ("LIP/set_state", boost::bind(&LIPPlugin::SetStateCallback, this, _1, _2),
00099                                                                                         ros::VoidPtr(), &this->service_queue_);
00100       this->set_state_srv_ = this->ros_node_->advertiseService(set_state_srv_option);
00101 
00102       // Listen to the update event
00103       this->update_connection_ = event::Events::ConnectWorldUpdateBegin(boost::bind(&LIPPlugin::OnUpdate, this, _1));
00104       this->service_callback_thread_ = boost::thread(boost::bind(&LIPPlugin::ServiceCallbackThread, this));
00105 
00106       gzmsg << "LIPPlugin was loaded !" << std::endl;
00107     }
00108 
00109     void ServiceCallbackThread() {
00110       while (this->ros_node_->ok()) {
00111         this->service_queue_.callAvailable();
00112       }
00113     }
00114 
00115     bool SwitchFootCallback(hrpsys_gazebo_msgs::LIPSwitchFootRequest &req, hrpsys_gazebo_msgs::LIPSwitchFootResponse &res)
00116     {
00117       math::Pose base_pose(req.command.foot_position.x, req.command.foot_position.y, req.command.foot_position.z, 0, 0, 0);
00118       math::Pose mass_pose;
00119       math::Vector3 mass_velocity(req.command.mass_velocity.x, req.command.mass_velocity.y, req.command.mass_velocity.z);
00120 
00121       mass_pose = this->mass_link_->GetWorldPose();
00122       if (req.command.keep_mass_velocity) {
00123         mass_velocity = this->mass_link_->GetWorldLinearVel();
00124       }
00125 
00126       ROS_INFO_STREAM_THROTTLE(1.0, "[LIP command]  switch foot command" << std::endl
00127                                << "  foot_pos: " << base_pose.pos << std::endl
00128                                << "  mass_vel: (keep: " << bool(req.command.keep_mass_velocity) << ") " << mass_velocity);
00129 
00130       // reset force and velocity
00131       this->linear_joint_->SetForce(0, 0);
00132       this->root_x_joint_->SetVelocity(0, 0);
00133       this->root_y_joint_->SetVelocity(0, 0);
00134       this->linear_joint_->SetVelocity(0, 0);
00135       // set position and velocity
00136       this->model_->SetWorldPose(base_pose, this->base_link_);
00137       this->mass_link_->SetWorldPose(mass_pose);
00138       this->mass_link_->SetLinearVel(mass_velocity);
00139 
00140       return true;
00141     }
00142 
00143     bool SetStateCallback(hrpsys_gazebo_msgs::LIPSetStateRequest &req, hrpsys_gazebo_msgs::LIPSetStateResponse &res)
00144     {
00145       math::Pose base_pose(req.command.foot_position.x, req.command.foot_position.y, req.command.foot_position.z, 0, 0, 0);
00146       math::Pose mass_pose(req.command.mass_position.x, req.command.mass_position.y, req.command.mass_position.z, 0, 0, 0);
00147       math::Vector3 mass_velocity(req.command.mass_velocity.x, req.command.mass_velocity.y, req.command.mass_velocity.z);
00148 
00149       ROS_INFO_STREAM_THROTTLE(1.0, "[LIP command]  set state command" << std::endl
00150                                << "  foot_pos: " << base_pose.pos << std::endl
00151                                << "  mass_pos: " << mass_pose.pos << std::endl
00152                                << "  mass_vel: " << mass_velocity);
00153 
00154       // reset force and velocity
00155       this->linear_joint_->SetForce(0, 0);
00156       this->root_x_joint_->SetVelocity(0, 0);
00157       this->root_y_joint_->SetVelocity(0, 0);
00158       this->linear_joint_->SetVelocity(0, 0);
00159       // set position and velocity
00160       this->model_->SetWorldPose(base_pose, this->base_link_);
00161       this->mass_link_->SetWorldPose(mass_pose);
00162       this->mass_link_->SetLinearVel(mass_velocity);
00163 
00164       return true;
00165     }
00166 
00167     // Called by the world update start event
00168     void OnUpdate(const common::UpdateInfo & /*_info*/)
00169     {
00170       addForce();
00171       publishState();
00172     }
00173 
00174     void addForce()
00175     {
00176       math::Pose base_pose = this->base_link_->GetWorldPose();;
00177       math::Pose mass_pose = this->mass_link_->GetWorldPose();;
00178       double mass_z = mass_pose.pos.z;
00179       double mass_length = (base_pose.pos - mass_pose.pos).GetLength();
00180       double mass = this->mass_link_->GetInertial()->GetMass();
00181       double gravity = 9.81;
00182       double force = mass * gravity * mass_length / mass_z;
00183       double force_limit = this->linear_joint_->GetEffortLimit(0);
00184       force = math::clamp(force, -force_limit, force_limit);
00185 
00186       ROS_INFO_STREAM_THROTTLE(1.0, "[LIP control]  " << "mg: " << mass * gravity << "  z: " << mass_z << "  l: " << mass_length << "  f: " << force);
00187 
00188       this->linear_joint_->SetForce(0, force);
00189     }
00190 
00191     void publishState()
00192     {
00193       hrpsys_gazebo_msgs::LIPState state;
00194       math::Pose base_pose = this->base_link_->GetWorldPose();;
00195       math::Pose mass_pose = this->mass_link_->GetWorldPose();;
00196       math::Vector3 mass_velocity = this->mass_link_->GetWorldLinearVel();
00197 
00198       std_msgs::Header tmp_header;
00199       tmp_header.stamp = ros::Time::now();
00200       state.header = tmp_header;
00201 
00202       state.foot_position.x = base_pose.pos.x;
00203       state.foot_position.y = base_pose.pos.y;
00204       state.foot_position.z = base_pose.pos.z;
00205 
00206       state.mass_position.x = mass_pose.pos.x;
00207       state.mass_position.y = mass_pose.pos.y;
00208       state.mass_position.z = mass_pose.pos.z;
00209 
00210       state.mass_velocity.x = mass_velocity.x;
00211       state.mass_velocity.y = mass_velocity.y;
00212       state.mass_velocity.z = mass_velocity.z;
00213 
00214       this->state_pub_queue_->push(state, this->state_pub_);
00215     }
00216 
00217   private:
00218     physics::ModelPtr model_;
00219     event::ConnectionPtr update_connection_;
00220 
00221     ros::NodeHandle* ros_node_;
00222     PubMultiQueue pmq_;
00223 
00224     boost::thread deferred_load_thread_;
00225     boost::thread service_callback_thread_;
00226 
00227     ros::Publisher state_pub_;
00228     PubQueue<hrpsys_gazebo_msgs::LIPState>::Ptr state_pub_queue_;
00229 
00230     ros::ServiceServer switch_foot_srv_;
00231     ros::ServiceServer set_state_srv_;
00232 
00233     physics::LinkPtr base_link_;
00234     physics::LinkPtr mass_link_;
00235     physics::JointPtr root_x_joint_;
00236     physics::JointPtr root_y_joint_;
00237     physics::JointPtr linear_joint_;
00238 
00239     ros::CallbackQueue service_queue_;
00240   };
00241 
00242   GZ_REGISTER_MODEL_PLUGIN(LIPPlugin)
00243 }


hrpsys_gazebo_general
Author(s): Yohei Kakiuchi , Kei Okada , Masaki Murooka
autogenerated on Thu Jun 6 2019 20:56:53