%%capture
'''
(C) Copyright 2020-2025 Murilo Marques Marinho (murilomarinho@ieee.org)
This file is licensed in the terms of the
Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
license.
Derivative work of:
https://github.com/dqrobotics/learning-dqrobotics-in-matlab/tree/master/robotic_manipulators
Contributors to this file:
Murilo Marques Marinho (murilomarinho@ieee.org)
'''
DQ4 Dual Quaternion Basics using DQ Robotics - Part 2¶
I found an issue¶
Thank you! Please report it at https://
Introduction¶
The last lesson introduced dual quaternions, some basic dual quaternion operations; and, most importantly, unit dual quaternions and their ability to represent rigid body motion.
As always, before we start, make essential installations and imports.
%%capture
%pip install dqrobotics dqrobotics-pyplot
%pip install dqrobotics dqrobotics-pyplot --break-system-packages
from dqrobotics import *
from dqrobotics_extensions.pyplot import plot
import matplotlib.pyplot as plt
from math import pi, sin, cos, sqrt
Notation¶
In the last lesson, we learned that unit dual quaternions represent reference frames and pose transformations. In this lesson, we will see that dual quaternions can also represent points, lines, and planes.
Keep these in mind (we will also use this notation when writting papers to conferences and journals):
- : a quaternion. (Bold-face, lowercase character)
- : a dual quaternion. (Bold-face, underlined, lowercase character)
- : pure quaternions. They represent points, positions, and translations. They are quaternions for which .
- : unit quaternions. They represent orientations and rotations. They are quaternions for which .
- : unit dual quaternions. They represent poses and pose transformations. They are dual quaternions for which .
What we have seen so far¶
Points, positions, and translations¶
A pure quaternion, such as , can be used to represent points, positions, and translations. Pure quaternions can be always written in the form
where represent the 3D coordinates.
Orientations and rotations¶
A unit quaternion, , can always be written in the form
where represents the rotation angle and represents the rotation axis.
Reference frames and pose transformations¶
A unit dual quaternion, , can always be written in the form
where is the unit-norm quaternion representing the rotation; and is the quaternion representing the translation.
Lines and planes¶
Unit dual quaternions, besides being used to represent rotations and translations, can also be used to represent lines and planes in 3D space. These geometric primitives are very useful in many robot control scenarios.
Plücker Lines¶
In high-school, you have been introduced to the line equation in 3D space using linear algebra. Using the concept of unit dual quaternions, we can also represent lines, in the form
where is a unit vector representing the line’s direction and is called the line’s moment. The moment is defined as , in which is a point (any point) in the line. A line represented this way is called a Plücker line. Note that a Plücker line is a pure dual quaternion with unit norm, that is .
Pure quaternion cross product¶
Note that is the cross product between pure quaternions, and is defined as
for any . Note that this operation is equivalent to the cross product between vectors in .
Plücker line example¶
Suppose that we want the Plücker line that represents the x-axis. The direction of the line will be
l1=i_
print(f"l1 = {l1}")
l1 = 1i
and a point in the line is
,
p_l1 = DQ([0]) # We use the DQ() constructor so that Python knows its a DQ, not a real number.
print(f"p_l1 = {p_l1}")
p_l1 = 0
because the line crosses the origin. Hence, the moment of the line will be given by
m1 = cross(p_l1,l1)
print(f"m1 = {m1}")
m1 = 0
Hence, the Plücker line representing the origin will be
l1_dq = l1 + E_*m1
print(f"l1_dq = {l1_dq}")
l1_dq = 1i
Checking if a dual quaternion is a line using DQ Robotics¶
Let us check that the Plücker line we calculated is a pure dual quaternion with unit norm. The following two conditions have to hold simultaneously.
is_pure(l1_dq)
True
is_unit(l1_dq)
True
You can also test directly if those two conditions hold simultaneously with
is_line(l1_dq)
True
Plotting lines using DQ Robotics¶
When you plot lines using DQ Robotics you have to specify that you want to plot that unit dual quaternion as a line. For example
plt.figure()
ax = plt.axes(projection='3d')
plot(l1_dq,line=True,scale=5)
plt.show()

Note that a Plücker line is, well, a line (not a line segment). This means that, mathematically, its length is infinite. When plotting, you have to choose how much of the line you want to show on screen. In this example, we are showing 5 meters only.
Planes¶
Also in high-school-level linear-algebra, you have been introduced to the equation of the plane. Unit dual quaternions can also be used to represent planes, in the form
where is the unit vector representing the plane’s normal. In addition, is the signed distance to the plane (with respect to the normal centered at the origin), that can be written as
in which is any point in the plane.
Pure quaternion inner product¶
Note that is the inner product between pure quaternions, and is defined as
for any .
Plane example¶
Suppose that we want one of the unit dual quaternions that represents the x-y plane. One of the normals to the x-y plane (there are two), is given by
n_pi1 = k_
print(f"n_pi1 = {n_pi1}")
n_pi1 = 1k
p_pi1 = DQ([0]) # We use the DQ() constructor so that Python knows its a DQ, not a real number.
print(f"p_pi1 = {p_pi1}")
p_pi1 = 0
Hence, the distance can be calculated as
d_pi1 = dot(p_pi1, n_pi1)
print(f"d_pi1 = {d_pi1}")
d_pi1 = 0
Therefore, the x-y plane can be represented by the unit dual quaternion
pi1 = n_pi1 + E_*d_pi1
print(f"pi1 = {pi1}")
pi1 = 1k
Checking if a dual quaternion is a plane using DQ Robotics¶
We can check if a unit dual quaternion represents a plane if all the following conditions hold simultaneously.
is_unit(pi1)
True
is_pure(P(pi1))
True
is_real(D(pi1))
True
is_plane(pi1)
True
Plotting planes using DQ Robotics¶
When you plot planes using DQ Robotics, you have to specify that you want to plot that unit dual quaternion as a plane. For example
plt.figure()
ax = plt.axes(projection='3d')
plot(pi1,plane=True,scale=5)
plt.show()

