test_trajectory_point_interface.cpp
Go to the documentation of this file.
1 // -- BEGIN LICENSE BLOCK ----------------------------------------------
2 // Copyright 2022 Universal Robots A/S
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of the {copyright_holder} nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 // -- END LICENSE BLOCK ------------------------------------------------
30 
31 #include <gtest/gtest.h>
34 
35 using namespace urcl;
36 
37 class TrajectoryPointInterfaceTest : public ::testing::Test
38 {
39 protected:
40  class Client : public comm::TCPSocket
41  {
42  public:
43  Client(const int& port)
44  {
45  std::string host = "127.0.0.1";
46  TCPSocket::setup(host, port);
47  timeval tv;
48  tv.tv_sec = 1;
49  tv.tv_usec = 0;
50  TCPSocket::setReceiveTimeout(tv);
51  }
52 
53  void send(const int32_t& result)
54  {
55  uint8_t buffer[sizeof(int32_t)];
56  int32_t val = htobe32(result);
57  std::memcpy(buffer, &val, sizeof(int32_t));
58  size_t written = 0;
59  TCPSocket::write(buffer, sizeof(buffer), written);
60  }
61 
62  void readMessage(vector6int32_t& pos, vector6int32_t& vel, vector6int32_t& acc, int32_t& goal_time,
63  int32_t& blend_radius_or_spline_type, int32_t& motion_type)
64  {
65  // Read message
66  uint8_t buf[sizeof(int32_t) * 21];
67  uint8_t* b_pos = buf;
68  size_t read = 0;
69  size_t remainder = sizeof(int32_t) * 21;
70  while (remainder > 0)
71  {
72  TCPSocket::setOptions(getSocketFD());
73  if (!TCPSocket::read(b_pos, remainder, read))
74  {
75  std::cout << "Failed to read from socket, this should not happen during a test!" << std::endl;
76  break;
77  }
78  b_pos += read;
79  remainder -= read;
80  }
81 
82  // Decode positions
83  int32_t val;
84  b_pos = buf;
85  for (unsigned int i = 0; i < pos.size(); ++i)
86  {
87  std::memcpy(&val, b_pos, sizeof(int32_t));
88  pos[i] = be32toh(val);
89  b_pos += sizeof(int32_t);
90  }
91 
92  // Read velocity
93  for (unsigned int i = 0; i < pos.size(); ++i)
94  {
95  std::memcpy(&val, b_pos, sizeof(int32_t));
96  vel[i] = be32toh(val);
97  b_pos += sizeof(int32_t);
98  }
99 
100  // Read acceleration
101  for (unsigned int i = 0; i < pos.size(); ++i)
102  {
103  std::memcpy(&val, b_pos, sizeof(int32_t));
104  acc[i] = be32toh(val);
105  b_pos += sizeof(int32_t);
106  }
107 
108  // Decode goal time
109  std::memcpy(&val, b_pos, sizeof(int32_t));
110  goal_time = be32toh(val);
111  b_pos += sizeof(int32_t);
112 
113  // Decode blend radius or spline type
114  std::memcpy(&val, b_pos, sizeof(int32_t));
115  blend_radius_or_spline_type = be32toh(val);
116  b_pos += sizeof(int32_t);
117 
118  // Decode motion type
119  std::memcpy(&val, b_pos, sizeof(int32_t));
120  motion_type = be32toh(val);
121  }
122 
124  {
125  int32_t goal_time, blend_radius_or_spline_type, motion_type;
126  vector6int32_t pos, vel, acc;
127  readMessage(pos, vel, acc, goal_time, blend_radius_or_spline_type, motion_type);
128  return pos;
129  }
130 
132  {
133  int32_t goal_time, blend_radius_or_spline_type, motion_type;
134  vector6int32_t pos, vel, acc;
135  readMessage(pos, vel, acc, goal_time, blend_radius_or_spline_type, motion_type);
136  return vel;
137  }
138 
139  int32_t getGoalTime()
140  {
141  int32_t goal_time, blend_radius_or_spline_type, motion_type;
142  vector6int32_t pos, vel, acc;
143  readMessage(pos, vel, acc, goal_time, blend_radius_or_spline_type, motion_type);
144  return goal_time;
145  }
146 
147  int32_t getBlendRadius()
148  {
149  int32_t goal_time, blend_radius_or_spline_type, motion_type;
150  vector6int32_t pos, vel, acc;
151  readMessage(pos, vel, acc, goal_time, blend_radius_or_spline_type, motion_type);
152  return blend_radius_or_spline_type;
153  }
154 
155  int32_t getMotionType()
156  {
157  int32_t goal_time, blend_radius_or_spline_type, motion_type;
158  vector6int32_t pos, vel, acc;
159  readMessage(pos, vel, acc, goal_time, blend_radius_or_spline_type, motion_type);
160  return motion_type;
161  }
162 
163  struct TrajData
164  {
165  vector6int32_t pos, vel, acc;
166  int32_t goal_time, blend_radius_or_spline_type, motion_type;
167  };
168 
170  {
171  TrajData spl;
172  readMessage(spl.pos, spl.vel, spl.acc, spl.goal_time, spl.blend_radius_or_spline_type, spl.motion_type);
173  return spl;
174  }
175 
176  protected:
177  virtual bool open(int socket_fd, struct sockaddr* address, size_t address_len)
178  {
179  return ::connect(socket_fd, address, address_len) == 0;
180  }
181  };
182 
183  void SetUp()
184  {
185  traj_point_interface_.reset(new control::TrajectoryPointInterface(50003));
186  client_.reset(new Client(50003));
187  // Need to be sure that the client has connected to the server
188  std::this_thread::sleep_for(std::chrono::seconds(1));
189  }
190 
191  void TearDown()
192  {
193  if (client_->getState() == comm::SocketState::Connected)
194  {
195  client_->close();
196  }
197  }
198 
199  std::unique_ptr<control::TrajectoryPointInterface> traj_point_interface_;
200  std::unique_ptr<Client> client_;
201 
202 public:
204  {
205  std::lock_guard<std::mutex> lk(trajectory_end_mutex_);
206  trajectory_end_.notify_one();
207  result_ = result;
208  }
209 
210  bool waitTrajectoryEnd(int milliseconds = 100,
212  {
213  std::unique_lock<std::mutex> lk(trajectory_end_mutex_);
214  if (trajectory_end_.wait_for(lk, std::chrono::milliseconds(milliseconds)) == std::cv_status::no_timeout ||
215  result_ == result)
216  {
217  if (result_ == result)
218  {
219  return true;
220  }
221  }
222  return false;
223  }
224 
225 private:
226  std::condition_variable trajectory_end_;
229 };
230 
232 {
233  urcl::vector6d_t send_positions = { 1.2, 3.1, 2.2, -3.4, -1.1, -1.2 };
234  traj_point_interface_->writeTrajectoryPoint(&send_positions, 0, 0, 0);
235  vector6int32_t received_positions = client_->getPosition();
236 
237  EXPECT_EQ(send_positions[0], ((double)received_positions[0]) / traj_point_interface_->MULT_JOINTSTATE);
238  EXPECT_EQ(send_positions[1], ((double)received_positions[1]) / traj_point_interface_->MULT_JOINTSTATE);
239  EXPECT_EQ(send_positions[2], ((double)received_positions[2]) / traj_point_interface_->MULT_JOINTSTATE);
240  EXPECT_EQ(send_positions[3], ((double)received_positions[3]) / traj_point_interface_->MULT_JOINTSTATE);
241  EXPECT_EQ(send_positions[4], ((double)received_positions[4]) / traj_point_interface_->MULT_JOINTSTATE);
242  EXPECT_EQ(send_positions[5], ((double)received_positions[5]) / traj_point_interface_->MULT_JOINTSTATE);
243 }
244 
245 TEST_F(TrajectoryPointInterfaceTest, write_quintic_joint_spline)
246 {
247  urcl::vector6d_t send_pos = { 1.2, 3.1, 2.2, -1.4, -2.1, -3.2 };
248  urcl::vector6d_t send_vel = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
249  urcl::vector6d_t send_acc = { 3.2, 1.1, 1.2, -3.4, -1.1, -1.2 };
250  float send_goal_time = 0.5;
251  traj_point_interface_->writeTrajectorySplinePoint(&send_pos, &send_vel, &send_acc, send_goal_time);
252  Client::TrajData received_data = client_->getData();
253 
254  // Position
255  EXPECT_EQ(send_pos[0], ((double)received_data.pos[0]) / traj_point_interface_->MULT_JOINTSTATE);
256  EXPECT_EQ(send_pos[1], ((double)received_data.pos[1]) / traj_point_interface_->MULT_JOINTSTATE);
257  EXPECT_EQ(send_pos[2], ((double)received_data.pos[2]) / traj_point_interface_->MULT_JOINTSTATE);
258  EXPECT_EQ(send_pos[3], ((double)received_data.pos[3]) / traj_point_interface_->MULT_JOINTSTATE);
259  EXPECT_EQ(send_pos[4], ((double)received_data.pos[4]) / traj_point_interface_->MULT_JOINTSTATE);
260  EXPECT_EQ(send_pos[5], ((double)received_data.pos[5]) / traj_point_interface_->MULT_JOINTSTATE);
261 
262  // Velocities
263  EXPECT_EQ(send_vel[0], ((double)received_data.vel[0]) / traj_point_interface_->MULT_JOINTSTATE);
264  EXPECT_EQ(send_vel[1], ((double)received_data.vel[1]) / traj_point_interface_->MULT_JOINTSTATE);
265  EXPECT_EQ(send_vel[2], ((double)received_data.vel[2]) / traj_point_interface_->MULT_JOINTSTATE);
266  EXPECT_EQ(send_vel[3], ((double)received_data.vel[3]) / traj_point_interface_->MULT_JOINTSTATE);
267  EXPECT_EQ(send_vel[4], ((double)received_data.vel[4]) / traj_point_interface_->MULT_JOINTSTATE);
268  EXPECT_EQ(send_vel[5], ((double)received_data.vel[5]) / traj_point_interface_->MULT_JOINTSTATE);
269 
270  // Velocities
271  EXPECT_EQ(send_acc[0], ((double)received_data.acc[0]) / traj_point_interface_->MULT_JOINTSTATE);
272  EXPECT_EQ(send_acc[1], ((double)received_data.acc[1]) / traj_point_interface_->MULT_JOINTSTATE);
273  EXPECT_EQ(send_acc[2], ((double)received_data.acc[2]) / traj_point_interface_->MULT_JOINTSTATE);
274  EXPECT_EQ(send_acc[3], ((double)received_data.acc[3]) / traj_point_interface_->MULT_JOINTSTATE);
275  EXPECT_EQ(send_acc[4], ((double)received_data.acc[4]) / traj_point_interface_->MULT_JOINTSTATE);
276  EXPECT_EQ(send_acc[5], ((double)received_data.acc[5]) / traj_point_interface_->MULT_JOINTSTATE);
277 
278  // Goal time
279  EXPECT_EQ(send_goal_time, ((double)received_data.goal_time / traj_point_interface_->MULT_TIME));
280 
281  // Spline type
282  EXPECT_EQ(static_cast<int32_t>(control::TrajectorySplineType::SPLINE_QUINTIC),
283  received_data.blend_radius_or_spline_type);
284 
285  // Motion type
286  EXPECT_EQ(static_cast<int32_t>(control::TrajectoryMotionType::JOINT_POINT_SPLINE), received_data.motion_type);
287 }
288 
289 TEST_F(TrajectoryPointInterfaceTest, write_cubic_joint_spline)
290 {
291  urcl::vector6d_t send_pos = { 1.2, 3.1, 2.2, -1.4, -2.1, -3.2 };
292  urcl::vector6d_t send_vel = { 2.2, 2.1, 3.2, -2.4, -3.1, -2.3 };
293  urcl::vector6d_t send_acc = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
294  float send_goal_time = 1.5;
295  traj_point_interface_->writeTrajectorySplinePoint(&send_pos, &send_vel, nullptr, send_goal_time);
296  Client::TrajData received_data = client_->getData();
297 
298  // Position
299  EXPECT_EQ(send_pos[0], ((double)received_data.pos[0]) / traj_point_interface_->MULT_JOINTSTATE);
300  EXPECT_EQ(send_pos[1], ((double)received_data.pos[1]) / traj_point_interface_->MULT_JOINTSTATE);
301  EXPECT_EQ(send_pos[2], ((double)received_data.pos[2]) / traj_point_interface_->MULT_JOINTSTATE);
302  EXPECT_EQ(send_pos[3], ((double)received_data.pos[3]) / traj_point_interface_->MULT_JOINTSTATE);
303  EXPECT_EQ(send_pos[4], ((double)received_data.pos[4]) / traj_point_interface_->MULT_JOINTSTATE);
304  EXPECT_EQ(send_pos[5], ((double)received_data.pos[5]) / traj_point_interface_->MULT_JOINTSTATE);
305 
306  // Velocities
307  EXPECT_EQ(send_vel[0], ((double)received_data.vel[0]) / traj_point_interface_->MULT_JOINTSTATE);
308  EXPECT_EQ(send_vel[1], ((double)received_data.vel[1]) / traj_point_interface_->MULT_JOINTSTATE);
309  EXPECT_EQ(send_vel[2], ((double)received_data.vel[2]) / traj_point_interface_->MULT_JOINTSTATE);
310  EXPECT_EQ(send_vel[3], ((double)received_data.vel[3]) / traj_point_interface_->MULT_JOINTSTATE);
311  EXPECT_EQ(send_vel[4], ((double)received_data.vel[4]) / traj_point_interface_->MULT_JOINTSTATE);
312  EXPECT_EQ(send_vel[5], ((double)received_data.vel[5]) / traj_point_interface_->MULT_JOINTSTATE);
313 
314  // Velocities
315  EXPECT_EQ(send_acc[0], ((double)received_data.acc[0]) / traj_point_interface_->MULT_JOINTSTATE);
316  EXPECT_EQ(send_acc[1], ((double)received_data.acc[1]) / traj_point_interface_->MULT_JOINTSTATE);
317  EXPECT_EQ(send_acc[2], ((double)received_data.acc[2]) / traj_point_interface_->MULT_JOINTSTATE);
318  EXPECT_EQ(send_acc[3], ((double)received_data.acc[3]) / traj_point_interface_->MULT_JOINTSTATE);
319  EXPECT_EQ(send_acc[4], ((double)received_data.acc[4]) / traj_point_interface_->MULT_JOINTSTATE);
320  EXPECT_EQ(send_acc[5], ((double)received_data.acc[5]) / traj_point_interface_->MULT_JOINTSTATE);
321 
322  // Goal time
323  EXPECT_EQ(send_goal_time, ((double)received_data.goal_time) / traj_point_interface_->MULT_TIME);
324 
325  // Spline type
326  EXPECT_EQ(static_cast<int32_t>(control::TrajectorySplineType::SPLINE_CUBIC),
327  received_data.blend_radius_or_spline_type);
328 
329  // Motion type
330  EXPECT_EQ(static_cast<int32_t>(control::TrajectoryMotionType::JOINT_POINT_SPLINE), received_data.motion_type);
331 }
332 
333 TEST_F(TrajectoryPointInterfaceTest, write_splines_velocities)
334 {
335  urcl::vector6d_t send_pos = { 1.2, 3.1, 2.2, -1.4, -2.1, -3.2 };
336  urcl::vector6d_t send_vel = { 2.2, 2.1, 3.2, -2.4, -3.1, -2.2 };
337  urcl::vector6d_t send_acc = { 3.2, 1.1, 1.2, -3.4, -1.1, -1.2 };
338  float send_goal_time = 0.5;
339  traj_point_interface_->writeTrajectorySplinePoint(&send_pos, &send_vel, &send_acc, send_goal_time);
340  vector6int32_t received_velocities = client_->getVelocity();
341 
342  EXPECT_EQ(send_vel[0], ((double)received_velocities[0]) / traj_point_interface_->MULT_JOINTSTATE);
343  EXPECT_EQ(send_vel[1], ((double)received_velocities[1]) / traj_point_interface_->MULT_JOINTSTATE);
344  EXPECT_EQ(send_vel[2], ((double)received_velocities[2]) / traj_point_interface_->MULT_JOINTSTATE);
345  EXPECT_EQ(send_vel[3], ((double)received_velocities[3]) / traj_point_interface_->MULT_JOINTSTATE);
346  EXPECT_EQ(send_vel[4], ((double)received_velocities[4]) / traj_point_interface_->MULT_JOINTSTATE);
347  EXPECT_EQ(send_vel[5], ((double)received_velocities[5]) / traj_point_interface_->MULT_JOINTSTATE);
348 }
349 
350 TEST_F(TrajectoryPointInterfaceTest, write_splines_accelerations)
351 {
352  urcl::vector6d_t send_pos = { 1.2, 3.1, 2.2, -1.4, -2.1, -3.2 };
353  urcl::vector6d_t send_vel = { 2.2, 2.1, 3.2, -2.4, -3.1, -2.2 };
354  urcl::vector6d_t send_acc = { 3.2, 1.1, 1.2, -3.4, -1.1, -1.2 };
355  float send_goal_time = 0.5;
356  traj_point_interface_->writeTrajectorySplinePoint(&send_pos, &send_vel, &send_acc, send_goal_time);
357  vector6int32_t received_velocities = client_->getVelocity();
358 
359  EXPECT_EQ(send_vel[0], ((double)received_velocities[0]) / traj_point_interface_->MULT_JOINTSTATE);
360  EXPECT_EQ(send_vel[1], ((double)received_velocities[1]) / traj_point_interface_->MULT_JOINTSTATE);
361  EXPECT_EQ(send_vel[2], ((double)received_velocities[2]) / traj_point_interface_->MULT_JOINTSTATE);
362  EXPECT_EQ(send_vel[3], ((double)received_velocities[3]) / traj_point_interface_->MULT_JOINTSTATE);
363  EXPECT_EQ(send_vel[4], ((double)received_velocities[4]) / traj_point_interface_->MULT_JOINTSTATE);
364  EXPECT_EQ(send_vel[5], ((double)received_velocities[5]) / traj_point_interface_->MULT_JOINTSTATE);
365 }
366 
368 {
369  urcl::vector6d_t send_positions = { 0, 0, 0, 0, 0, 0 };
370  float send_goal_time = 0.5;
371  traj_point_interface_->writeTrajectoryPoint(&send_positions, send_goal_time, 0, 0);
372  int32_t received_goal_time = client_->getGoalTime();
373 
374  EXPECT_EQ(send_goal_time, ((float)received_goal_time) / traj_point_interface_->MULT_TIME);
375 }
376 
378 {
379  urcl::vector6d_t send_positions = { 0, 0, 0, 0, 0, 0 };
380  float send_blend_radius = 0.5;
381  traj_point_interface_->writeTrajectoryPoint(&send_positions, 0, send_blend_radius, 0);
382  int32_t received_blend_radius = client_->getBlendRadius();
383 
384  EXPECT_EQ(send_blend_radius, ((float)received_blend_radius) / traj_point_interface_->MULT_TIME);
385 }
386 
388 {
389  // Write cartesian point
390  urcl::vector6d_t send_positions = { 0, 0, 0, 0, 0, 0 };
391  bool send_cartesian = true;
392  traj_point_interface_->writeTrajectoryPoint(&send_positions, 0, 0, send_cartesian);
393  bool received_cartesian = bool(client_->getMotionType());
394 
395  EXPECT_EQ(send_cartesian, received_cartesian);
396 
397  // Write joint point
398  send_cartesian = false;
399  traj_point_interface_->writeTrajectoryPoint(&send_positions, 0, 0, send_cartesian);
400  received_cartesian = bool(client_->getMotionType());
401 
402  EXPECT_EQ(send_cartesian, received_cartesian);
403 }
404 
406 {
407  traj_point_interface_->setTrajectoryEndCallback(
408  std::bind(&TrajectoryPointInterfaceTest::handleTrajectoryEnd, this, std::placeholders::_1));
409 
411  EXPECT_TRUE(waitTrajectoryEnd(1000, control::TrajectoryResult::TRAJECTORY_RESULT_CANCELED));
412 
414  EXPECT_TRUE(waitTrajectoryEnd(1000, control::TrajectoryResult::TRAJECTORY_RESULT_FAILURE));
415 
417  EXPECT_TRUE(waitTrajectoryEnd(1000, control::TrajectoryResult::TRAJECTORY_RESULT_SUCCESS));
418 }
419 
420 int main(int argc, char* argv[])
421 {
422  ::testing::InitGoogleTest(&argc, argv);
423 
424  return RUN_ALL_TESTS();
425 }
TrajectoryResult
Types for encoding trajectory execution result.
void handleTrajectoryEnd(control::TrajectoryResult result)
virtual bool open(int socket_fd, struct sockaddr *address, size_t address_len)
The TrajectoryPointInterface class handles trajectory forwarding to the robot. Full trajectories are ...
std::unique_ptr< control::TrajectoryPointInterface > traj_point_interface_
TEST_F(TrajectoryPointInterfaceTest, write_postions)
bool waitTrajectoryEnd(int milliseconds=100, control::TrajectoryResult result=control::TrajectoryResult::TRAJECTORY_RESULT_CANCELED)
Aborted due to error during execution.
void readMessage(vector6int32_t &pos, vector6int32_t &vel, vector6int32_t &acc, int32_t &goal_time, int32_t &blend_radius_or_spline_type, int32_t &motion_type)
std::array< int32_t, 6 > vector6int32_t
Definition: types.h:31
Class for TCP socket abstraction.
Definition: tcp_socket.h:48
constexpr std::underlying_type< E >::type toUnderlying(const E e) noexcept
Converts an enum type to its underlying type.
Definition: types.h:58
Socket is connected and ready to use.
std::array< double, 6 > vector6d_t
Definition: types.h:30
int main(int argc, char *argv[])


ur_client_library
Author(s): Thomas Timm Andersen, Simon Rasmussen, Felix Exner, Lea Steffen, Tristan Schnell
autogenerated on Tue Jul 4 2023 02:09:47