Skip to content

Commit f6f3f25

Browse files
Merge pull request #172 from Yaskawa-Global/debug_tf
Correct `/tf` calculation for base tracks
2 parents 62ac8ed + 8950ca5 commit f6f3f25

16 files changed

+280
-45
lines changed

src/MathConstants.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
#define DEGREES_PER_RAD (57.295779513082)
1717

1818
// macro
19-
#define NANOMETERS_TO_METERS(x) (x * 0.000001)
19+
#define MICROMETERS_TO_METERS(x) (x * 0.000001)
20+
#define METERS_TO_MICROMETERS(x) (x * 1000000)
21+
#define RAD_TO_DEG_0001(x) (x * DEGREES_PER_RAD * 10000)
22+
#define DEG_0001_TO_RAD(x) ((x / 10000) * RAD_PER_DEGREE)
2023

2124
// used for comparing floating point values
2225
#define EPSILON_TOLERANCE_DOUBLE (0.001)

src/MotoROS.h

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
//============================================
5151
#include <std_srvs/srv/trigger.h>
5252
#include <sensor_msgs/msg/joint_state.h>
53+
#include <geometry_msgs/msg/pose.h>
5354
#include <geometry_msgs/msg/transform_stamped.h>
5455
#include <geometry_msgs/msg/quaternion.h>
5556
#include <tf2_msgs/msg/tf_message.h>
@@ -98,11 +99,14 @@
9899
#include "RosApiNameConstants.h"
99100
#include "TimeConversionUtils.h"
100101
#include "Tests_CtrlGroup.h"
102+
#include "Tests_TestUtils.h"
103+
#include "Tests_RosMotoPlusConversionUtils.h"
101104
#include "FauxCommandLineArgs.h"
102105
#include "InformCheckerAndGenerator.h"
103106
#include "MathConstants.h"
104107
#include "MotoROS_PlatformLib.h"
105108
#include "Ros_mpGetRobotCalibrationData.h"
109+
#include "RosMotoPlusConversionUtils.h"
106110

107111
extern void Ros_Sleep(float milliseconds);
108112

src/MotoROS2_AllControllers.vcxproj

+6
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,8 @@
344344
<ClCompile Include="ServiceStartTrajMode.c" />
345345
<ClCompile Include="ServiceSelectMotionTool.c" />
346346
<ClCompile Include="Tests_CtrlGroup.c" />
347+
<ClCompile Include="Tests_TestUtils.c" />
348+
<ClCompile Include="Tests_RosMotoPlusConversionUtils.c" />
347349
<ClCompile Include="MotionControl.c" />
348350
<ClCompile Include="ActionServer_FJT.c" />
349351
<ClCompile Include="main.c" />
@@ -352,6 +354,7 @@
352354
<ClCompile Include="ServiceResetError.c" />
353355
<ClCompile Include="FauxCommandLineArgs.c" />
354356
<ClCompile Include="Ros_mpGetRobotCalibrationData.c" />
357+
<ClCompile Include="RosMotoPlusConversionUtils.c" />
355358
</ItemGroup>
356359
<ItemGroup>
357360
<ClInclude Include="ConfigFile.h" />
@@ -373,6 +376,8 @@
373376
<ClInclude Include="ServiceStartTrajMode.h" />
374377
<ClInclude Include="ServiceSelectMotionTool.h" />
375378
<ClInclude Include="Tests_CtrlGroup.h" />
379+
<ClInclude Include="Tests_TestUtils.h" />
380+
<ClInclude Include="Tests_RosMotoPlusConversionUtils.h" />
376381
<ClInclude Include="TimeConversionUtils.h" />
377382
<ClInclude Include="MotionControl.h" />
378383
<ClInclude Include="ActionServer_FJT.h" />
@@ -386,6 +391,7 @@
386391
<ClInclude Include="MathConstants.h" />
387392
<ClInclude Include="MotoROS_PlatformLib.h" />
388393
<ClInclude Include="Ros_mpGetRobotCalibrationData.h" />
394+
<ClInclude Include="RosMotoPlusConversionUtils.h" />
389395
</ItemGroup>
390396
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
391397
<ImportGroup Label="ExtensionTargets">

