quadrotor_hardware_gazebo.cpp
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2012-2016, Institute of Flight Systems and Automatic Control,
3 // Technische Universität Darmstadt.
4 // All rights reserved.
5 
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of hector_quadrotor nor the names of its contributors
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //=================================================================================================
28 
30 
31 #include <geometry_msgs/WrenchStamped.h>
32 
34 {
35 
37 {
44 
47 }
48 
50 {
51 
52 }
53 
55  const std::string &robot_namespace,
56  ros::NodeHandle model_nh,
57  gazebo::physics::ModelPtr parent_model,
58  const urdf::Model *const urdf_model,
59  std::vector<transmission_interface::TransmissionInfo> transmissions)
60 {
61  // store parent model pointer
62  model_ = parent_model;
63  link_ = model_->GetLink();
64 #if (GAZEBO_MAJOR_VERSION >= 8)
65  physics_ = model_->GetWorld()->Physics();
66 #else
67  physics_ = model_->GetWorld()->GetPhysicsEngine();
68 #endif
69 
70  model_nh.param<std::string>("world_frame", world_frame_, "world");
71  model_nh.param<std::string>("base_link_frame", base_link_frame_, "base_link");
72 
73  // subscribe state
74  std::string state_topic;
75  model_nh.getParam("state_topic", state_topic);
76  if (!state_topic.empty())
77  {
78  odom_sub_helper_ = boost::make_shared<OdomSubscriberHelper>(model_nh, state_topic, boost::ref(pose_),
79  boost::ref(twist_), boost::ref(acceleration_),
80  boost::ref(header_));
81  gzlog << "[hector_quadrotor_controller_gazebo] Using topic '" << state_topic << "' as state input for control" <<
82  std::endl;
83  }
84  else
85  {
86  gzlog << "[hector_quadrotor_controller_gazebo] Using ground truth from Gazebo as state input for control" <<
87  std::endl;
88  }
89 
90  // subscribe imu
91  std::string imu_topic;
92  model_nh.getParam("imu_topic", imu_topic);
93  if (!imu_topic.empty())
94  {
95  imu_sub_helper_ = boost::make_shared<ImuSubscriberHelper>(model_nh, imu_topic, boost::ref(imu_));
96  gzlog << "[hector_quadrotor_controller_gazebo] Using topic '" << imu_topic << "' as imu input for control" <<
97  std::endl;
98  }
99  else
100  {
101  gzlog << "[hector_quadrotor_controller_gazebo] Using ground truth from Gazebo as imu input for control" <<
102  std::endl;
103  }
104 
105  motor_status_.on = true;
106  motor_status_.header.frame_id = base_link_frame_;
107 
109 
110  wrench_limiter_.init(model_nh, "wrench_limits");
111 
112  wrench_command_publisher_ = model_nh.advertise<geometry_msgs::WrenchStamped>("command/wrench", 1);
113  motor_command_publisher_ = model_nh.advertise<geometry_msgs::WrenchStamped>("command/motor", 1);
114 
115  return true;
116 }
117 
119 {
120  // read state from Gazebo
121  const double acceleration_time_constant = 0.1;
122 #if (GAZEBO_MAJOR_VERSION >= 8)
123  gz_acceleration_ = ((link_->WorldLinearVel() - gz_velocity_) + acceleration_time_constant * gz_acceleration_) /
124  (period.toSec() + acceleration_time_constant);
126  ((link_->WorldLinearVel() - gz_angular_velocity_) + acceleration_time_constant * gz_angular_acceleration_) /
127  (period.toSec() + acceleration_time_constant);
128 
129  gz_pose_ = link_->WorldPose();
130  gz_velocity_ = link_->WorldLinearVel();
131  gz_angular_velocity_ = link_->WorldAngularVel();
132 #else
133  gz_acceleration_ = ((link_->GetWorldLinearVel() - gz_velocity_) + acceleration_time_constant * gz_acceleration_) /
134  (period.toSec() + acceleration_time_constant);
135  gz_angular_acceleration_ =
136  ((link_->GetWorldLinearVel() - gz_angular_velocity_) + acceleration_time_constant * gz_angular_acceleration_) /
137  (period.toSec() + acceleration_time_constant);
138 
139  gz_pose_ = link_->GetWorldPose();
140  gz_velocity_ = link_->GetWorldLinearVel();
141  gz_angular_velocity_ = link_->GetWorldAngularVel();
142 #endif
143 
144  // Use when Gazebo patches accel = 0 bug
145 // gz_acceleration_ = link_->GetWorldLinearAccel();
146 // gz_angular_acceleration_ = link_->GetWorldAngularAccel();
147 
148  if (!odom_sub_helper_)
149  {
150  header_.frame_id = world_frame_;
151  header_.stamp = time;
152 #if (GAZEBO_MAJOR_VERSION >= 8)
153  pose_.position.x = gz_pose_.Pos().X();
154  pose_.position.y = gz_pose_.Pos().Y();
155  pose_.position.z = gz_pose_.Pos().Z();
156  pose_.orientation.w = gz_pose_.Rot().W();
157  pose_.orientation.x = gz_pose_.Rot().X();
158  pose_.orientation.y = gz_pose_.Rot().Y();
159  pose_.orientation.z = gz_pose_.Rot().Z();
160  twist_.linear.x = gz_velocity_.X();
161  twist_.linear.y = gz_velocity_.Y();
162  twist_.linear.z = gz_velocity_.Z();
163  twist_.angular.x = gz_angular_velocity_.X();
164  twist_.angular.y = gz_angular_velocity_.Y();
165  twist_.angular.z = gz_angular_velocity_.Z();
166  acceleration_.linear.x = gz_acceleration_.X();
167  acceleration_.linear.y = gz_acceleration_.Y();
168  acceleration_.linear.z = gz_acceleration_.Z();
169  acceleration_.angular.x = gz_angular_acceleration_.X();
170  acceleration_.angular.y = gz_angular_acceleration_.Y();
171  acceleration_.angular.z = gz_angular_acceleration_.Z();
172 #else
173  pose_.position.x = gz_pose_.pos.x;
174  pose_.position.y = gz_pose_.pos.y;
175  pose_.position.z = gz_pose_.pos.z;
176  pose_.orientation.w = gz_pose_.rot.w;
177  pose_.orientation.x = gz_pose_.rot.x;
178  pose_.orientation.y = gz_pose_.rot.y;
179  pose_.orientation.z = gz_pose_.rot.z;
180  twist_.linear.x = gz_velocity_.x;
181  twist_.linear.y = gz_velocity_.y;
182  twist_.linear.z = gz_velocity_.z;
183  twist_.angular.x = gz_angular_velocity_.x;
184  twist_.angular.y = gz_angular_velocity_.y;
185  twist_.angular.z = gz_angular_velocity_.z;
186  acceleration_.linear.x = gz_acceleration_.x;
187  acceleration_.linear.y = gz_acceleration_.y;
188  acceleration_.linear.z = gz_acceleration_.z;
189  acceleration_.angular.x = gz_angular_acceleration_.x;
190  acceleration_.angular.y = gz_angular_acceleration_.y;
191  acceleration_.angular.z = gz_angular_acceleration_.z;
192 #endif
193  }
194 
195  if (!imu_sub_helper_)
196  {
197 #if (GAZEBO_MAJOR_VERSION >= 8)
198  imu_.orientation.w = gz_pose_.Rot().W();
199  imu_.orientation.x = gz_pose_.Rot().X();
200  imu_.orientation.y = gz_pose_.Rot().Y();
201  imu_.orientation.z = gz_pose_.Rot().Z();
202 
203  ignition::math::Vector3d gz_angular_velocity_body = gz_pose_.Rot().RotateVectorReverse(gz_angular_velocity_);
204  imu_.angular_velocity.x = gz_angular_velocity_body.X();
205  imu_.angular_velocity.y = gz_angular_velocity_body.Y();
206  imu_.angular_velocity.z = gz_angular_velocity_body.Z();
207 
208  ignition::math::Vector3d gz_linear_acceleration_body = gz_pose_.Rot().RotateVectorReverse(
209  gz_acceleration_ - model_->GetWorld()->Gravity());
210  imu_.linear_acceleration.x = gz_linear_acceleration_body.X();
211  imu_.linear_acceleration.y = gz_linear_acceleration_body.Y();
212  imu_.linear_acceleration.z = gz_linear_acceleration_body.Z();
213 #else
214  imu_.orientation.w = gz_pose_.rot.w;
215  imu_.orientation.x = gz_pose_.rot.x;
216  imu_.orientation.y = gz_pose_.rot.y;
217  imu_.orientation.z = gz_pose_.rot.z;
218 
219  gazebo::math::Vector3 gz_angular_velocity_body = gz_pose_.rot.RotateVectorReverse(gz_angular_velocity_);
220  imu_.angular_velocity.x = gz_angular_velocity_body.x;
221  imu_.angular_velocity.y = gz_angular_velocity_body.y;
222  imu_.angular_velocity.z = gz_angular_velocity_body.z;
223 
224  gazebo::math::Vector3 gz_linear_acceleration_body = gz_pose_.rot.RotateVectorReverse(
225  gz_acceleration_ - physics_->GetGravity());
226  imu_.linear_acceleration.x = gz_linear_acceleration_body.x;
227  imu_.linear_acceleration.y = gz_linear_acceleration_body.y;
228  imu_.linear_acceleration.z = gz_linear_acceleration_body.z;
229 #endif
230  }
231 }
232 
234 {
235  bool result_written = false;
236 
237  if (motor_output_->connected() && motor_output_->enabled()) {
239  result_written = true;
240  }
241 
242  if (wrench_output_->connected() && wrench_output_->enabled()) {
243  geometry_msgs::WrenchStamped wrench;
244  wrench.header.stamp = time;
245  wrench.header.frame_id = base_link_frame_;
246 
247  if (motor_status_.on && motor_status_.running) {
248  wrench.wrench = wrench_limiter_(wrench_output_->getCommand());
249 
250  if (!result_written) {
251 #if (GAZEBO_MAJOR_VERSION >= 8)
252  ignition::math::Vector3d force(wrench.wrench.force.x, wrench.wrench.force.y, wrench.wrench.force.z);
253  ignition::math::Vector3d torque(wrench.wrench.torque.x, wrench.wrench.torque.y, wrench.wrench.torque.z);
254 #else
255  gazebo::math::Vector3 force(wrench.wrench.force.x, wrench.wrench.force.y, wrench.wrench.force.z);
256  gazebo::math::Vector3 torque(wrench.wrench.torque.x, wrench.wrench.torque.y, wrench.wrench.torque.z);
257 #endif
258  link_->AddRelativeForce(force);
259 #if (GAZEBO_MAJOR_VERSION >= 8)
260  link_->AddRelativeTorque(torque - link_->GetInertial()->CoG().Cross(force));
261 #else
262  link_->AddRelativeTorque(torque - link_->GetInertial()->GetCoG().Cross(force));
263 #endif
264  }
265 
266  } else {
267  wrench.wrench = geometry_msgs::Wrench();
268  }
269 
271  }
272 }
273 
274 bool QuadrotorHardwareSim::enableMotorsCallback(hector_uav_msgs::EnableMotors::Request &req, hector_uav_msgs::EnableMotors::Response &res)
275 {
276  res.success = enableMotors(req.enable);
277  return true;
278 }
279 
281 {
282  motor_status_.running = enable;
283  return true;
284 }
285 
286 } // namespace hector_quadrotor_controller_gazebo
287 
void registerPose(geometry_msgs::Pose *pose)
void publish(const boost::shared_ptr< M > &message) const
virtual void writeSim(ros::Time time, ros::Duration period)
void init(const ros::NodeHandle &nh, const std::string &field=std::string())
void registerMotorStatus(hector_uav_msgs::MotorStatus *motor_status)
boost::shared_ptr< HandleType > addInput(const std::string &name)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
hector_quadrotor_interface::WrenchLimiter wrench_limiter_
boost::shared_ptr< hector_quadrotor_interface::ImuSubscriberHelper > imu_sub_helper_
boost::shared_ptr< hector_quadrotor_interface::OdomSubscriberHelper > odom_sub_helper_
bool param(const std::string &param_name, T &param_val, const T &default_val) const
virtual void readSim(ros::Time time, ros::Duration period)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void registerTwist(geometry_msgs::Twist *twist)
virtual bool initSim(const std::string &robot_namespace, ros::NodeHandle model_nh, gazebo::physics::ModelPtr parent_model, const urdf::Model *const urdf_model, std::vector< transmission_interface::TransmissionInfo > transmissions)
bool getParam(const std::string &key, std::string &s) const
bool enableMotorsCallback(hector_uav_msgs::EnableMotors::Request &req, hector_uav_msgs::EnableMotors::Response &res)
void registerAccel(geometry_msgs::Accel *accel)
PLUGINLIB_EXPORT_CLASS(transmission_interface::BiDirectionalEffortJointInterfaceProvider, transmission_interface::RequisiteProvider)
void registerSensorImu(sensor_msgs::Imu *imu)


hector_quadrotor_controller_gazebo
Author(s): Johannes Meyer
autogenerated on Mon Jun 10 2019 13:36:51