Skip to content

Commit 73e7226

Browse files
felixvdv4hn
andauthored
Use tau instead of pi for rotations (#554)
Tau is the circle constant C/r (diameter over radius) = 2*pi = tau. This makes writing rotations easier. See https://tauday.com/tau-manifesto for more reasoning. * Add more explicit comments * Add clearer radian definition in MGI C++ tutorial Co-authored-by: v4hn <me@v4hn.de>
1 parent 840e121 commit 73e7226

4 files changed

Lines changed: 37 additions & 22 deletions

File tree

doc/move_group_interface/src/move_group_interface_tutorial.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545

4646
#include <moveit_visual_tools/moveit_visual_tools.h>
4747

48+
// The circle constant tau = 2*pi. One tau is one rotation in radians.
49+
const double tau = 2 * M_PI;
50+
4851
int main(int argc, char** argv)
4952
{
5053
ros::init(argc, argv, "move_group_interface_tutorial");
@@ -178,7 +181,7 @@ int main(int argc, char** argv)
178181
current_state->copyJointGroupPositions(joint_model_group, joint_group_positions);
179182

180183
// Now, let's modify one of the joints, plan to the new joint space goal and visualize the plan.
181-
joint_group_positions[0] = -1.0; // radians
184+
joint_group_positions[0] = -tau / 6; // -1/6 turn in radians
182185
move_group.setJointValueTarget(joint_group_positions);
183186

184187
// We lower the allowed maximum velocity and acceleration to 5% of their maximum.

doc/move_group_python_interface/scripts/move_group_python_interface_tutorial.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@
5252
import moveit_msgs.msg
5353
import geometry_msgs.msg
5454
from math import pi, dist, fabs, cos
55+
try:
56+
from math import tau
57+
except: # For Python 2 compatibility
58+
from math import pi
59+
tau = 2.0*pi
5560
from std_msgs.msg import String
5661
from moveit_commander.conversions import pose_to_list
5762
## END_SUB_TUTORIAL
@@ -168,16 +173,17 @@ def go_to_joint_state(self):
168173
##
169174
## Planning to a Joint Goal
170175
## ^^^^^^^^^^^^^^^^^^^^^^^^
171-
## The Panda's zero configuration is at a `singularity <https://www.quora.com/Robotics-What-is-meant-by-kinematic-singularity>`_ so the first
172-
## thing we want to do is move it to a slightly better configuration.
173-
# We can get the joint values from the group and adjust some of the values:
176+
## The Panda's zero configuration is at a `singularity <https://www.quora.com/Robotics-What-is-meant-by-kinematic-singularity>`_, so the first
177+
## thing we want to do is move it to a slightly better configuration.
178+
## We use the constant `tau = 2*pi <https://en.wikipedia.org/wiki/Turn_(angle)#Tau_proposals>`_ for convenience:
179+
# We get the joint values from the group and change some of the values:
174180
joint_goal = move_group.get_current_joint_values()
175181
joint_goal[0] = 0
176-
joint_goal[1] = -pi/4
182+
joint_goal[1] = -tau/8
177183
joint_goal[2] = 0
178-
joint_goal[3] = -pi/2
184+
joint_goal[3] = -tau/4
179185
joint_goal[4] = 0
180-
joint_goal[5] = pi/3
186+
joint_goal[5] = tau/6 # 1/6 of a turn
181187
joint_goal[6] = 0
182188

183189
# The go command can be called with joint values, poses, or without any

doc/pick_place/src/pick_place_tutorial.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
// TF2
4545
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
4646

47+
// The circle constant tau = 2*pi. One tau is one rotation in radians.
48+
const double tau = 2 * M_PI;
49+
4750
void openGripper(trajectory_msgs::JointTrajectory& posture)
4851
{
4952
// BEGIN_SUB_TUTORIAL open_gripper
@@ -94,7 +97,7 @@ void pick(moveit::planning_interface::MoveGroupInterface& move_group)
9497
// transform from `"panda_link8"` to the palm of the end effector.
9598
grasps[0].grasp_pose.header.frame_id = "panda_link0";
9699
tf2::Quaternion orientation;
97-
orientation.setRPY(-M_PI / 2, -M_PI / 4, -M_PI / 2);
100+
orientation.setRPY(-tau / 4, -tau / 8, -tau / 4);
98101
grasps[0].grasp_pose.pose.orientation = tf2::toMsg(orientation);
99102
grasps[0].grasp_pose.pose.position.x = 0.415;
100103
grasps[0].grasp_pose.pose.position.y = 0;
@@ -152,7 +155,7 @@ void place(moveit::planning_interface::MoveGroupInterface& group)
152155
// +++++++++++++++++++++++++++
153156
place_location[0].place_pose.header.frame_id = "panda_link0";
154157
tf2::Quaternion orientation;
155-
orientation.setRPY(0, 0, M_PI / 2);
158+
orientation.setRPY(0, 0, tau / 4); // A quarter turn about the z-axis
156159
place_location[0].place_pose.pose.orientation = tf2::toMsg(orientation);
157160

158161
/* For place location, we set the value to the exact location of the center of the object. */

doc/subframes/src/subframes_tutorial.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
4747
#include <tf2_eigen/tf2_eigen.h>
4848

49+
// The circle constant tau = 2*pi. One tau is one rotation in radians.
50+
const double tau = 2 * M_PI;
51+
4952
// BEGIN_SUB_TUTORIAL plan1
5053
//
5154
// Creating the planning request
@@ -121,35 +124,35 @@ void spawnCollisionObjects(moveit::planning_interface::PlanningSceneInterface& p
121124
box.subframe_poses[0].position.z = 0.0 + z_offset_box;
122125

123126
tf2::Quaternion orientation;
124-
orientation.setRPY(90.0 / 180.0 * M_PI, 0, 0);
127+
orientation.setRPY(tau / 4, 0, 0); // A quarter turn about the x-axis
125128
box.subframe_poses[0].orientation = tf2::toMsg(orientation);
126129
// END_SUB_TUTORIAL
127130

128131
box.subframe_names[1] = "top";
129132
box.subframe_poses[1].position.y = .05;
130133
box.subframe_poses[1].position.z = 0.0 + z_offset_box;
131-
orientation.setRPY(-90.0 / 180.0 * M_PI, 0, 0);
134+
orientation.setRPY(-tau / 4, 0, 0);
132135
box.subframe_poses[1].orientation = tf2::toMsg(orientation);
133136

134137
box.subframe_names[2] = "corner_1";
135138
box.subframe_poses[2].position.x = -.025;
136139
box.subframe_poses[2].position.y = -.05;
137140
box.subframe_poses[2].position.z = -.01 + z_offset_box;
138-
orientation.setRPY(90.0 / 180.0 * M_PI, 0, 0);
141+
orientation.setRPY(tau / 4, 0, 0);
139142
box.subframe_poses[2].orientation = tf2::toMsg(orientation);
140143

141144
box.subframe_names[3] = "corner_2";
142145
box.subframe_poses[3].position.x = .025;
143146
box.subframe_poses[3].position.y = -.05;
144147
box.subframe_poses[3].position.z = -.01 + z_offset_box;
145-
orientation.setRPY(90.0 / 180.0 * M_PI, 0, 0);
148+
orientation.setRPY(tau / 4, 0, 0);
146149
box.subframe_poses[3].orientation = tf2::toMsg(orientation);
147150

148151
box.subframe_names[4] = "side";
149152
box.subframe_poses[4].position.x = .0;
150153
box.subframe_poses[4].position.y = .0;
151154
box.subframe_poses[4].position.z = -.01 + z_offset_box;
152-
orientation.setRPY(0, 180.0 / 180.0 * M_PI, 0);
155+
orientation.setRPY(0, tau / 2, 0);
153156
box.subframe_poses[4].orientation = tf2::toMsg(orientation);
154157

155158
// Next, define the cylinder
@@ -165,7 +168,7 @@ void spawnCollisionObjects(moveit::planning_interface::PlanningSceneInterface& p
165168
cylinder.primitive_poses[0].position.x = 0.0;
166169
cylinder.primitive_poses[0].position.y = 0.0;
167170
cylinder.primitive_poses[0].position.z = 0.0 + z_offset_cylinder;
168-
orientation.setRPY(0, 90.0 / 180.0 * M_PI, 0);
171+
orientation.setRPY(0, tau / 4, 0);
169172
cylinder.primitive_poses[0].orientation = tf2::toMsg(orientation);
170173

171174
cylinder.subframe_poses.resize(1);
@@ -174,7 +177,7 @@ void spawnCollisionObjects(moveit::planning_interface::PlanningSceneInterface& p
174177
cylinder.subframe_poses[0].position.x = 0.03;
175178
cylinder.subframe_poses[0].position.y = 0.0;
176179
cylinder.subframe_poses[0].position.z = 0.0 + z_offset_cylinder;
177-
orientation.setRPY(0, 90.0 / 180.0 * M_PI, 0);
180+
orientation.setRPY(0, tau / 4, 0);
178181
cylinder.subframe_poses[0].orientation = tf2::toMsg(orientation);
179182

180183
// BEGIN_SUB_TUTORIAL object2
@@ -282,7 +285,7 @@ int main(int argc, char** argv)
282285
fixed_pose.header.frame_id = "panda_link0";
283286
fixed_pose.pose.position.y = -.4;
284287
fixed_pose.pose.position.z = .3;
285-
target_orientation.setRPY(0, (-20.0 / 180.0 * M_PI), 0);
288+
target_orientation.setRPY(0, (-20.0 / 360.0 * tau), 0);
286289
fixed_pose.pose.orientation = tf2::toMsg(target_orientation);
287290

288291
// Set up a small command line interface to make the tutorial interactive.
@@ -316,7 +319,7 @@ int main(int argc, char** argv)
316319
// The target pose is given relative to a box subframe:
317320
target_pose.header.frame_id = "box/bottom";
318321
// The orientation is determined by RPY angles to align the cylinder and box subframes:
319-
target_orientation.setRPY(0, 180.0 / 180.0 * M_PI, 90.0 / 180.0 * M_PI);
322+
target_orientation.setRPY(0, tau / 2, tau / 4);
320323
target_pose.pose.orientation = tf2::toMsg(target_orientation);
321324
// To keep some distance to the box, we use a small offset:
322325
target_pose.pose.position.z = 0.01;
@@ -330,7 +333,7 @@ int main(int argc, char** argv)
330333
{
331334
ROS_INFO_STREAM("Moving to top of box with cylinder tip");
332335
target_pose.header.frame_id = "box/top";
333-
target_orientation.setRPY(180.0 / 180.0 * M_PI, 0, 90.0 / 180.0 * M_PI);
336+
target_orientation.setRPY(tau / 2, 0, tau / 4);
334337
target_pose.pose.orientation = tf2::toMsg(target_orientation);
335338
target_pose.pose.position.z = 0.01;
336339
showFrames(target_pose, "cylinder/tip");
@@ -341,7 +344,7 @@ int main(int argc, char** argv)
341344
{
342345
ROS_INFO_STREAM("Moving to corner1 of box with cylinder tip");
343346
target_pose.header.frame_id = "box/corner_1";
344-
target_orientation.setRPY(0, 180.0 / 180.0 * M_PI, 90.0 / 180.0 * M_PI);
347+
target_orientation.setRPY(0, tau / 2, tau / 4);
345348
target_pose.pose.orientation = tf2::toMsg(target_orientation);
346349
target_pose.pose.position.z = 0.01;
347350
showFrames(target_pose, "cylinder/tip");
@@ -350,7 +353,7 @@ int main(int argc, char** argv)
350353
else if (character_input == 4)
351354
{
352355
target_pose.header.frame_id = "box/corner_2";
353-
target_orientation.setRPY(0, 180.0 / 180.0 * M_PI, 90.0 / 180.0 * M_PI);
356+
target_orientation.setRPY(0, tau / 2, tau / 4);
354357
target_pose.pose.orientation = tf2::toMsg(target_orientation);
355358
target_pose.pose.position.z = 0.01;
356359
showFrames(target_pose, "cylinder/tip");
@@ -359,7 +362,7 @@ int main(int argc, char** argv)
359362
else if (character_input == 5)
360363
{
361364
target_pose.header.frame_id = "box/side";
362-
target_orientation.setRPY(0, 180.0 / 180.0 * M_PI, 90.0 / 180.0 * M_PI);
365+
target_orientation.setRPY(0, tau / 2, tau / 4);
363366
target_pose.pose.orientation = tf2::toMsg(target_orientation);
364367
target_pose.pose.position.z = 0.01;
365368
showFrames(target_pose, "cylinder/tip");

0 commit comments

Comments
 (0)