src/MotoROS2_AllControllers.vcxproj.filters

+18
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,12 @@
306306
<ClCompile Include="Tests_CtrlGroup.c">
307307
<Filter>Source Files\Tests</Filter>
308308
</ClCompile>
309+
<ClCompile Include="Tests_TestUtils.c">
310+
<Filter>Source Files\Tests</Filter>
311+
</ClCompile>
312+
<ClCompile Include="Tests_RosMotoPlusConversionUtils.c">
313+
<Filter>Source Files\Tests</Filter>
314+
</ClCompile>
309315
<ClCompile Include="InformCheckerAndGenerator.c">
310316
<Filter>Source Files\Robot Controller</Filter>
311317
</ClCompile>
@@ -321,6 +327,9 @@
321327
<ClCompile Include="Ros_mpGetRobotCalibrationData.c">
322328
<Filter>Source Files\Robot Controller</Filter>
323329
</ClCompile>
330+
<ClCompile Include="RosMotoPlusConversionUtils.c">
331+
<Filter>Source Files\Utilities</Filter>
332+
</ClCompile>
324333
</ItemGroup>
325334
<ItemGroup>
326335
<ClInclude Include="MotoROS.h">
@@ -338,6 +347,12 @@
338347
<ClInclude Include="Tests_CtrlGroup.h">
339348
<Filter>Header Files\Tests</Filter>
340349
</ClInclude>
350+
<ClInclude Include="Tests_TestUtils.h">
351+
<Filter>Header Files\Tests</Filter>
352+
</ClInclude>
353+
<ClInclude Include="Tests_RosMotoPlusConversionUtils.h">
354+
<Filter>Header Files\Tests</Filter>
355+
</ClInclude>
341356
<ClInclude Include="ConfigFile.h">
342357
<Filter>Header Files\Parameters and Config</Filter>
343358
</ClInclude>
@@ -401,6 +416,9 @@
401416
<ClInclude Include="TimeConversionUtils.h">
402417
<Filter>Header Files\Utilities</Filter>
403418
</ClInclude>
419+
<ClInclude Include="RosMotoPlusConversionUtils.h">
420+
<Filter>Header Files\Utilities</Filter>
421+
</ClInclude>
404422
<ClInclude Include="MotoPlusExterns.h">
405423
<Filter>Header Files\Robot Controller</Filter>
406424
</ClInclude>

src/ParameterExtraction.dnLib

0 Bytes
Binary file not shown.

src/ParameterExtraction.yrcLib

982 Bytes
Binary file not shown.

src/ParameterExtraction.yrcmLib

982 Bytes
Binary file not shown.

src/PositionMonitor.c

