PageRenderTime 28ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/telerob_worlds/src/dexterity_test_plugin.cpp

https://bitbucket.org/telerobcar/telerobcar-ros-pkg
C++ | 304 lines | 214 code | 15 blank | 75 comment | 24 complexity | f368e4e185ebe0b4357855c48b09c41e MD5 | raw file
  1. /*********************************************************************
  2. * Software License Agreement (BSD License)
  3. *
  4. * Copyright (c) 2013
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. * * Neither the name of the Open Source Robotics Foundation
  18. * nor the names of its contributors may be
  19. * used to endorse or promote products derived
  20. * from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  30. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *********************************************************************/
  35. /**
  36. * \author Francisco Suarez Ruiz
  37. * \desc Plugin for the dexterity test
  38. */
  39. #include <ros/ros.h>
  40. #include <boost/thread.hpp>
  41. #include <boost/thread/mutex.hpp>
  42. #include <gazebo/physics/physics.hh>
  43. #include <gazebo/transport/TransportTypes.hh>
  44. #include <gazebo/common/Time.hh>
  45. #include <gazebo/common/Plugin.hh>
  46. #include <gazebo/common/Events.hh>
  47. using std::endl;
  48. namespace gazebo
  49. {
  50. class DexterityTest : public ModelPlugin
  51. {
  52. private:
  53. physics::WorldPtr world_;
  54. physics::ModelPtr model_;
  55. physics::Joint_V joints_;
  56. physics::Link_V links_;
  57. event::ConnectionPtr update_connection_;
  58. common::Time last_time_;
  59. // Poses of the anchors
  60. std::vector<math::Pose> wall_anchor_;
  61. std::vector<math::Pose> back_anchor_;
  62. std::vector<math::Pose> shaft_anchor_;
  63. /* Constructor */
  64. public: DexterityTest() : ModelPlugin() {
  65. }
  66. /* Destructor */
  67. public: virtual ~DexterityTest()
  68. {
  69. event::Events::DisconnectWorldUpdateBegin(this->update_connection_);
  70. }
  71. /* Load the plugin */
  72. public: void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
  73. {
  74. int i;
  75. // Store the pointer to the model and world
  76. this->model_ = _parent;
  77. this->world_ = model_->GetWorld();
  78. // Get joints and links
  79. this->joints_ = this->model_->GetJoints();
  80. this->links_ = this->model_->GetLinks();
  81. /* Debug msg joints and links names
  82. for (i = 0; i < this->joints_.size(); i++)
  83. gzdbg << "Joint " << i << ": " << this->joints_[i]->GetName() << endl;
  84. for (i = 0; i < this->links_.size(); i++)
  85. gzdbg << "Link " << i << ": " << this->links_[i]->GetName() << endl;*/
  86. // Load parameters
  87. if (!_sdf->HasElement("wall_anchor_1")) {
  88. gzerr << "dexterity_test_plugin missing <wall_anchor_1>" << endl;
  89. return; }
  90. else
  91. this->wall_anchor_.push_back(_sdf->GetElement("wall_anchor_1")->Get<math::Pose>());
  92. if (!_sdf->HasElement("wall_anchor_2")) {
  93. gzerr << "dexterity_test_plugin missing <wall_anchor_2>" << endl;
  94. return; }
  95. else
  96. this->wall_anchor_.push_back(_sdf->GetElement("wall_anchor_2")->Get<math::Pose>());
  97. if (!_sdf->HasElement("wall_anchor_3")) {
  98. gzerr << "dexterity_test_plugin missing <wall_anchor_3>" << endl;
  99. return; }
  100. else
  101. this->wall_anchor_.push_back(_sdf->GetElement("wall_anchor_3")->Get<math::Pose>());
  102. if (!_sdf->HasElement("wall_anchor_4")) {
  103. gzerr << "dexterity_test_plugin missing <wall_anchor_4>" << endl;
  104. return; }
  105. else
  106. this->wall_anchor_.push_back(_sdf->GetElement("wall_anchor_4")->Get<math::Pose>());
  107. if (!_sdf->HasElement("back_anchor_1")) {
  108. gzerr << "dexterity_test_plugin missing <back_anchor_1>" << endl;
  109. return; }
  110. else
  111. this->back_anchor_.push_back(_sdf->GetElement("back_anchor_1")->Get<math::Pose>());
  112. if (!_sdf->HasElement("back_anchor_2")) {
  113. gzerr << "dexterity_test_plugin missing <back_anchor_2>" << endl;
  114. return; }
  115. else
  116. this->back_anchor_.push_back(_sdf->GetElement("back_anchor_2")->Get<math::Pose>());
  117. if (!_sdf->HasElement("shaft_anchor_1")) {
  118. gzerr << "dexterity_test_plugin missing <shaft_anchor_1>" << endl;
  119. return; }
  120. else
  121. this->shaft_anchor_.push_back(_sdf->GetElement("shaft_anchor_1")->Get<math::Pose>());
  122. if (!_sdf->HasElement("shaft_anchor_2")) {
  123. gzerr << "dexterity_test_plugin missing <shaft_anchor_2>" << endl;
  124. return; }
  125. else
  126. this->shaft_anchor_.push_back(_sdf->GetElement("shaft_anchor_2")->Get<math::Pose>());
  127. // Make sure the ROS node for Gazebo has already been initialized
  128. if (!ros::isInitialized())
  129. {
  130. gzerr << "A ROS node for Gazebo has not been initialized, unable to load plugin. "
  131. << "Load the Gazebo system plugin 'libgazebo_ros_api_plugin.so' in the gazebo_ros package)" << endl;
  132. return;
  133. }
  134. // Reset Time
  135. this->last_time_ = this->world_->GetSimTime();
  136. // Listen to the update event. This event is broadcast every
  137. // simulation iteration.
  138. this->update_connection_ = event::Events::ConnectWorldUpdateBegin(
  139. boost::bind(&DexterityTest::UpdateChild, this));
  140. this->BlueMsg("dexterity_test_plugin successfully loaded!");
  141. }
  142. /* Update the plugin */
  143. private: void UpdateChild()
  144. {
  145. common::Time current_time = this->world_->GetSimTime();
  146. if (current_time > this->last_time_)
  147. {
  148. this->CheckJointCreation();
  149. }
  150. }
  151. /* Check the joints creation and removal */
  152. bool CheckJointCreation()
  153. {
  154. int min_idx, joint_idx;
  155. double position;
  156. std::vector<double> pos_error, rot_error;
  157. pos_error.resize(this->wall_anchor_.size());
  158. rot_error.resize(this->wall_anchor_.size());
  159. // left joint
  160. /* For debugging you can push the link up
  161. this->links_[2]->SetLinearVel(math::Vector3(0, 0, 0.1)); */
  162. joint_idx = 2;
  163. if (!this->joints_[joint_idx])
  164. {
  165. min_idx = this->ClosestAnchor(joint_idx, pos_error, rot_error, this->wall_anchor_);
  166. // Tolerance: position in meters, rotation in ¿radians?
  167. if (pos_error[min_idx] < 0.0025 && rot_error[min_idx] < 0.01)
  168. {
  169. this->joints_[joint_idx] = this->AddJoint(this->world_, this->model_,
  170. this->links_[0], this->links_[joint_idx],
  171. "prismatic",
  172. math::Pose(0, 0, 0, 0, 0, 0),
  173. math::Vector3(0, 0, 1),
  174. 0.015, -0.04);
  175. }
  176. }
  177. else
  178. {
  179. // check joint position to disconnect
  180. position = this->joints_[joint_idx]->GetAngle(0).Radian();
  181. if (position > 0.01)
  182. this->RemoveJoint(this->joints_[joint_idx]);
  183. }
  184. // right joint
  185. joint_idx = 3;
  186. if (!this->joints_[joint_idx])
  187. {
  188. min_idx = this->ClosestAnchor(joint_idx, pos_error, rot_error, this->wall_anchor_);
  189. // Tolerance: position in meters, rotation in ¿radians?
  190. if (pos_error[min_idx] < 0.0025 && rot_error[min_idx] < 0.01)
  191. {
  192. this->joints_[joint_idx] = this->AddJoint(this->world_, this->model_,
  193. this->links_[0], this->links_[joint_idx],
  194. "prismatic",
  195. math::Pose(0, 0, 0, 0, 0, 0),
  196. math::Vector3(0, 0, 1),
  197. 0.015, -0.04);
  198. }
  199. }
  200. else
  201. {
  202. // check joint position to disconnect
  203. position = this->joints_[joint_idx]->GetAngle(0).Radian();
  204. if (position > 0.01)
  205. this->RemoveJoint(this->joints_[joint_idx]);
  206. }
  207. // back joint
  208. joint_idx = 4;
  209. if (!this->joints_[joint_idx])
  210. {
  211. min_idx = this->ClosestAnchor(joint_idx, pos_error, rot_error, this->wall_anchor_);
  212. // Tolerance: position in meters, rotation in ¿radians?
  213. if (pos_error[min_idx] < 0.0025 && rot_error[min_idx] < 0.01)
  214. {
  215. this->joints_[joint_idx] = this->AddJoint(this->world_, this->model_,
  216. this->links_[0], this->links_[joint_idx],
  217. "prismatic",
  218. math::Pose(0, 0, 0, 0, 0, 0),
  219. math::Vector3(0, 0, 1),
  220. 0.015, -0.024);
  221. }
  222. }
  223. else
  224. {
  225. // check joint position to disconnect
  226. position = this->joints_[joint_idx]->GetAngle(0).Radian();
  227. if (position > 0.01)
  228. this->RemoveJoint(this->joints_[joint_idx]);
  229. }
  230. return true;
  231. }
  232. /* Dynamically add joint between 2 links */
  233. private: physics::JointPtr AddJoint(physics::WorldPtr _world,
  234. physics::ModelPtr _model,
  235. physics::LinkPtr _parent,
  236. physics::LinkPtr _child,
  237. std::string _type,
  238. math::Pose _pose,
  239. math::Vector3 _axis,
  240. double _upper, double _lower)
  241. {
  242. physics::JointPtr joint = _world->GetPhysicsEngine()->CreateJoint(
  243. _type, _model);
  244. joint->Attach(_parent, _child);
  245. // load adds the joint to a vector of shared pointers kept
  246. // in parent and child links, preventing joint from being destroyed.
  247. joint->Load(_parent, _child, _pose);
  248. joint->SetAxis(0, _axis);
  249. joint->SetHighStop(0, _upper);
  250. joint->SetLowStop(0, _lower);
  251. joint->SetName(_child->GetName() + "_joint");
  252. joint->Init();
  253. // disable collision between the link pair
  254. _parent->SetCollideMode("fixed");
  255. _child->SetCollideMode("fixed");
  256. return joint;
  257. }
  258. /* Remove a joint */
  259. private: void RemoveJoint(physics::JointPtr &_joint)
  260. {
  261. if (_joint)
  262. {
  263. // enable collision of the child link
  264. physics::LinkPtr child = _joint->GetChild();
  265. child->SetCollideMode("all");
  266. _joint->Detach();
  267. _joint.reset();
  268. }
  269. }
  270. /* Gives the index of the lower position error with respect to a vector of anchors */
  271. private: int ClosestAnchor(int _link_idx, std::vector<double>& _pos_err,
  272. std::vector<double>& _rot_err, std::vector<math::Pose> _anchors)
  273. {
  274. math::Pose link_pose = this->links_[_link_idx]->GetWorldPose() - this->model_->GetWorldPose();
  275. for (int i = 0; i < _anchors.size(); i++)
  276. {
  277. _pos_err[i] = (_anchors[i].pos - link_pose.pos).GetLength();
  278. _rot_err[i] = (_anchors[i].rot.GetZAxis() - link_pose.rot.GetZAxis()).GetLength();
  279. }
  280. return std::min_element(_pos_err.begin(), _pos_err.end()) - _pos_err.begin();
  281. }
  282. /* Custom log messages */
  283. private: void BlueMsg(std::string msg) {
  284. gzmsg << "\033[94m" << msg << "\033[0m" << endl; }
  285. private: void GreenMsg(std::string msg) {
  286. gzmsg << "\033[92m" << msg << "\033[0m" << endl; }
  287. };
  288. GZ_REGISTER_MODEL_PLUGIN(DexterityTest)
  289. }