imarker_end_effector.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2016, University of Colorado, Boulder
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 PickNik LLC nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Dave Coleman
36  Desc: Class to encapsule a visualized robot state that can be controlled using an interactive marker
37 */
38 
39 // Boost
40 #include <boost/filesystem.hpp>
41 
42 // C++
43 #include <string>
44 
45 // Conversions
48 
49 // this package
52 
53 namespace moveit_visual_tools
54 {
55 IMarkerEndEffector::IMarkerEndEffector(IMarkerRobotState* imarker_parent, const std::string& imarker_name,
56  ArmData arm_data, rviz_visual_tools::colors color)
57  : name_(imarker_name)
58  , imarker_parent_(imarker_parent)
59  , psm_(imarker_parent_->psm_)
60  , arm_data_(arm_data)
61  , color_(color)
62  , imarker_server_(imarker_parent_->imarker_server_)
63  , imarker_state_(imarker_parent_->imarker_state_)
64  , visual_tools_(imarker_parent_->visual_tools_)
65 {
66  // Get pose from robot state
67  imarker_pose_ = imarker_state_->getGlobalLinkTransform(arm_data_.ee_link_);
68 
69  // Create imarker
71 
72  ROS_INFO_STREAM_NAMED(name_, "IMarkerEndEffector '" << name_ << "' tracking ee link '"
73  << arm_data_.ee_link_->getName() << "' ready.");
74 }
75 
76 void IMarkerEndEffector::getPose(Eigen::Affine3d& pose)
77 {
78  pose = imarker_pose_;
79 }
80 
82 {
83  imarker_pose_ = imarker_state_->getGlobalLinkTransform(arm_data_.ee_link_);
84 
86 
87  return true;
88 }
89 
90 void IMarkerEndEffector::iMarkerCallback(const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback)
91 {
92  if (feedback->event_type == visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP)
93  {
94  // Save pose to file if its been long enough
95  double save_every_sec = 0.1;
96  if (time_since_last_save_ < ros::Time::now() - ros::Duration(save_every_sec))
97  {
100  }
101  return;
102  }
103 
104  // Ignore if not pose update
105  if (feedback->event_type != visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE)
106  return;
107 
108  // Only allow one feedback to be processed at a time
109  {
110  // boost::unique_lock<boost::mutex> scoped_lock(imarker_mutex_);
111  if (imarker_ready_to_process_ == false)
112  {
113  return;
114  }
116  }
117 
118  // Convert
119  Eigen::Affine3d robot_ee_pose;
120  tf::poseMsgToEigen(feedback->pose, robot_ee_pose);
121 
122  // Update robot
123  solveIK(robot_ee_pose);
124 
125  // Redirect to base class
126  if (imarker_callback_)
127  imarker_callback_(feedback, robot_ee_pose);
128 
129  // Allow next feedback to be processed
130  {
131  // boost::unique_lock<boost::mutex> scoped_lock(imarker_mutex_);
133  }
134 }
135 
136 void IMarkerEndEffector::solveIK(Eigen::Affine3d& pose)
137 {
138  // Cartesian settings
139  const std::size_t attempts = 2;
140  const double timeout = 1.0 / 30.0; // 30 fps
141 
142  // Optionally collision check
145  {
146  // TODO(davetcoleman): this is currently not working, the locking seems to cause segfaults
147  boost::scoped_ptr<planning_scene_monitor::LockedPlanningSceneRO> ls;
149  constraint_fn = boost::bind(&isStateValid, static_cast<const planning_scene::PlanningSceneConstPtr&>(*ls).get(),
151  }
152 
153  // Attempt to set robot to new pose
154  if (imarker_state_->setFromIK(arm_data_.jmg_, pose, arm_data_.ee_link_->getName(), attempts, timeout, constraint_fn))
155  {
156  imarker_state_->update();
157  // if (psm_->getPlanningScene()->isStateValid(*imarker_state_))
158  //{
159  // ROS_INFO_STREAM_NAMED(name_, "Solved IK");
161  //}
162  // else
163  // {
164  // visual_tools_->publishRobotState(imarker_state_, rviz_visual_tools::RED);
165  // exit(0);
166  // }
167  }
168 }
169 
171 {
172  // Convert
173  geometry_msgs::Pose pose_msg;
175 
176  // marker
177  make6DofMarker(pose_msg);
178 }
179 
180 void IMarkerEndEffector::updateIMarkerPose(const Eigen::Affine3d& pose)
181 {
182  // Move marker to tip of fingers
183  // imarker_pose_ = pose * imarker_offset_.inverse();
185 }
186 
188 {
189  // Convert
190  geometry_msgs::Pose pose_msg;
192 
193  imarker_server_->setPose(int_marker_.name, pose_msg);
194  imarker_server_->applyChanges();
195 }
196 
197 void IMarkerEndEffector::make6DofMarker(const geometry_msgs::Pose& pose)
198 {
199  ROS_DEBUG_STREAM_NAMED(name_, "Making 6dof interactive marker named " << name_);
200 
201  int_marker_.header.frame_id = "world";
202  int_marker_.pose = pose;
203  int_marker_.scale = 0.2;
204 
205  int_marker_.name = name_;
206  // int_marker_.description = "imarker_" + name_; // TODO: unsure, but I think this causes a caption in Rviz that I
207  // don't want
208 
209  // insert a box
210  // makeBoxControl(int_marker_);
211 
212  // int_marker_.controls[0].interaction_mode = InteractiveMarkerControl::MENU;
213 
214  InteractiveMarkerControl control;
215  control.orientation.w = 1;
216  control.orientation.x = 1;
217  control.orientation.y = 0;
218  control.orientation.z = 0;
219  control.name = "rotate_x";
220  control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
221  int_marker_.controls.push_back(control);
222  control.name = "move_x";
223  control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
224  int_marker_.controls.push_back(control);
225 
226  control.orientation.w = 1;
227  control.orientation.x = 0;
228  control.orientation.y = 1;
229  control.orientation.z = 0;
230  control.name = "rotate_z";
231  control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
232  int_marker_.controls.push_back(control);
233  control.name = "move_z";
234  control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
235  int_marker_.controls.push_back(control);
236 
237  control.orientation.w = 1;
238  control.orientation.x = 0;
239  control.orientation.y = 0;
240  control.orientation.z = 1;
241  control.name = "rotate_y";
242  control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
243  int_marker_.controls.push_back(control);
244  control.name = "move_y";
245  control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
246  int_marker_.controls.push_back(control);
247 
248  imarker_server_->insert(int_marker_);
249  imarker_server_->setCallback(int_marker_.name, boost::bind(&IMarkerEndEffector::iMarkerCallback, this, _1));
250  // menu_handler_.apply(*imarker_server_, int_marker_.name);
251 }
252 
253 visualization_msgs::InteractiveMarkerControl&
254 IMarkerEndEffector::makeBoxControl(visualization_msgs::InteractiveMarker& msg)
255 {
256  visualization_msgs::InteractiveMarkerControl control;
257  control.always_visible = true;
258 
259  visualization_msgs::Marker marker;
260  marker.type = visualization_msgs::Marker::CUBE;
261  marker.scale.x = msg.scale * 0.3; // x direction
262  marker.scale.y = msg.scale * 0.10; // y direction
263  marker.scale.z = msg.scale * 0.10; // height
264  marker.color.r = 0.5;
265  marker.color.g = 0.5;
266  marker.color.b = 0.5;
267  marker.color.a = 1.0;
268 
269  control.markers.push_back(marker);
270  msg.controls.push_back(control);
271 
272  return msg.controls.back();
273 }
274 
275 } // namespace moveit_visual_tools
276 
277 namespace
278 {
279 bool isStateValid(const planning_scene::PlanningScene* planning_scene, bool verbose, bool only_check_self_collision,
281  const moveit::core::JointModelGroup* group, const double* ik_solution)
282 {
283  // Apply IK solution to robot state
284  robot_state->setJointGroupPositions(group, ik_solution);
285  robot_state->update();
286 
287  // Ensure there are objects in the planning scene
288  if (false)
289  {
290  const std::size_t num_collision_objects = planning_scene->getCollisionWorld()->getWorld()->size();
291  if (num_collision_objects == 0)
292  {
293  ROS_ERROR_STREAM_NAMED("cart_path_planner", "No collision objects exist in world, you need at least a table "
294  "modeled for the controller to work");
295  ROS_ERROR_STREAM_NAMED("cart_path_planner", "To fix this, relaunch the teleop/head tracking/whatever MoveIt! "
296  "node to publish the collision objects");
297  return false;
298  }
299  }
300 
301  if (!planning_scene)
302  {
303  ROS_ERROR_STREAM_NAMED("cart_path_planner", "No planning scene provided");
304  return false;
305  }
306  if (only_check_self_collision)
307  {
308  // No easy API exists for only checking self-collision, so we do it here.
309  // TODO(davetcoleman): move this into planning_scene.cpp
311  req.verbose = verbose;
312  req.group_name = group->getName();
314  planning_scene->checkSelfCollision(req, res, *robot_state);
315  if (!res.collision)
316  return true; // not in collision
317  }
318  else if (!planning_scene->isStateColliding(*robot_state, group->getName()))
319  return true; // not in collision
320 
321  // Display more info about the collision
322  if (verbose)
323  {
324  visual_tools->publishRobotState(*robot_state, rviz_visual_tools::RED);
325  planning_scene->isStateColliding(*robot_state, group->getName(), true);
326  visual_tools->publishContactPoints(*robot_state, planning_scene);
327  }
328  ROS_WARN_STREAM_THROTTLE_NAMED(2.0, "cart_path_planner", "Collision");
329  return false;
330 }
331 
332 } // end annonymous namespace
const std::string & getName() const
moveit_visual_tools::MoveItVisualToolsPtr visual_tools_
#define ROS_DEBUG_STREAM_NAMED(name, args)
std::shared_ptr< MoveItVisualTools > MoveItVisualToolsPtr
void iMarkerCallback(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
#define ROS_ERROR_STREAM_NAMED(name, args)
void poseEigenToMsg(const Eigen::Affine3d &e, geometry_msgs::Pose &m)
void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e)
void checkSelfCollision(const collision_detection::CollisionRequest &req, collision_detection::CollisionResult &res)
const std::string & getName() const
visualization_msgs::InteractiveMarker int_marker_
moveit::core::RobotStatePtr imarker_state_
void publishRobotState()
Show current state in Rviz.
#define ROS_INFO_STREAM_NAMED(name, args)
planning_scene_monitor::PlanningSceneMonitorPtr psm_
bool verbose
void update(bool force=false)
#define ROS_WARN_STREAM_THROTTLE_NAMED(rate, name, args)
moveit::core::JointModelGroup * jmg_
void updateIMarkerPose(const Eigen::Affine3d &pose)
I wish this struct wasn&#39;t necessary, but the SRDF does not seem to support choosing one particular li...
void setJointGroupPositions(const std::string &joint_group_name, const double *gstate)
void getPose(Eigen::Affine3d &pose)
Get the current end effector pose.
IMarkerEndEffector(IMarkerRobotState *imarker_parent, const std::string &imarker_name, ArmData arm_data, rviz_visual_tools::colors color)
Constructor.
static Time now()
moveit::core::LinkModel * ee_link_
visualization_msgs::InteractiveMarkerControl & makeBoxControl(visualization_msgs::InteractiveMarker &msg)
void make6DofMarker(const geometry_msgs::Pose &pose)
boost::function< bool(RobotState *robot_state, const JointModelGroup *joint_group, const double *joint_group_variable_values)> GroupStateValidityCallbackFn
bool isStateColliding(const std::string &group="", bool verbose=false)
const collision_detection::CollisionWorldConstPtr & getCollisionWorld() const


moveit_visual_tools
Author(s): Dave Coleman
autogenerated on Thu Jul 16 2020 03:55:17