33 #include <boost/thread.hpp> 36 #include <Eigen/Geometry> 40 #include <geometry_msgs/Twist.h> 41 #include <nav_msgs/Path.h> 42 #include <rosgraph_msgs/Clock.h> 46 #include <trajectory_tracker_msgs/TrajectoryTrackerStatus.h> 47 #include <trajectory_tracker_msgs/PathWithVelocity.h> 49 #include <gtest/gtest.h> 63 void cbStatus(
const trajectory_tracker_msgs::TrajectoryTrackerStatus::ConstPtr& msg)
67 void cbCmdVel(
const geometry_msgs::Twist::ConstPtr& msg)
74 yaw_ += msg->angular.z * dt;
75 pos_ += Eigen::Vector2d(std::cos(
yaw_), std::sin(
yaw_)) * msg->linear.x * dt;
83 trajectory_tracker_msgs::TrajectoryTrackerStatus::ConstPtr
status_;
93 pub_path_ = nh_.
advertise<nav_msgs::Path>(
"path", 1,
true);
94 pub_path_vel_ = nh_.
advertise<trajectory_tracker_msgs::PathWithVelocity>(
"path_velocity", 1,
true);
96 void initState(
const Eigen::Vector2d& pos,
const float yaw)
99 path.header.frame_id =
"odom";
125 if (status_->status == trajectory_tracker_msgs::TrajectoryTrackerStatus::FOLLOWING)
132 path.header.frame_id =
"odom";
135 for (
const Eigen::Vector3d& p : poses)
137 const Eigen::Quaterniond q(Eigen::AngleAxisd(p[2], Eigen::Vector3d(0, 0, 1)));
139 geometry_msgs::PoseStamped pose;
140 pose.header.frame_id = path.header.frame_id;
141 pose.pose.position.x = p[0];
142 pose.pose.position.y = p[1];
143 pose.pose.orientation.x = q.x();
144 pose.pose.orientation.y = q.y();
145 pose.pose.orientation.z = q.z();
146 pose.pose.orientation.w = q.w();
148 path.poses.push_back(pose);
154 trajectory_tracker_msgs::PathWithVelocity path;
155 path.header.frame_id =
"odom";
158 for (
const Eigen::Vector4d& p : poses)
160 const Eigen::Quaterniond q(Eigen::AngleAxisd(p[2], Eigen::Vector3d(0, 0, 1)));
162 trajectory_tracker_msgs::PoseStampedWithVelocity pose;
163 pose.header.frame_id = path.header.frame_id;
164 pose.pose.position.x = p[0];
165 pose.pose.position.y = p[1];
166 pose.pose.orientation.x = q.x();
167 pose.pose.orientation.y = q.y();
168 pose.pose.orientation.z = q.z();
169 pose.pose.orientation.w = q.w();
170 pose.linear_velocity.x = p[3];
172 path.poses.push_back(pose);
180 const Eigen::Quaterniond q(Eigen::AngleAxisd(yaw_, Eigen::Vector3d(0, 0, 1)));
181 geometry_msgs::TransformStamped trans;
182 trans.header.frame_id =
"odom";
184 trans.child_frame_id =
"base_link";
185 trans.transform.translation.x = pos_[0];
186 trans.transform.translation.y = pos_[1];
187 trans.transform.rotation.x = q.x();
188 trans.transform.rotation.y = q.y();
189 trans.transform.rotation.z = q.z();
190 trans.transform.rotation.w = q.w();
199 std::vector<Eigen::Vector3d> poses;
200 for (
double x = 0.0;
x < 0.5;
x += 0.01)
201 poses.push_back(Eigen::Vector3d(
x, 0.0, 0.0));
202 poses.push_back(Eigen::Vector3d(0.5, 0.0, 0.0));
216 if (
status_->status == trajectory_tracker_msgs::TrajectoryTrackerStatus::GOAL)
219 for (
int i = 0; i < 25; ++i)
226 ASSERT_NEAR(
yaw_, 0.0, 1e-2);
227 ASSERT_NEAR(
pos_[0], 0.5, 1e-2);
228 ASSERT_NEAR(
pos_[1], 0.0, 1e-2);
233 const double vels[] =
235 0.02, 0.05, 0.1, 0.2, 0.5, 1.0
237 const double path_length = 2.0;
238 for (
const double vel : vels)
240 const std::string info_message =
"linear vel: " + std::to_string(vel);
244 std::vector<Eigen::Vector4d> poses;
245 for (
double x = 0.0;
x < path_length;
x += 0.01)
246 poses.push_back(Eigen::Vector4d(
x, 0.0, 0.0, vel));
247 poses.push_back(Eigen::Vector4d(path_length, 0.0, 0.0, vel));
261 if (
status_->status == trajectory_tracker_msgs::TrajectoryTrackerStatus::GOAL)
264 for (
int i = 0; i < 25; ++i)
271 EXPECT_NEAR(
yaw_, 0.0, 1e-2) << info_message;
272 EXPECT_NEAR(
pos_[0], path_length, 1e-2) << info_message;
273 EXPECT_NEAR(
pos_[1], 0.0, 1e-2) << info_message;
281 std::vector<Eigen::Vector4d> poses;
282 for (
double x = 0.0;
x < 0.5;
x += 0.01)
283 poses.push_back(Eigen::Vector4d(
x, 0.0, 0.0, 0.3));
284 for (
double x = 0.5;
x < 1.5;
x += 0.01)
285 poses.push_back(Eigen::Vector4d(
x, 0.0, 0.0, 0.5));
286 poses.push_back(Eigen::Vector4d(1.5, 0.0, 0.0, 0.5));
302 ASSERT_NEAR(
cmd_vel_->linear.x, 0.3, 1e-2);
304 else if (0.9 <
pos_[0] &&
pos_[0] < 1.0)
306 ASSERT_NEAR(
cmd_vel_->linear.x, 0.5, 1e-2);
309 if (
status_->status == trajectory_tracker_msgs::TrajectoryTrackerStatus::GOAL)
312 for (
int i = 0; i < 25; ++i)
319 ASSERT_NEAR(
yaw_, 0.0, 1e-2);
320 ASSERT_NEAR(
pos_[0], 1.5, 1e-2);
321 ASSERT_NEAR(
pos_[1], 0.0, 1e-2);
328 std::vector<Eigen::Vector3d> poses;
329 Eigen::Vector3d p(0.0, 0.0, 0.0);
330 for (
double t = 0.0;
t < 1.0;
t += 0.01)
332 p += Eigen::Vector3d(std::cos(p[2]) * 0.05, std::sin(p[2]) * 0.05, 0.005);
335 for (
double t = 0.0;
t < 1.0;
t += 0.01)
337 p += Eigen::Vector3d(std::cos(p[2]) * 0.05, std::sin(p[2]) * 0.05, 0.0);
353 if (
status_->status == trajectory_tracker_msgs::TrajectoryTrackerStatus::GOAL)
356 for (
int i = 0; i < 25; ++i)
363 ASSERT_NEAR(
yaw_, p[2], 1e-2);
364 ASSERT_NEAR(
pos_[0], p[0], 1e-1);
365 ASSERT_NEAR(
pos_[1], p[1], 1e-1);
370 const float init_yaw_array[] =
375 for (
const float init_yaw : init_yaw_array)
377 initState(Eigen::Vector2d(0, 0), init_yaw);
379 const float target_angle_array[] =
384 for (
const float ang : target_angle_array)
386 std::vector<Eigen::Vector3d> poses;
387 poses.push_back(Eigen::Vector3d(0.0, 0.0, init_yaw + ang));
404 ASSERT_GT(
cmd_vel_->angular.z * ang, -1e-2);
408 ASSERT_LT(
status_->angle_remains * ang, 1e-2);
411 if (
status_->status == trajectory_tracker_msgs::TrajectoryTrackerStatus::GOAL)
414 ASSERT_TRUE(static_cast<bool>(
cmd_vel_));
415 for (
int i = 0; i < 25; ++i)
422 ASSERT_NEAR(
yaw_, init_yaw + ang, 1e-2);
431 std::vector<Eigen::Vector3d> poses;
432 Eigen::Vector3d p(0.0, 0.0, 0.0);
433 for (
double t = 0.0;
t < 0.5;
t += 0.01)
435 p -= Eigen::Vector3d(std::cos(p[2]) * 0.05, std::sin(p[2]) * 0.05, -0.01);
438 for (
double t = 0.0;
t < 0.5;
t += 0.01)
440 p += Eigen::Vector3d(std::cos(p[2]) * 0.05, std::sin(p[2]) * 0.05, 0.01);
456 if (
status_->status == trajectory_tracker_msgs::TrajectoryTrackerStatus::GOAL)
459 for (
int i = 0; i < 25; ++i)
466 ASSERT_NEAR(
yaw_, p[2], 1e-2);
467 ASSERT_NEAR(
pos_[0], p[0], 1e-1);
468 ASSERT_NEAR(
pos_[1], p[1], 1e-1);
475 std::vector<Eigen::Vector3d> poses;
476 std::vector<Eigen::Vector3d> poses_second_half;
477 Eigen::Vector3d p(0.0, 0.0, 0.0);
478 for (
double t = 0.0;
t < 0.5;
t += 0.01)
480 p -= Eigen::Vector3d(std::cos(p[2]) * 0.05, std::sin(p[2]) * 0.05, -0.01);
483 const Eigen::Vector2d pos_local_goal = p.head<2>();
484 for (
double t = 0.0;
t < 1.0;
t += 0.01)
486 p += Eigen::Vector3d(std::cos(p[2]) * 0.05, std::sin(p[2]) * 0.05, 0.01);
488 poses_second_half.push_back(p);
494 int cnt_arrive_local_goal(0);
504 if (
status_->status == trajectory_tracker_msgs::TrajectoryTrackerStatus::GOAL)
507 if ((pos_local_goal -
pos_).norm() < 0.1)
508 cnt_arrive_local_goal++;
510 if (cnt_arrive_local_goal > 25)
515 for (
int i = 0; i < 25; ++i)
522 ASSERT_NEAR(
yaw_, p[2], 1e-2);
523 ASSERT_NEAR(
pos_[0], p[0], 1e-1);
524 ASSERT_NEAR(
pos_[1], p[1], 1e-1);
531 nh.
param(
"/use_sim_time", use_sim_time,
false);
541 rosgraph_msgs::Clock clock;
542 clock.clock.fromNSec(time.
toNSec());
549 int main(
int argc,
char** argv)
551 testing::InitGoogleTest(&argc, argv);
552 ros::init(argc, argv,
"test_trajectory_tracker");
556 return RUN_ALL_TESTS();
void publish(const boost::shared_ptr< M > &message) const
void publishPath(const std::vector< Eigen::Vector3d > &poses)
geometry_msgs::Twist::ConstPtr cmd_vel_
tf2_ros::TransformBroadcaster tfb_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void cbCmdVel(const geometry_msgs::Twist::ConstPtr &msg)
ros::Publisher pub_path_vel_
geometry_msgs::TransformStamped t
trajectory_tracker_msgs::TrajectoryTrackerStatus::ConstPtr status_
ros::Subscriber sub_cmd_vel_
int main(int argc, char **argv)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
ros::Subscriber sub_status_
TEST_F(TrajectoryTrackerTest, StraightStop)
TFSIMD_FORCE_INLINE const tfScalar & x() const
void initState(const Eigen::Vector2d &pos, const float yaw)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void publishPathVelocity(const std::vector< Eigen::Vector4d > &poses)
void cbStatus(const trajectory_tracker_msgs::TrajectoryTrackerStatus::ConstPtr &msg)
ROSCPP_DECL void spinOnce()