Note that a plane line is, mathematically, infinite. When plotting, you have specify its size, in this case 5, and a central location, in this case .
(Signed) distances¶
One important measure for controlling robotic systems is the measurement of distance. The distance is always a real number. In some contexts it might be signed. We will discuss some of those cases.
Point to point distance¶
The distance between two points is the most basic form of distance. Given , the distance between them is given by
For example, using DQ Robotics, this can be calculated as,
p1 = i_+j_
p2 = k_
d_p1_p2 = norm(p1-p2)
print(f"d_p1_p2 = {d_p1_p2}")
d_p1_p2 = 1.732051
Point to line distance¶
The distance between any point and a line is
For example, using DQ Robotics, this can be calculated as,
# Point coordinates
p = i_+j_
# Build the line
l1 = k_
m1 = cross(i_,k_)
l1_dq = l1 + E_*m1
# Calculate distance
d_p_l1 = norm(cross(p,l1)-m1)
print(f"d_p_l1 = {d_p_l1}")
d_p_l1 = 1
The distance can also be calculated in using a dedicated function inside DQ_Geometry.
from dqrobotics.utils import DQ_Geometry
d_p_l1 = sqrt(DQ_Geometry.point_to_line_squared_distance(p,l1_dq))
print(f"d_p_l1 = {d_p_l1}")
d_p_l1 = 1.0
Note: when controlling robots, it is usually more convenient to use the squared norm instead of the norm.
Point to plane signed distance¶
The (signed) distance between a point and a plane , with respect to the plane, is
Note that the sign of the distance indicates if the point is “above” the plane or “below” the plane.
For example, using DQ Robotics, this can be calculated as,
# Point coordinates
p = k_
# Build the plane
n_pi1 = k_
p_pi1 = DQ([0])
d_pi1 = dot(p_pi1,n_pi1)
pi1 = n_pi1 + E_*d_pi1
# Calculate distance
d_p_pi1 = dot(p,n_pi1)-d_pi1
print(f"d_p_pi1 = {d_p_pi1}")
d_p_pi1 = 1
This distance can also be calculated with
from dqrobotics.utils import DQ_Geometry
d_p_pi1 = DQ_Geometry.point_to_plane_distance(p,pi1)
print(f"d_p_pi1 = {d_p_pi1}")
d_p_pi1 = 1.0
Line to line distance¶
Calculating the distance between two lines, is somewhat more complicated than the ones mentioned above so we will skip the details for now. You can check the following paper for details:
\underline{ Dynamic Active Constraints for Surgical Robots using Vector Field Inequalities. }Marinho, M. M; Adorno, B. V; Harada, K.; and Mitsuishi, M. IEEE Transactions on Robotics (T-RO), 35(5): 1166–1185. October 2019.
For now, it suffices to know that the distance between two lines can be obtained, using DQ Robotics, as follows
from dqrobotics.utils import DQ_Geometry
# Build l1_dq
l1 = k_
p_l1 = DQ([0])
m1 = cross(p_l1,k_)
l1_dq = l1 + E_*m1
# Build l2_dq
l2 = k_
p_l2 = i_
m2 = cross(p_l2,k_)
l2_dq = l2 + E_*m2
# Get the distance
d_l1_l2 = sqrt(DQ_Geometry.line_to_line_squared_distance(l1_dq,l2_dq))
print(f"d_l1_l2 = {d_l1_l2}")
d_l1_l2 = 1.0
Homework¶
## Homework example
# Essential imports
from dqrobotics import *
from dqrobotics.utils import DQ_Geometry
from math import pi, sin, cos
## Solutions
# Question 1
# Question 2
# Question 3
Following the template above to create a script called [dual_quaternion_basics_part2_homework.py], do the following.
- Find the Plücker line representing the y-axis using four different and store them in . Are all Plücker lines the same?
- Define the point and calculate its distance to .
- Find the y-z plane using the two possible plane normals, , and store them in and .
- Calculate the distance between and , and between and . Are the signs different? Why?
- Build a 5mx5mx5m cubic region centered in the origin delineated by 6 planes. Call them , , , , , . Make sure that all normals point towards the origin. Plot this cubic region.
- Among , , , , , , which one is the plane closest to ? What is the distance between and the closest plane?