imarker_robot_state.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 // MoveIt
42 
43 // this package
46 
47 #include <boost/filesystem.hpp>
48 
49 // C++
50 #include <string>
51 #include <utility>
52 #include <vector>
53 
54 namespace
55 {
56 bool isIKStateValid(const planning_scene::PlanningScene* planning_scene, bool verbose, bool only_check_self_collision,
59  const double* ik_solution)
60 {
61  // Apply IK solution to robot state
62  robot_state->setJointGroupPositions(group, ik_solution);
63  robot_state->update();
64 
65 #if 0 // Ensure there are objects in the planning scene
66  const std::size_t num_collision_objects = planning_scene->getCollisionEnv()->getWorld()->size();
67  if (num_collision_objects == 0)
68  {
69  ROS_ERROR_STREAM_NAMED("imarker_robot_state", "No collision objects exist in world, you need at least a table "
70  "modeled for the controller to work");
71  ROS_ERROR_STREAM_NAMED("imarker_robot_state", "To fix this, relaunch the teleop/head tracking/whatever MoveIt "
72  "node to publish the collision objects");
73  return false;
74  }
75 #endif
76 
77  if (!planning_scene)
78  {
79  ROS_ERROR_STREAM_NAMED("imarker_robot_state", "No planning scene provided");
80  return false;
81  }
82  if (only_check_self_collision)
83  {
84  // No easy API exists for only checking self-collision, so we do it here.
85  // TODO(davetcoleman): move this into planning_scene.cpp
87  req.verbose = verbose;
88  req.group_name = group->getName();
90  planning_scene->checkSelfCollision(req, res, *robot_state);
91  if (!res.collision)
92  return true; // not in collision
93  }
94  else if (!planning_scene->isStateColliding(*robot_state, group->getName()))
95  return true; // not in collision
96 
97  // Display more info about the collision
98  if (verbose)
99  {
100  visual_tools->publishRobotState(*robot_state, rviz_visual_tools::RED);
101  planning_scene->isStateColliding(*robot_state, group->getName(), true);
102  visual_tools->publishContactPoints(*robot_state, planning_scene);
103  ROS_WARN_STREAM_THROTTLE_NAMED(2.0, "imarker_robot_state", "Collision in IK CC callback");
104  }
105 
106  return false;
107 }
108 
109 } // namespace
110 
111 namespace moveit_visual_tools
112 {
113 IMarkerRobotState::IMarkerRobotState(planning_scene_monitor::PlanningSceneMonitorPtr psm,
114  const std::string& imarker_name, std::vector<ArmData> arm_datas,
115  rviz_visual_tools::colors color, const std::string& package_path)
116  : name_(imarker_name)
117  , nh_("~")
118  , arm_datas_(std::move(arm_datas))
119  , psm_(std::move(psm))
120  , color_(color)
121  , package_path_(package_path)
122 {
123  // Load Visual tools with respect to Eigen memory alignment
124  visual_tools_ = std::allocate_shared<moveit_visual_tools::MoveItVisualTools>(
125  Eigen::aligned_allocator<moveit_visual_tools::MoveItVisualTools>(), psm_->getRobotModel()->getModelFrame(),
126  nh_.getNamespace() + "/" + imarker_name, psm_);
127 
128  // visual_tools_->setPlanningSceneMonitor(psm_);
129  visual_tools_->loadRobotStatePub(nh_.getNamespace() + "/imarker_" + imarker_name + "_state");
130 
131  // Load robot state
132  imarker_state_ = std::make_shared<moveit::core::RobotState>(psm_->getRobotModel());
133  imarker_state_->setToDefaultValues();
134 
135  // Create Marker Server
136  const std::string imarker_topic = nh_.getNamespace() + "/" + imarker_name + "_imarker";
137  imarker_server_ = std::make_shared<interactive_markers::InteractiveMarkerServer>(imarker_topic, "", false);
138 
139  // Get file name
140  if (!getFilePath(file_path_, "imarker_" + name_ + ".csv", "config/imarkers"))
141  exit(-1);
142 
143  // Load previous pose from file
144  if (!loadFromFile(file_path_))
145  ROS_INFO_STREAM_NAMED(name_, "Unable to find state from file, setting to default");
146 
147  // Show initial robot state loaded from file
149 
150  // Create each end effector
151  end_effectors_.resize(arm_datas_.size());
152  for (std::size_t i = 0; i < arm_datas_.size(); ++i)
153  {
154  std::string eef_name;
155  if (i == 0)
156  eef_name = imarker_name + "_right";
157  else
158  eef_name = imarker_name + "_left";
159 
160  // respect Eigen alignment
161  end_effectors_[i] = std::allocate_shared<IMarkerEndEffector>(Eigen::aligned_allocator<IMarkerEndEffector>(), this,
162  eef_name, arm_datas_[i], color);
163 
164  // Create map from eef name to object
165  name_to_eef_[eef_name] = end_effectors_[i];
166  }
167 
168  // After both end effectors have been added, apply on server
169  imarker_server_->applyChanges();
170 
171  ROS_DEBUG_STREAM_NAMED(name_, "IMarkerRobotState '" << name_ << "' Ready.");
172 }
173 
174 bool IMarkerRobotState::loadFromFile(const std::string& file_name)
175 {
176  if (!boost::filesystem::exists(file_name))
177  {
178  ROS_WARN_STREAM_NAMED(name_, "File not found: " << file_name);
179  return false;
180  }
181  std::ifstream input_file(file_name);
182 
183  std::string line;
184 
185  if (!std::getline(input_file, line))
186  {
187  ROS_ERROR_STREAM_NAMED(name_, "Unable to read line");
188  return false;
189  }
190 
191  // Get robot state from file
193 
194  return true;
195 }
196 
198 {
199  output_file_.open(file_path_);
201  output_file_.close();
202 
203  return true;
204 }
205 
207 {
208  for (const IMarkerEndEffectorPtr& ee : end_effectors_)
209  ee->setIMarkerCallback(callback);
210 }
211 
212 void IMarkerRobotState::setRobotState(const moveit::core::RobotStatePtr& state)
213 {
214  // Do a copy
215  *imarker_state_ = *state;
216 
217  // Update the imarkers
218  for (const IMarkerEndEffectorPtr& ee : end_effectors_)
219  ee->setPoseFromRobotState();
220 }
221 
223 {
224  // Get the real current state
225  planning_scene_monitor::LockedPlanningSceneRO scene(psm_); // Lock planning scene
226  (*imarker_state_) = scene->getCurrentState();
227 
228  // Set updated pose from robot state
229  for (std::size_t i = 0; i < arm_datas_.size(); ++i)
230  end_effectors_[i]->setPoseFromRobotState();
231 
232  // Show new state
233  visual_tools_->publishRobotState(imarker_state_, color_);
234 }
235 
237 {
238  static const std::size_t MAX_ATTEMPTS = 1000;
239  for (std::size_t attempt = 0; attempt < MAX_ATTEMPTS; ++attempt)
240  {
241  // Set each planning group to random
242  for (std::size_t i = 0; i < arm_datas_.size(); ++i)
243  {
244  imarker_state_->setToRandomPositions(arm_datas_[i].jmg_);
245  }
246 
247  // Update transforms
248  imarker_state_->update();
250 
251  // Collision check
252  // which planning group to collision check, "" is everything
253  static const bool verbose = false;
254  if (planning_scene->isStateValid(*imarker_state_, "", verbose))
255  {
256  // Check clearance
257  if (clearance > 0)
258  {
259  // which planning group to collision check, "" is everything
260  if (planning_scene->distanceToCollision(*imarker_state_) < clearance)
261  {
262  continue; // clearance is not enough
263  }
264  }
265 
266  ROS_INFO_STREAM_NAMED(name_, "Found valid random robot state after " << attempt << " attempts");
267 
268  // Set updated pose from robot state
269  for (std::size_t i = 0; i < arm_datas_.size(); ++i)
270  end_effectors_[i]->setPoseFromRobotState();
271 
272  // Send to imarker
273  for (std::size_t i = 0; i < arm_datas_.size(); ++i)
274  end_effectors_[i]->sendUpdatedIMarkerPose();
275 
276  return true;
277  }
278 
279  if (attempt == 100)
280  ROS_WARN_STREAM_NAMED(name_, "Taking long time to find valid random state");
281  }
282 
284  "Unable to find valid random robot state for imarker after " << MAX_ATTEMPTS << " attempts");
285 
286  return false;
287 }
288 
290 {
291  // Update transforms
292  imarker_state_->update();
293 
295 
296  // which planning group to collision check, "" is everything
297  return planning_scene->isStateValid(*imarker_state_, "", verbose);
298 }
299 
301 {
302  visual_tools_->publishRobotState(imarker_state_, color_);
303 }
304 
306 {
307  return visual_tools_;
308 }
309 
310 bool IMarkerRobotState::getFilePath(std::string& file_path, const std::string& file_name,
311  const std::string& subdirectory) const
312 
313 {
314  namespace fs = boost::filesystem;
315 
316  // Check that the directory exists, if not, create it
317  fs::path rootPath = fs::path(package_path_);
318  rootPath = rootPath / fs::path(subdirectory);
319 
320  boost::system::error_code returnedError;
321  fs::create_directories(rootPath, returnedError);
322 
323  if (returnedError)
324  {
325  // did not successfully create directories
326  ROS_ERROR("Unable to create directory %s", subdirectory.c_str());
327  return false;
328  }
329 
330  // directories successfully created, append the group name as the file name
331  rootPath = rootPath / fs::path(file_name);
332  file_path = rootPath.string();
333  // ROS_DEBUG_STREAM_NAMED(name_, "Config file: " << file_path);
334 
335  return true;
336 }
337 
339  const moveit::core::JointModelGroup* group)
340 {
341  std::vector<std::string> tips;
342  for (std::size_t i = 0; i < arm_datas_.size(); ++i)
343  tips.push_back(arm_datas_[i].ee_link_->getName());
344 
345  // ROS_DEBUG_STREAM_NAMED(name_, "First pose should be for joint model group: " << arm_datas_[0].ee_link_->getName());
346 
347  const double timeout = 1.0 / 30.0; // 30 fps
348 
349  // Optionally collision check
351 #if 1
352  bool collision_checking_verbose_ = false;
353  bool only_check_self_collision_ = false;
354 
355  // TODO(davetcoleman): this is currently not working, the locking seems to cause segfaults
356  // TODO(davetcoleman): change to std shared_ptr
357  boost::scoped_ptr<planning_scene_monitor::LockedPlanningSceneRO> ls;
359  constraint_fn = boost::bind(&isIKStateValid, static_cast<const planning_scene::PlanningSceneConstPtr&>(*ls).get(),
360  collision_checking_verbose_, only_check_self_collision_, visual_tools_,
361  boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3);
362 #endif
363 
364  // Solve
365  std::size_t outer_attempts = 20;
366  for (std::size_t i = 0; i < outer_attempts; ++i)
367  {
368  if (!imarker_state_->setFromIK(group, poses, tips, timeout, constraint_fn))
369  {
370  ROS_DEBUG_STREAM_NAMED(name_, "Failed to find dual arm pose, trying again");
371 
372  // Re-seed
373  imarker_state_->setToRandomPositions(group);
374  }
375  else
376  {
377  ROS_DEBUG_STREAM_NAMED(name_, "Found IK solution");
378 
379  // Visualize robot
381 
382  // Update the imarkers
383  for (const IMarkerEndEffectorPtr& ee : end_effectors_)
384  ee->setPoseFromRobotState();
385 
386  return true;
387  }
388  }
389 
390  ROS_ERROR_STREAM_NAMED(name_, "Failed to find dual arm pose");
391  return false;
392 }
393 
394 } // namespace moveit_visual_tools
ROS_WARN_STREAM_THROTTLE_NAMED
#define ROS_WARN_STREAM_THROTTLE_NAMED(period, name, args)
moveit::core::GroupStateValidityCallbackFn
boost::function< bool(RobotState *robot_state, const JointModelGroup *joint_group, const double *joint_group_variable_values)> GroupStateValidityCallbackFn
moveit_visual_tools::IMarkerRobotState::isStateValid
bool isStateValid(bool verbose=false)
Return true if the currently solved IK solution is valid.
Definition: imarker_robot_state.cpp:289
imarker_end_effector.h
EigenSTL::vector_Isometry3d
std::vector< Eigen::Isometry3d, Eigen::aligned_allocator< Eigen::Isometry3d > > vector_Isometry3d
moveit_visual_tools::IMarkerRobotState::setToCurrentState
void setToCurrentState()
Set the robot state to current in planning scene monitor.
Definition: imarker_robot_state.cpp:222
moveit_visual_tools::IMarkerRobotState::setFromPoses
bool setFromPoses(const EigenSTL::vector_Isometry3d &poses, const moveit::core::JointModelGroup *group)
Definition: imarker_robot_state.cpp:338
moveit_visual_tools::IMarkerEndEffectorPtr
std::shared_ptr< IMarkerEndEffector > IMarkerEndEffectorPtr
Definition: imarker_end_effector.h:208
ROS_DEBUG_STREAM_NAMED
#define ROS_DEBUG_STREAM_NAMED(name, args)
planning_scene::PlanningScene
moveit_visual_tools::IMarkerRobotState::arm_datas_
std::vector< ArmData > arm_datas_
Definition: imarker_robot_state.h:188
moveit_visual_tools::IMarkerRobotState::IMarkerRobotState
IMarkerRobotState(planning_scene_monitor::PlanningSceneMonitorPtr psm, const std::string &imarker_name, std::vector< ArmData > arm_datas, rviz_visual_tools::colors color, const std::string &package_path)
Constructor.
Definition: imarker_robot_state.cpp:113
moveit_visual_tools::IMarkerRobotState::imarker_state_
moveit::core::RobotStatePtr imarker_state_
Definition: imarker_robot_state.h:185
moveit_visual_tools::IMarkerRobotState::end_effectors_
std::vector< IMarkerEndEffectorPtr > end_effectors_
Definition: imarker_robot_state.h:189
moveit_visual_tools::IMarkerRobotState::getFilePath
bool getFilePath(std::string &file_path, const std::string &file_name, const std::string &subdirectory) const
Definition: imarker_robot_state.cpp:310
moveit::core::RobotState
moveit::core::robotStateToStream
void robotStateToStream(const RobotState &state, std::ostream &out, bool include_header=true, const std::string &separator=",")
collision_detection::CollisionRequest
transforms.h
moveit_visual_tools::IMarkerRobotState::color_
rviz_visual_tools::colors color_
Definition: imarker_robot_state.h:200
moveit_visual_tools::IMarkerRobotState::psm_
planning_scene_monitor::PlanningSceneMonitorPtr psm_
Definition: imarker_robot_state.h:193
moveit::core::JointModelGroup::getName
const std::string & getName() const
moveit_visual_tools::IMarkerRobotState::nh_
ros::NodeHandle nh_
Definition: imarker_robot_state.h:182
moveit_visual_tools::IMarkerRobotState::name_to_eef_
std::map< std::string, IMarkerEndEffectorPtr > name_to_eef_
Definition: imarker_robot_state.h:190
moveit_visual_tools::MoveItVisualToolsPtr
std::shared_ptr< MoveItVisualTools > MoveItVisualToolsPtr
Definition: moveit_visual_tools.h:782
moveit::core::RobotState::update
void update(bool force=false)
moveit_visual_tools::IMarkerRobotState::setRobotState
void setRobotState(const moveit::core::RobotStatePtr &state)
Set the robot state.
Definition: imarker_robot_state.cpp:212
collision_detection::CollisionResult
moveit_visual_tools::IMarkerRobotState::visual_tools_
moveit_visual_tools::MoveItVisualToolsPtr visual_tools_
Definition: imarker_robot_state.h:196
moveit_visual_tools::IMarkerRobotState::setIMarkerCallback
void setIMarkerCallback(const IMarkerCallback &callback)
Set where in the parent class the feedback should be sent.
Definition: imarker_robot_state.cpp:206
ROS_ERROR_STREAM_NAMED
#define ROS_ERROR_STREAM_NAMED(name, args)
collision_detection::CollisionRequest::verbose
bool verbose
collision_detection::CollisionRequest::group_name
std::string group_name
ROS_ERROR
#define ROS_ERROR(...)
moveit_visual_tools::IMarkerCallback
std::function< void(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &, const Eigen::Isometry3d &)> IMarkerCallback
Definition: imarker_end_effector.h:100
moveit_visual_tools::IMarkerRobotState::getVisualTools
moveit_visual_tools::MoveItVisualToolsPtr getVisualTools()
Definition: imarker_robot_state.cpp:305
ROS_WARN_STREAM_NAMED
#define ROS_WARN_STREAM_NAMED(name, args)
rviz_visual_tools::RED
RED
imarker_robot_state.h
rviz_visual_tools::colors
colors
moveit_visual_tools::IMarkerRobotState::package_path_
std::string package_path_
Definition: imarker_robot_state.h:208
moveit_visual_tools::IMarkerRobotState::publishRobotState
void publishRobotState()
Show current state in Rviz.
Definition: imarker_robot_state.cpp:300
moveit_visual_tools::IMarkerRobotState::name_
std::string name_
Definition: imarker_robot_state.h:179
std
planning_scene_monitor::LockedPlanningSceneRO
moveit_visual_tools::IMarkerRobotState::file_path_
std::string file_path_
Definition: imarker_robot_state.h:206
moveit::core::JointModelGroup
ROS_INFO_STREAM_NAMED
#define ROS_INFO_STREAM_NAMED(name, args)
collision_detection::CollisionResult::collision
bool collision
conversions.h
moveit_visual_tools::IMarkerRobotState::saveToFile
bool saveToFile()
Definition: imarker_robot_state.cpp:197
moveit_visual_tools::IMarkerRobotState::imarker_server_
InteractiveMarkerServerPtr imarker_server_
Definition: imarker_robot_state.h:203
moveit_visual_tools::IMarkerRobotState::output_file_
std::ofstream output_file_
Definition: imarker_robot_state.h:207
ros::NodeHandle::getNamespace
const std::string & getNamespace() const
moveit::core::RobotState::setJointGroupPositions
void setJointGroupPositions(const std::string &joint_group_name, const double *gstate)
planning_scene
moveit::core::streamToRobotState
void streamToRobotState(RobotState &state, const std::string &line, const std::string &separator=",")
moveit_visual_tools::IMarkerRobotState::setToRandomState
bool setToRandomState(double clearance=0)
Set the robot to a random position.
Definition: imarker_robot_state.cpp:236
moveit_visual_tools
Definition: imarker_end_effector.h:62
moveit_visual_tools::IMarkerRobotState::loadFromFile
bool loadFromFile(const std::string &file_name)
Definition: imarker_robot_state.cpp:174
verbose
bool verbose


moveit_visual_tools
Author(s): Dave Coleman
autogenerated on Fri May 19 2023 02:14:04