+10-22
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,12 @@ void Ros_PositionMonitor_CalculateTransforms(int groupIndex, long* pulsePos_moto
295295
{
296296
switch (group->baseTrackInfo.motionType[i])
297297
{
298-
case MOTION_TYPE_X: coordTrackTravel.x = track_pos_meters[i]; break;
299-
case MOTION_TYPE_Y: coordTrackTravel.y = track_pos_meters[i]; break;
300-
case MOTION_TYPE_Z: coordTrackTravel.z = track_pos_meters[i]; break;
301-
case MOTION_TYPE_RX: coordTrackTravel.rx = track_pos_meters[i]; break;
302-
case MOTION_TYPE_RY: coordTrackTravel.ry = track_pos_meters[i]; break;
303-
case MOTION_TYPE_RZ: coordTrackTravel.rz = track_pos_meters[i]; break;
298+
case MOTION_TYPE_X: coordTrackTravel.x = METERS_TO_MICROMETERS(track_pos_meters[i]); break;
299+
case MOTION_TYPE_Y: coordTrackTravel.y = METERS_TO_MICROMETERS(track_pos_meters[i]); break;
300+
case MOTION_TYPE_Z: coordTrackTravel.z = METERS_TO_MICROMETERS(track_pos_meters[i]); break;
301+
case MOTION_TYPE_RX: coordTrackTravel.rx = RAD_TO_DEG_0001(track_pos_meters[i]); break;
302+
case MOTION_TYPE_RY: coordTrackTravel.ry = RAD_TO_DEG_0001(track_pos_meters[i]); break;
303+
case MOTION_TYPE_RZ: coordTrackTravel.rz = RAD_TO_DEG_0001(track_pos_meters[i]); break;
304304
}
305305
}
306306
mpZYXeulerToFrame(&coordWorldToBase, &frameWorldToTrack);
@@ -314,10 +314,7 @@ void Ros_PositionMonitor_CalculateTransforms(int groupIndex, long* pulsePos_moto
314314
}
315315

316316
geometry_msgs__msg__Transform* transform = &g_messages_PositionMonitor.transform->transforms.data[(groupIndex * NUMBER_TRANSFORM_LINKS_PER_ROBOT) + tfLink_WorldToBase].transform;
317-
transform->translation.x = NANOMETERS_TO_METERS(coordWorldToBase.x);
318-
transform->translation.y = NANOMETERS_TO_METERS(coordWorldToBase.y);
319-
transform->translation.z = NANOMETERS_TO_METERS(coordWorldToBase.z);
320-
QuatConversion_MpCoordOrient_To_GeomMsgsQuaternion(coordWorldToBase.rx, coordWorldToBase.ry, coordWorldToBase.rz, &transform->rotation);
317+
Ros_MpCoord_To_GeomMsgsTransform(&coordWorldToBase, transform);
321318

322319
//============================
323320
// Calculate Flange and Tool0
@@ -374,22 +371,13 @@ void Ros_PositionMonitor_CalculateTransforms(int groupIndex, long* pulsePos_moto
374371
//=======================
375372

376373
transform = &g_messages_PositionMonitor.transform->transforms.data[(groupIndex * NUMBER_TRANSFORM_LINKS_PER_ROBOT) + tfLink_BaseToFlange].transform;
377-
transform->translation.x = NANOMETERS_TO_METERS(coordBaseToFlange.x);
378-
transform->translation.y = NANOMETERS_TO_METERS(coordBaseToFlange.y);
379-
transform->translation.z = NANOMETERS_TO_METERS(coordBaseToFlange.z);
380-
QuatConversion_MpCoordOrient_To_GeomMsgsQuaternion(coordBaseToFlange.rx, coordBaseToFlange.ry, coordBaseToFlange.rz, &transform->rotation);
374+
Ros_MpCoord_To_GeomMsgsTransform(&coordBaseToFlange, transform);
381375

382376
transform = &g_messages_PositionMonitor.transform->transforms.data[(groupIndex * NUMBER_TRANSFORM_LINKS_PER_ROBOT) + tfLink_FlangeToTool0].transform;
383-
transform->translation.x = NANOMETERS_TO_METERS(coordFlangeToTool0.x);
384-
transform->translation.y = NANOMETERS_TO_METERS(coordFlangeToTool0.y);
385-
transform->translation.z = NANOMETERS_TO_METERS(coordFlangeToTool0.z);
386-
QuatConversion_MpCoordOrient_To_GeomMsgsQuaternion(coordFlangeToTool0.rx, coordFlangeToTool0.ry, coordFlangeToTool0.rz, &transform->rotation);
377+
Ros_MpCoord_To_GeomMsgsTransform(&coordFlangeToTool0, transform);
387378

388379
transform = &g_messages_PositionMonitor.transform->transforms.data[(groupIndex * NUMBER_TRANSFORM_LINKS_PER_ROBOT) + tfLink_FlangeToTcp].transform;
389-
transform->translation.x = NANOMETERS_TO_METERS(coordToolData.x);
390-
transform->translation.y = NANOMETERS_TO_METERS(coordToolData.y);
391-
transform->translation.z = NANOMETERS_TO_METERS(coordToolData.z);
392-
QuatConversion_MpCoordOrient_To_GeomMsgsQuaternion(coordToolData.rx, coordToolData.ry, coordToolData.rz, &transform->rotation);
380+
Ros_MpCoord_To_GeomMsgsTransform(&coordToolData, transform);
393381
}
394382

395383
void Ros_PositionMonitor_UpdateLocation()

src/RosMotoPlusConversionUtils.c

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//RosMotoPlusConversionUtils.c
2+
3+
// SPDX-FileCopyrightText: 2023, Yaskawa America, Inc.
4+
// SPDX-FileCopyrightText: 2023, Delft University of Technology
5+
//
6+
// SPDX-License-Identifier: Apache-2.0
7+
8+
#include "MotoROS.h"
9+
10+
11+
void Ros_MpCoord_To_GeomMsgsPose(MP_COORD const* const mp_coord, geometry_msgs__msg__Pose* const ros_pose)
12+
{
13+
ros_pose->position.x = MICROMETERS_TO_METERS(mp_coord->x);
14+
ros_pose->position.y = MICROMETERS_TO_METERS(mp_coord->y);
15+
ros_pose->position.z = MICROMETERS_TO_METERS(mp_coord->z);
16+
QuatConversion_MpCoordOrient_To_GeomMsgsQuaternion(
17+
mp_coord->rx, mp_coord->ry, mp_coord->rz, &ros_pose->orientation);
18+
}
19+
20+
void Ros_MpCoord_To_GeomMsgsTransform(MP_COORD const* const mp_coord, geometry_msgs__msg__Transform* const ros_transform)
21+
{
22+
ros_transform->translation.x = MICROMETERS_TO_METERS(mp_coord->x);
23+
ros_transform->translation.y = MICROMETERS_TO_METERS(mp_coord->y);
24+
ros_transform->translation.z = MICROMETERS_TO_METERS(mp_coord->z);
25+
QuatConversion_MpCoordOrient_To_GeomMsgsQuaternion(
26+
mp_coord->rx, mp_coord->ry, mp_coord->rz, &ros_transform->rotation);
27+
}

src/RosMotoPlusConversionUtils.h

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//RosMotoPlusConversionUtils.h
2+
3+
// SPDX-FileCopyrightText: 2023, Yaskawa America, Inc.
4+
// SPDX-FileCopyrightText: 2023, Delft University of Technology
5+
//
6+
// SPDX-License-Identifier: Apache-2.0
7+
8+
#ifndef MOTOROS2_ROS_MOTOPLUS_CONVERSION_UTILS_H
9+
#define MOTOROS2_ROS_MOTOPLUS_CONVERSION_UTILS_H
10+
11+
12+
/**
13+
* Converts an M+ `MP_COORD` struct to a ROS `geometry_msgs/msg/Pose`.
14+
*
15+
* Unit conversion is also performed by this function:
16+
*
17+
* - `MP_COORD` positions are converted from micro-meters to meters
18+
* - `MP_COORD` orientations are converted from milli-degrees to radians (and
19+
* subsequently to a `Quaternion`)
20+
*
21+
* @param mp_coord Input M+ `MP_COORD` instance
22+
* @param ros_pose Output `geometry_msgs/msg/Pose`
23+
*/
24+
extern void Ros_MpCoord_To_GeomMsgsPose(MP_COORD const* const mp_coord, geometry_msgs__msg__Pose* const ros_pose);
25+
26+
27+
/**
28+
* Converts an M+ `MP_COORD` struct to a ROS `geometry_msgs/msg/Transform`.
29+
*
30+
* Unit conversion is also performed by this function:
31+
*
32+
* - `MP_COORD` positions are converted from micro-meters to meters
33+
* - `MP_COORD` orientations are converted from milli-degrees to radians (and
34+
* subsequently to a `Quaternion`)
35+
*
36+
* @param mp_coord Input M+ `MP_COORD` instance
37+
* @param ros_transform Output `geometry_msgs/msg/Pose`
38+
*/
39+
extern void Ros_MpCoord_To_GeomMsgsTransform(MP_COORD const* const mp_coord, geometry_msgs__msg__Transform* const ros_transform);
40+
41+
42+
#endif // MOTOROS2_ROS_MOTOPLUS_CONVERSION_UTILS_H

src/Tests_CtrlGroup.c

-21
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,6 @@
99

1010
#include "MotoROS.h"
1111

12-
BOOL Ros_Testing_CompareDouble(double a, double b)
13-
{
14-
BOOL ok = fabs(a - b) < EPSILON_TOLERANCE_DOUBLE; //this approach has potential flaws, but it works just fine for these simple tests
15-
16-
if (!ok)
17-
Ros_Debug_BroadcastMsg("Fail: %.04f != %.04f", a, b);
18-
19-
return ok;
20-
}
21-
22-
// This is necessary because rounding errors can cause the converted positions to be wrong by a pulse-count or two
23-
BOOL Ros_Testing_CompareLong(long a, long b)
24-
{
25-
BOOL ok = fabs(a - b) < EPSILON_TOLERANCE_PULSECOUNT; //this approach has potential flaws, but it works just fine for these simple tests
26-
27-
if (!ok)
28-
Ros_Debug_BroadcastMsg("Fail: %d != %d", a, b);
29-
30-
return ok;
31-
}
32-
3312
void Ros_Testing_CtrlGroup_MakeFake6dofRobot(CtrlGroup* group)
3413
{
3514
bzero(group, sizeof(CtrlGroup));
+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Tests_RosMotoPlusConversionUtils.c
2+
3+
// SPDX-FileCopyrightText: 2023, Yaskawa America, Inc.
4+
// SPDX-FileCopyrightText: 2023, Delft University of Technology
5+
//
6+
// SPDX-License-Identifier: Apache-2.0
7+
8+
#ifdef MOTOROS2_TESTING_ENABLE
9+
10+
#include "MotoROS.h"
11+
12+
13+
BOOL Ros_Testing_Ros_MpCoord_To_GeomMsgsPose()
14+
{
15+
BOOL bSuccess = TRUE;
16+
MP_COORD mp_coord_ = { 0 };
17+
geometry_msgs__msg__Pose ros_pose_ = { { 0 } };
18+
19+
mp_coord_.x = 1e6;
20+
mp_coord_.y = 2e6;
21+
mp_coord_.z = 3e6;
22+
mp_coord_.rx = 4;
23+
mp_coord_.ry = 5;
24+
mp_coord_.rz = 6;
25+
26+
Ros_MpCoord_To_GeomMsgsPose(&mp_coord_, &ros_pose_);
27+
28+
// position is in micro-meters originally, so the ROS type should have it
29+
// in meters
30+
bSuccess &= Ros_Testing_CompareDouble(1.0, ros_pose_.position.x);
31+
bSuccess &= Ros_Testing_CompareDouble(2.0, ros_pose_.position.y);
32+
bSuccess &= Ros_Testing_CompareDouble(3.0, ros_pose_.position.z);
33+
34+
// orientation is a Quaternion (and 'in' radians)
35+
// use the inverse (quaternion -> MP_COORD) and compare to the original
36+
LONG rx_ = 0, ry_ = 0, rz_ = 0;
37+
QuatConversion_GeomMsgsQuaternion_To_MpCoordOrient(
38+
&ros_pose_.orientation, &rx_, &ry_, &rz_);
39+
40+
// NOTE: this is not a strict equals test right now (uses non-zero epsilon)
41+
bSuccess &= Ros_Testing_CompareLong(mp_coord_.rx, rx_);
42+
bSuccess &= Ros_Testing_CompareLong(mp_coord_.ry, ry_);
43+
bSuccess &= Ros_Testing_CompareLong(mp_coord_.rz, rz_);
44+
45+
Ros_Debug_BroadcastMsg("Testing Ros_MpCoord_To_GeomMsgsPose: %s", bSuccess ? "PASS" : "FAIL");
46+
return bSuccess;
47+
}
48+
49+
BOOL Ros_Testing_Ros_MpCoord_To_GeomMsgsTransform()
50+
{
51+
BOOL bSuccess = TRUE;
52+
MP_COORD mp_coord_ = { 0 };
53+
geometry_msgs__msg__Transform ros_tf_ = { { 0 } };
54+
55+
mp_coord_.x = 4e6;
56+
mp_coord_.y = 5e6;
57+
mp_coord_.z = 6e6;
58+
mp_coord_.rx = 1;
59+
mp_coord_.ry = 2;
60+
mp_coord_.rz = 3;
61+
62+
Ros_MpCoord_To_GeomMsgsTransform(&mp_coord_, &ros_tf_);
63+
64+
// translation is in micro-meters originally, so the ROS type should have it
65+
// in meters
66+
bSuccess &= Ros_Testing_CompareDouble(4.0, ros_tf_.translation.x);
67+
bSuccess &= Ros_Testing_CompareDouble(5.0, ros_tf_.translation.y);
68+
bSuccess &= Ros_Testing_CompareDouble(6.0, ros_tf_.translation.z);
69+
70+
// rotation is a Quaternion (and 'in' radians)
71+
// use the inverse (quaternion -> MP_COORD) and compare to the original
72+
LONG rx_ = 0, ry_ = 0, rz_ = 0;
73+
QuatConversion_GeomMsgsQuaternion_To_MpCoordOrient(
74+
&ros_tf_.rotation, &rx_, &ry_, &rz_);
75+
76+
// NOTE: this is not a strict equals test right now (uses non-zero epsilon)
77+
bSuccess &= Ros_Testing_CompareLong(mp_coord_.rx, rx_);
78+
bSuccess &= Ros_Testing_CompareLong(mp_coord_.ry, ry_);
79+
bSuccess &= Ros_Testing_CompareLong(mp_coord_.rz, rz_);
80+
81+
Ros_Debug_BroadcastMsg("Testing Ros_MpCoord_To_GeomMsgsTransform: %s", bSuccess ? "PASS" : "FAIL");
82+
return bSuccess;
83+
}
84+
85+
BOOL Ros_Testing_RosMotoPlusConversionUtils()
86+
{
87+
BOOL bSuccess = TRUE;
88+
89+
bSuccess &= Ros_Testing_Ros_MpCoord_To_GeomMsgsPose();
90+
bSuccess &= Ros_Testing_Ros_MpCoord_To_GeomMsgsTransform();
91+
92+
return bSuccess;
93+
}
94+
95+
#endif //MOTOROS2_TESTING_ENABLE
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Tests_RosMotoPlusConversionUtils.h
2+
3+
// SPDX-FileCopyrightText: 2023, Yaskawa America, Inc.
4+
// SPDX-FileCopyrightText: 2023, Delft University of Technology
5+
//
6+
// SPDX-License-Identifier: Apache-2.0
7+
8+
#ifndef MOTOROS2_TESTS_ROS_MOTO_PLUS_CONVERSION_UTILS_H
9+
#define MOTOROS2_TESTS_ROS_MOTO_PLUS_CONVERSION_UTILS_H
10+
11+
#ifdef MOTOROS2_TESTING_ENABLE
12+
13+
extern BOOL Ros_Testing_RosMotoPlusConversionUtils();
14+
15+
#endif //MOTOROS2_TESTING_ENABLE
16+
17+
#endif // MOTOROS2_TESTS_ROS_MOTO_PLUS_CONVERSION_UTILS_H

0 commit comments

Comments
 (0)