moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
transform_provider.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2013, Willow Garage, Inc.
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 Willow Garage 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: Suat Gedikli */
36
38#include <rclcpp/version.h>
39// For Rolling, Kilted, and newer
40#if RCLCPP_VERSION_GTE(29, 6, 0)
41#include <tf2_ros/buffer.hpp>
42#include <tf2_ros/transform_listener.hpp>
43// For Jazzy and older
44#else
45#include <tf2_ros/buffer.h>
46#include <tf2_ros/transform_listener.h>
47#endif
48#include <tf2_eigen/tf2_eigen.hpp>
49
50TransformProvider::TransformProvider(double update_rate) : stop_(true), update_rate_(update_rate)
51{
52 tf_buffer_ = std::make_shared<tf2_ros::Buffer>();
53 tf_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);
54 psm_ = std::make_shared<planning_scene_monitor::PlanningSceneMonitor>("robot_description", tf_buffer_);
55 psm_->startStateMonitor();
56}
57
62
64{
65 stop_ = false;
66 thread_ = std::thread(&TransformProvider::run, this);
67}
68
70{
71 stop_ = true;
72 thread_.join();
73}
74
75void TransformProvider::addHandle(mesh_filter::MeshHandle handle, const std::string& name)
76{
77 if (!stop_)
78 throw std::runtime_error("Can not add handles if TransformProvider is running");
79
80 handle2context_[handle] = std::make_shared<TransformContext>(name);
81}
82
83void TransformProvider::setFrame(const std::string& frame)
84{
85 if (frame_id_ != frame)
86 {
87 frame_id_ = frame;
88 for (auto& context_it : handle2context_)
89 {
90 // invalidate transformations
91 context_it.second->mutex_.lock();
92 context_it.second->transformation_.matrix().setZero();
93 context_it.second->mutex_.unlock();
94 }
95 }
96}
97
98bool TransformProvider::getTransform(mesh_filter::MeshHandle handle, Eigen::Isometry3d& transform) const
99{
100 auto context_it = handle2context_.find(handle);
101
102 if (context_it == handle2context_.end())
103 {
104 ROS_ERROR("Unable to find mesh with handle %d", handle);
105 return false;
106 }
107 context_it->second->mutex_.lock();
108 transform = context_it->second->transformation_;
109 context_it->second->mutex_.unlock();
110 return !(transform.matrix().isZero(0));
111}
112
113void TransformProvider::run()
114{
115 if (handle2context_.empty())
116 throw std::runtime_error("TransformProvider is listening to empty list of frames!");
117
118 while (ros::ok() && !stop_)
119 {
120 updateTransforms();
121 update_rate_.sleep();
122 }
123}
124
125void TransformProvider::setUpdateRate(double update_rate)
126{
127 update_rate_ = ros::Rate(update_rate);
128}
129
130void TransformProvider::updateTransforms()
131{
132 // Don't bother if frame_id_ is empty (true initially)
133 if (frame_id_.empty())
134 {
135 ROS_DEBUG_THROTTLE(2., "Not updating transforms because frame_id_ is empty.");
136 return;
137 }
138
139 static tf2::Stamped<Eigen::Isometry3d> input_transform, output_transform;
140 static moveit::core::RobotStatePtr robot_state;
141 robot_state = psm_->getStateMonitor()->getCurrentState();
142 try
143 {
144 geometry_msgs::TransformStamped common_tf =
145 tf_buffer_->lookupTransform(frame_id_, psm_->getPlanningScene()->getPlanningFrame(), ros::Time(0.0));
146 input_transform.stamp_ = common_tf.header.stamp;
147 }
148 catch (tf2::TransformException& ex)
149 {
150 ROS_ERROR("TF Problem: %s", ex.what());
151 return;
152 }
153 input_transform.frame_id_ = psm_->getPlanningScene()->getPlanningFrame();
154
155 for (auto& context_it : handle2context_)
156 {
157 try
158 {
159 // TODO: check logic here - which global collision body's transform should be used?
160 input_transform.setData(robot_state->getGlobalLinkTransform(context_it.second->frame_id_));
161 tf_buffer_->transform(input_transform, output_transform, frame_id_);
162 }
163 catch (const tf2::TransformException& ex)
164 {
165 handle2context_[context_it.first]->mutex_.lock();
166 handle2context_[context_it.first]->transformation_.matrix().setZero();
167 handle2context_[context_it.first]->mutex_.unlock();
168 continue;
169 }
170 catch (std::exception& ex)
171 {
172 ROS_ERROR("Caught %s while updating transforms", ex.what());
173 }
174 handle2context_[context_it.first]->mutex_.lock();
175 handle2context_[context_it.first]->transformation_ = static_cast<Eigen::Isometry3d>(output_transform);
176 handle2context_[context_it.first]->mutex_.unlock();
177 }
178}
void start()
starts the updating process. Done in a separate thread
void stop()
stops the update process/thread.
void setFrame(const std::string &frame)
sets the camera frame id. The returned transformations are in respect to this coordinate frame
void addHandle(mesh_filter::MeshHandle handle, const std::string &name)
registers a mesh with its handle
~TransformProvider()
Destructor.
void setUpdateRate(double update_rate)
sets the update rate in Hz. This should be slow enough to reduce the system load but fast enough to g...
TransformProvider(double update_rate=30.)
Constructor.
bool getTransform(mesh_filter::MeshHandle handle, Eigen::Isometry3d &transform) const
returns the current transformation of a mesh given by its handle
unsigned int MeshHandle