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
00032 void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
00033 {
00034
00035 this->model_ = _parent;
00036
00037
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
00044 this->ros_node_ = new ros::NodeHandle("");
00045
00046 this->deferred_load_thread_ = boost::thread(boost::bind(&LIPPlugin::DeferredLoad, this));
00047 }
00048
00049 void DeferredLoad() {
00050
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
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
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
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
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
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
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
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
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
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
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
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
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
00168 void OnUpdate(const common::UpdateInfo & )
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 }