ros_conversions.cpp
Go to the documentation of this file.
1#include "ros_conversions.h"
2
3#include <math.h>
4
5#include <cmath>
6#include <optional>
7
8#include <boost/none.hpp>
9#include <boost/optional/optional.hpp>
10#include <boost/smart_ptr/make_shared_object.hpp>
11
16
24
25#include <geometry_msgs/Twist.h>
26#include <range/v3/view/drop.hpp>
27#include <range/v3/view/zip.hpp>
28#include <stuff/misc.h>
29#include <teb_local_planner/costmap.h>
30#include <teb_local_planner/penalty_models.h>
31#include <teb_local_planner/pose_se2.h>
32#include <teb_local_planner/timed_elastic_band.h>
33
35{
36 Eigen::Vector2d
37 toRos2D(const Eigen::Vector2f& vec)
38 {
39 return vec.cast<double>() / 1000; // [mm] to [m]
40 }
41
42 Eigen::Vector2d
43 toRos(const Eigen::Vector3f& vec)
44 {
45 return conv::to2D(vec).cast<double>() / 1000; // [mm] to [m]
46 }
47
48 Eigen::Vector3f
49 fromRos(const Eigen::Vector2d& vec)
50 {
51 return conv::to3D(vec.cast<float>()) * 1000; // [m] to [mm]
52 }
53
54 teb_local_planner::PoseSE2
55 toRos(const core::Pose& pose)
56 {
57 core::Pose2D pose2D = to2D(pose);
58 return toRos(pose2D);
59 }
60
61 teb_local_planner::PoseSE2
62 toRos(const core::Pose2D& pose)
63 {
64 Eigen::Vector2d pos = pose.translation().cast<double>();
65 double theta = Eigen::Rotation2Df(pose.linear()).angle();
66
67 // we change it such that x is pointing forward.
68 // ROS: x pointing forward, ArmarX: y pointing forward
69 theta += M_PI_2;
70 // normalize angle
71 theta = g2o::normalize_theta(theta);
72
73 return {pos / 1000., theta}; // [mm] to [m]
74 }
75
77 fromRos(const teb_local_planner::PoseSE2& pose)
78 {
79 Eigen::Vector2d pos = pose.position() * 1000; // [m] to [mm]
80 double theta = pose.theta();
81
82 // we change it such that x is pointing forward.
83 // ROS: x pointing forward, ArmarX: y pointing forward
84 theta -= M_PI_2;
85
86
87 core::Pose2D ret;
88 ret.translation() = pos.cast<float>();
89 ret.linear() = Eigen::Rotation2Df(theta).toRotationMatrix();
90
91 return to3D(ret);
92 }
93
94 geometry_msgs::Twist
95 toRos(const core::Twist& velocity)
96 {
97 geometry_msgs::Twist ret;
98
99 // we change it such that x is pointing forward.
100 // ROS: x pointing forward, ArmarX: y pointing forward
101
102 ret.linear.x = velocity.linear.y() / 1000; // [mm] to [m]
103 ret.linear.y = -velocity.linear.x() / 1000; // [mm] to [m]
104 ret.angular.z = velocity.angular.z();
105
106 return ret;
107 }
108
109 teb_local_planner::TimedElasticBand
111 {
112 teb_local_planner::TimedElasticBand teb;
113
114 bool first = true;
115 teb_local_planner::PoseSE2 lastPose;
116 for (const core::GlobalTrajectoryPoint& point : trajectory.points())
117 {
118 teb_local_planner::PoseSE2 pose = toRos(point.waypoint.pose);
119 teb.addPose(pose);
120
121 if (!first)
122 {
123 Eigen::Vector2d distance = pose.position() - lastPose.position();
124 double timeDiff = distance.norm() / (point.velocity / 1000); // [mm/s] -> [m/s]
125 teb.addTimeDiff(timeDiff);
126
127 first = false;
128 }
129
130 lastPose = pose;
131 }
132
133 return teb;
134 }
135
137 fromRos(const teb_local_planner::TimedElasticBand& teb, DateTime timestamp)
138 {
139 const auto& tebPoses = teb.poses();
140
141 if (tebPoses.empty())
142 {
143 return {};
144 }
145
147 trajectory.reserve(tebPoses.size());
148
149 // TODO this timestamp should be given via the argument list
150 //DateTime timestamp = Clock::Now();
151
152 ARMARX_CHECK_EQUAL(tebPoses.size() - 1, teb.timediffs().size());
153
154 // add the first pose at this timestamp
156 .timestamp = timestamp, .pose = {fromRos(tebPoses.front()->pose())}});
157
158 // all consecutive poses
159 for (const auto& [poseVertex, timediff] :
160 ranges::views::zip(tebPoses | ranges::views::drop(1), teb.timediffs()))
161 {
162 const core::Pose pose = fromRos(poseVertex->pose());
163 const Duration dt = Duration::SecondsDouble(timediff->dt());
164
165 timestamp += dt;
166 trajectory.push_back(
167 core::LocalTrajectoryPoint{.timestamp = timestamp, .pose = {pose}});
168 }
169
170 ARMARX_CHECK_EQUAL(trajectory.size(), tebPoses.size());
171
172 return {trajectory};
173 }
174
177 {
178 // a,b parameter are along the x and y axis respectively
179 // ROS and ArmarX have the x axis pointing in a different direction
180 // ROS: x pointing forward, ArmarX: y pointing forward
181 return {.a = ellipse.b / 1000, .b = ellipse.a / 1000}; // [mm] to [m]
182 }
183
184 teb_local_planner::Costmap
186 {
187 const algorithms::Costmap::Parameters& params = costmap.params();
188 const teb_local_planner::Costmap::Parameters teb_params = {
189 .binaryGrid = params.binaryGrid, .cellSize = params.cellSize / 1000}; // [mm] to [m]
190
191 const algorithms::SceneBounds& bounds = costmap.getLocalSceneBounds();
192 const teb_local_planner::Costmap::SceneBounds teb_bounds = {
193 .min = toRos2D(bounds.min).cast<float>(), .max = toRos2D(bounds.max).cast<float>()};
194
195 const std::optional<algorithms::Costmap::Mask>& mask = costmap.getMask();
196 boost::optional<teb_local_planner::Costmap::Mask> teb_mask = boost::none;
197 if (mask)
198 {
199 teb_mask = mask.value();
200 }
201
202 teb_local_planner::Costmap::Pose2D teb_origin = costmap.origin();
203 teb_origin.translation() /= 1000; // [mm] to[m]
204
205 algorithms::Costmap::Grid teb_grid = costmap.getGrid();
206 teb_grid /= 1000; // [mm] to [m]
207
208 return teb_local_planner::Costmap{teb_grid, teb_params, teb_bounds, teb_mask, teb_origin};
209 }
210
211 teb_local_planner::PenaltyModelPtr
213 {
214 return boost::make_shared<teb_local_planner::LinearPenaltyModel>(
215 teb_local_planner::LinearPenaltyModel(model.minDistance, model.epsilon));
216 }
217
218 teb_local_planner::PenaltyModelPtr
220 {
221 return boost::make_shared<teb_local_planner::ExponentialPenaltyModel>(
222 teb_local_planner::LinearPenaltyModel(model.minDistance, model.epsilon),
223 model.exponent);
224 }
225
226} // namespace armarx::navigation::conv
std::string timestamp()
constexpr T dt
static Duration SecondsDouble(double seconds)
Constructs a duration in seconds.
Definition Duration.cpp:78
Represents a point in time.
Definition DateTime.h:25
Represents a duration.
Definition Duration.h:17
const core::Pose2D & origin() const
Definition Costmap.h:171
const SceneBounds & getLocalSceneBounds() const noexcept
Definition Costmap.cpp:165
const Parameters & params() const noexcept
Definition Costmap.cpp:302
const std::optional< Mask > & getMask() const noexcept
Definition Costmap.cpp:529
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
This file is part of ArmarX.
Definition eigen.cpp:11
Eigen::Vector2d toRos(const Eigen::Vector3f &vec)
std::vector< Eigen::Vector2f > to2D(const std::vector< Eigen::Vector3f > &v)
Definition eigen.cpp:29
std::vector< Eigen::Vector3f > to3D(const std::vector< Eigen::Vector2f > &v)
Definition eigen.cpp:14
Eigen::Vector3f fromRos(const Eigen::Vector2d &vec)
Eigen::Vector2d toRos2D(const Eigen::Vector2f &vec)
std::vector< LocalTrajectoryPoint > LocalTrajectoryPoints
Definition Trajectory.h:216
Eigen::Isometry2f Pose2D
Definition basic_types.h:34
Eigen::Isometry3f Pose
Definition basic_types.h:31
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
double distance(const Point &a, const Point &b)
Definition point.hpp:95
float cellSize
How big each cell is in the uniform grid.
Definition Costmap.h:31
An axis oriented ellipse with half-axes a and b along the x- and y-axis respectively.
Definition shapes.h:35