Industrial robots are highly repeatable but not accurate, therefore the accuracy of an industrial robot can be improved through robot calibration. The nominal accuracy of a robot depends on the robot brand and model. With robot calibration you can improve robot accuracy by a factor of 2 to 10.
A measurement system is required to calibrate a robot. RoboDK can be used to calibrate the robots as well as to generate accurate robot programs (this includes filtering the programs and using RoboDK’s offline programming engine). RoboDK can also be used to test the accuracy of the robot before and after calibration through ballbar testing or robot milling.
Robot calibration can remarkably improve the accuracy of robots programmed offline, also known as Off-Line Programming (OLP). A calibrated robot has a higher absolute as well as relative positioning accuracy than an uncalibrated one.
The following items are required to install RoboDK and properly perform robot calibration:
1.One or more industrial robot arms
2.A measurement system: any laser tracker such as Leica, API or Faro and or optical CMM such as the C-Track stereocamera from Creaform should work
3.RoboDK software must be installed and an appropriate license for robot calibration testing is required. For network licenses, an internet connection is required to check the license. To install or update RoboDK for robot calibration:
a.Download RoboDK from the download section
b.Set up the driver for the measurement system (not required for Creaform Optical CMM).
Unzip and copy the appropriate folder:
API Laser tracker: https://robodk.com/downloads/private/API.zip (OTII and Radian trackers)
Faro Laser Tracker: https://robodk.com/downloads/private/Faro.zip (all Faro Trackers)
Leica Laser Tracker: https://robodk.com/downloads/private/Leica.zip (all Leica Trackers)
to the folder: C:/RoboDK/api/
It is recommended to create a virtual environment of the robot setup in RoboDK (offline setup) before starting to take measurements. This section explains how to prepare the RoboDK station offline. This can be done before having the robot and the tracker, only using a computer with RoboDK installed.
RoboDK calibration setup examples can be downloaded from the following folder:
Skip this section if you already have an offline cell. The reference frames and tool frames can be estimated approximately. A sample station is shown in the following picture.
A RoboDK station is where the virtual environment station and calibration information is stored. The station is saved as an RDK file. Follow the next steps to create a robot station for robot calibration from scratch (video preview: https://youtu.be/Nkb9uDamFb4):
1.Select the robot:
a.Select File➔Open online library. The online library will show up in RoboDK.
b.Use the filters to find your robot by brand, payload, ...
c.Select Download and the robot should automatically appear in the station.
d.Alternatively, download the robot files (.robot file extension) separately from http://www.robodk.com/library and open them with RoboDK.
2.Model the virtual station
a.Add reference frames by selecting Program➔Add Reference Frame.
i. One “Measurements reference” frame must be added with respect to the robot base frame.
ii. One “Tracker reference” must be added with respect to the “Measurements reference” that we just added.
iii. One additional “Tool reference” can be added with respect to the “Measurements reference” frame to visualize the position of the tool seen by the tracker.
Tip 1: Drag and drop items in the tree to reconstruct the dependency that exists in the real world. For example, the tracker reference must be placed with respect to the “Measurements Reference”.
Tip 2: you can approximately move any reference frames or tool frames by holding the ALT key and SHIFT+ALT key respectively. Alternatively, you can double click the reference frame and input the right coordinates.
Tip 3: Rename any object using the F2 key on the item tree.
b.Add the tool object (STL, IGES and STEP files are supported formats) and drag and drop it to the robot (inside the item tree), this will convert the object into a tool. More information available here.
Optional: Select Program➔Add empty tool to add any TCP’s that we want to visualize in the station (to check for collisions or other). To set an approximate value of the TCP:
i. Double click the new tool.
ii. Set an approximate TCP value. You can copy/paste the 6 values at once using the two buttons at the right.
iii. It is recommended to rename the TCPs used for calibration with the name “CalibTool id”, where id is the calibration target number.
c.Add other 3D CAD files (STL, IGES, STEP, SLD, ...) to model the virtual station using the menu File➔Open… Alternatively, drag and drop files to RoboDK’s main window.
Tip 1: Import the 3D files of the measurement workspace and name it Workspace so that the robot measurements are generated inside the workspace of the tracker. Alternatively, set the workspace invisible if we do not want to constrain the measurements inside the tracker workspace. More information is available in the next section.
Tip 2: It is possible to select CTRL+ALT+Shift+P to block exporting confidential 3D files that have been imported in RoboDK.
3.Add the calibration module in the station:
a.Select the menu Utilities➔Calibrate Robot.
b.Select Stereo camera.
Then, the following window will appear.
This window can be closed for now. We can open it anytime by double clicking the Robot calibration station item.
4.Save the station.
a.Select File➔Save station.
b.Provide a folder and a file name.
c.Select save. A new RDK file will be generated (RoboDK station file).
We can recover the station modifications anytime by opening the RDK file (double click the file on Windows).
Summarizing, it is important to double check the following points:
1.The reference frame “Measurements reference” is directly attached to the robot base reference frame.
For now, we can use an estimate of this reference frame (approximate value).
2.The Tracker reference is directly attached to the Measurements reference. The tracker reference must be an estimated position of the tracker measurement device with respect to the measurements reference.
3.The “Robot calibration” project is present in the station and all the measurements that we are planning to take are free of collision and visible by the tracker (double click the calibration settings and select show for each group of the four group of measurements).
4.If we want to automatically check for collisions we must use the name tag “collision” in every object that we want to use to check collisions. It is recommended to use a tool around 25% bigger than the calibrated tool to safely avoid collisions.
There are four sets of measurements that are required to successfully accomplish robot calibration:
1.Base setup: six measurements (or more) moving axis 1 and 2 are required to place the calibration reference with respect to the robot. Select Show in the calibration settings window and the robot will move along the sequence.
2.Tool setup: seven or more measurements are required to calibrate the tool flange and the tool targets (moving axis 5 and 6). Select Show and the robot will move along the sequence.
3.Calibration measurements: 60 measurements or more are required to calibrate the robot. These measurements can be randomly placed in the robot workspace and free of collision with the surrounding objects.
4.Validation measurements (optional): as many measurements as desired can be used to validate the robot accuracy. These measurements are used only to validate the accuracy of the robot and not to calibrate the robot.
The first two sets of measurements are automatically generated by RoboDK. Select Show and the robot will follow the sequence (as shown in the following images). If the sequence needs to be changed, select Measure and export the calibration measurements as a CSV file by selecting Export data. This file can be edited using an Excel sheet and re-imported by clicking Import data.
The last two sets of measurements (calibration and validation) can be generated using the macro script called “ Create measurements. This macro script is automatically added to the station when we start the robot calibration project. Double click the macro to execute it. This macro is a Python program that guides the user to define the following settings:
● Number of measurements: The number of measurements to generate. By default, 80 measurements are used because a minimum of 60 measurements is required for robot calibration.
● Reference position: The reference position must be a position of the robot where the tool is facing the tracker with visible targets.
o Joint limits: The lower and upper joint limits must be provided.
o Cartesian limits: We can provide Cartesian limits (X,Y,Z values) with respect to the robot reference frame.
The script automatically generates measurements where the tool is facing the tracker as well as respecting the joint and Cartesian constrains. A rotation of +/-180 deg around the tool is permitted around the direction that faces the tracker at the reference position. Furthermore, the sequence of joint movements is free of collision and inside the measurement workspace (if the workspace is set to be visible). The following image shows the summary that is presented to the user before the automatic sequence starts. It may take up to 5 minutes for the sequence to finish.
A new message will pop up once the algorithm finishes. Select Calibration to use the 60 measurements for robot calibration. We can re-execute the same script to generate another set of measurements for validation. This step is optional but 60 measurements ore more are recommended for validation purposes.
If desired, we can modify the script by right clicking the Create measurements script and selecting Edit script, then, modify additional parameters of the algorithm. The script automatically saves the user input as station parameters. We can view, edit or delete these settings by right clicking the station and selecting Station parameters, as shown in the next image.
Finally, it is also possible to import configurations that have been selected manually by selecting Import data (inside the Measure menu). We can import a CSV or a TXT file as an Nx6 matrix, where N is the number of configurations.
Two objects are required: a tool object (held by the robot) and a base reference object (static in the cell). The tracker must be able to see the tool object and the base reference object for each measurement. These objects are also known as “models” (in VXelements) and they are defined by a set of targets attached to the tool and reference frame objects. The tracker tracks the position of these targets providing the reference frame of these objects as a measurement with respect to the tracker. RoboDK takes each measurement as the position of the tool with respect to the base reference frame, so the tracker can be moved without altering the measurements.
It is required to attach a group of targets to the tool and the reference frame respectively to allow tracking these objects properly. The following images show some examples of appropriate setups:
The following subsections must be sequentially accomplished to be ready to start taking measurements. Finally, it will be required to connect the tracker and the robot to the computer to automate the procedure of taking measurements.
First, two models are required: one model of the tool and one model representing the reference frame. One model is one object defined as a list of points (X,Y,Z coordinates) corresponding to the targets with respect to the model reference (tool or base reference frame).
We must follow these steps twice to define the tool and base models:
1.Connect to VXElements by selecting Connect➔Connect Creaform’s C-Track Optical CMM.
2.Select Connect and wait until the connection is Ready.
Make sure to calibrate the tracker and the HandyProbe if it is required by VXElements. Also make sure to have the VXTrack and VXModel software options provided by Creaform.
3.Select Base reference in RoboDK. VXelements will open and will display visible positioning targets. You should select the static points. Make sure to select all points that represent the static reference. You should not include points that can move.
4.Select Tool reference in RoboDK and repeat this operation by selecting the points that represent the tool model.
To properly move the reference frame of the object we must use the HandyProbe and bring these features in the virtual VXelements session. The model being used must be defined as the positioning model so that the features are probed with respect to this model. It is possible to probe points, lines, planes, cylinders, cones and define reference frames with respect to these features.
The IP of the tracker is needed to properly set the communication in RoboDK. Make sure that VXelements is not running and follow these steps to verify the communication with the tracker:
a.Select the menu “Connect➔Connect Stereocamera”. A new window should open.
b.Enter the “Base model” and the “Tool model”, as text files (generated in the previous section). These are the position of the targets that define the reference frame and the tool frame respectively.
c.Select the “Connect” button.
d.When the connection succeeds, we must provide the Base and Tool models as text files (.txt).
You will see that an integrated version of VXelements starts and, after a few seconds, you should see a green message showing “Ready” if the connection is successful. The VXelements windows can be closed and the connection will remain active. If the connection does not succeed we must make sure that no VXelements processes are running behind the scenes in the Windows Task bar or the Task manager (select CTRL+ALT+DEL to force stop the “VXelementsApiImplementation” process), then, select Connect in RoboDK to try again.
The IP of the robot (or the COM port number for RS232 connections) is needed to properly set the communication with RoboDK. Follow these steps to verify the communication with the robot:
1.Select Connect➔Connect robot. A new window will appear.
2.Set the IP and port of the robot (or the COM port if the connection is through RS232).
3.Click the Connect button.
4.Refer to the appendix if any problems arise.
If the connection is successful you should see a green message displaying Ready. The position of the virtual robot should exactly match the position of the real robot if we select Get current joints. Alternatively, select Move to current joints to move the robot to the current position set in the simulator. The window can be closed and the connection will remain active.
Robot calibration is divided in 4 steps. Each step requires taking a set of measurements. These four steps must be followed in order:
1.Base reference measurements (3 minutes).
2.Tool reference measurements (3 minutes)
3.Calibration measurements (7 minutes, 60 measurements)
4.Validation measurements (7 minutes, 60 measurements).
The following video shows how perform this calibration in 20 minutes: https://youtu.be/Htpx-p7tmYs. The validation measurements (step 4) are not mandatory to calibrate the robot, however they provide an objective point of view of the accuracy results. It is also possible to see the impact of calibrating the robot in one area and validating it in a different area.
Select the button Measure for each of the four sets of measurements. This will open a new window that allows taking new measurements as well as import and export existing measurements in a text file (csv or txt format).
These measurements can be performed anywhere in the tool flange if we measure the same target for all the 6 measurements. To start the measurements, select Measure in the Base setup section. The following window will open. Then, select Start Measure and the robot will move sequentially through the scheduled measurements.
Close the window when the measurements are completed and the Measurements reference frame will be updated with respect to the robot base frame. If we did not select any reference frame, we can add a reference (select Program➔Add Reference Frame) and place it under the robot base reference (Drag & Drop in the item tree).
The summary will show the position and orientation or the robot reference frame with respect to the calibration reference frame ([x,y,z,w,p,r] format, in mm and radians)
Once this step is completed we can accurately display the workspace of the tracker with respect to the robot in RoboDK in real time.
Like the previous section: select Measure in the Tool setup section. The following window will open. Select Start Measure and the robot will move sequentially through the planned measurements. Double click a measurement to continue measuring from that position.
The summary will show the calibrated TCP (position and orientation) when the procedure is completed. The definition of the TCP (in the following image “Spindle”) will be updated automatically. If we did not select any TCP, we can add a new one (select “Program➔Add empty Tool”) and select “Recalculate”.
Select Measure in the Calibration section. The following window will open. Then, select Start Measure and the robot will move sequentially through the planned measurements. Double click a measurement to continue measuring from that position.
Close the window when the measurements are completed. The robot will be calibrated automatically and it will display the following message if there are no issues.
Finally, the green screen will display some statistics regarding the calibration measurements and how much the accuracy is improved for those measurements.
We shouldn’t validate the accuracy of the robot using the same measurements that we used to calibrate the robot, therefore, it is recommended to take additional measurements to validate the accuracy (having a more objective point of view of the accuracy results).
The same calibration procedure must be followed to take the validation measurements. The summary will display the validation statistics. See the following Results Section for more information.
Once the calibration is completed we can analyze the accuracy improvement by reading the statistics provided by RoboDK. To display these statistics, open the robot calibration window (double click the icon Robot Calibration). The summary window in the validation section will display the errors before calibration (nominal kinematics) and after calibration (calibrated kinematics). Two tables are provided, one shows statistics concerning position errors and the other one shows distance errors:
● Position errors: The position error is the accuracy that the robot can attain one point with respect to a reference frame.
● Distance errors: The distance error is obtained by measuring the distance error of pairs of points. The distance between two points seen by the robot (obtained using the calibrated kinematics) is compared with the distance seen by the measurement system (physically measured). All combinations are taken into account. If we took 315 measurements we will have 315x315/2= 49455 distance error values.
The statistics provided are the mean error, the standard deviation (std) and the maximum error. It is also provided the mean plus three times the standard deviation, which corresponds to the expected error for 99.98% of all the measurements (if we take into account that errors follow a normal distribution).
Select Show stats and two histograms will show the distribution of the errors before and after calibration, one histogram for position accuracy and the other showing distance accuracy. The following images correspond to the 315 validation measurements used in this example.
Finally, we can select “Make report” and a PDF report with the information presented in this section will be generated.
Once the robot has been calibrated, we have two options to generate programs using the absolute accuracy of the calibrated robot:
● Filter existing programs: all the robot targets inside a program are modified to improve the accuracy of the robot. It can be done manually or using the API.
● Use RoboDK for Offline Programming to generate accurate programs (generated programs are already filtered, including programs generated using the API).
To filter an existing program manually: drag & drop the robot program file into RoboDK’s main screen (or select File➔Open) and select Filter only. The program will be filtered and saved in the same folder. The filter summary will mention if there were any problems using the filtering algorithm. We also have the option to import a program if we want to simulate it inside RoboDK. If the program has any dependencies (tool frame or base frame definitions, subprograms, ...) they must be located in the same directory where the first program is imported.
Once we import the program inside RoboDK we can regenerate it with or without absolute accuracy. In the main accuracy settings of RoboDK (Tools➔Options➔Accuracy) we can decide if we want to always generate the programs using accurate kinematics, if we want to ask every time or if we want to use the current robot kinematics. The current robot kinematics can be changed by right clicking the robot and activating/deactivating the “Use accurate kinematics” tag. If it is active we will see a green dot, if it is not active, we will see a red dot.
It is possible to filter a complete program using RoboDK given a calibrated robot and the robot program using the FilterProgram call:
A macro example called FilterProgram is available in the Macros section of the library. The following code is an example Python script that uses the RoboDK API to filter a program.
from robolink import * # API to communicate with RoboDK
from robodk import * # basic matrix operations
import os # Path operations
# Get the current working directory
CWD = os.path.dirname(os.path.realpath(__file__))
# Start RoboDK if it is not running and link to the API
RDK = Robolink()
# optional: provide the following arguments to run behind the scenes
#RDK = Robolink(args='/NOSPLASH /NOSHOW /HIDDEN')
# Get the calibrated station (.rdk file) or robot file (.robot):
# Tip: after calibration, right click a robot and select "Save as .robot"
calibration_file = CWD + '/KUKA-KR6.rdk'
# Get the program file:
file_program = CWD + '/Prog1.src'
# Load the RDK file or the robot file:
calib_item = RDK.AddFile(calibration_file)
if not calib_item.Valid():
raise Exception("Something went wrong loading " + calibration_file)
# Retrieve the robot (no popup if there is only one robot):
robot = RDK.ItemUserPick('Select a robot to filter', ITEM_TYPE_ROBOT)
if not robot.Valid():
raise Exception("Robot not selected or not available")
# Activate accuracy
# Filter program: this will automatically save a program copy
# with a renamed file depending on the robot brand
status, summary = robot.FilterProgram(file_program)
if status == 0:
print("Program filtering succeeded")
print("Program filtering failed! Error code: %i" % status)
The following code is an example Python script that uses the RoboDK API to filter a target (pose target or joint target), using the FilterTarget command:
pose_filt, joints = robot.FilterTarget(nominal_pose, estimated_joints)
This example is useful if a 3rd party application (other than RoboDK) generates the robot program using pose targets.
from robolink import * # API to communicate with RoboDK
from robodk import * # basic matrix operations
return KUKA_2_Pose(xyzwpr) # Convert X,Y,Z,A,B,C to a pose
return Pose_2_KUKA(pose) # Convert a pose to X,Y,Z,A,B,C
# Start the RoboDK API and retrieve the robot:
RDK = Robolink()
robot = RDK.Item('', ITEM_TYPE_ROBOT)
if not robot.Valid():
raise Exception("Robot not available")
pose_tcp = XYZWPR_2_Pose([0, 0, 200, 0, 0, 0]) # Define the TCP
pose_ref = XYZWPR_2_Pose([400, 0, 0, 0, 0, 0]) # Define the Ref Frame
# Update the robot TCP and reference frame
# Very important for SolveFK and SolveIK (Forward/Inverse kinematics)
robot.setAccuracyActive(False) # Accuracy can be ON or OFF
# Define a nominal target in the joint space:
joints = [0, 0, 90, 0, 90, 0]
# Calculate the nominal robot position for the joint target:
pose_rob = robot.SolveFK(joints) # robot flange wrt the robot base
# Calculate pose_target: the TCP with respect to the reference frame
pose_target = invH(pose_ref)*pose_rob*pose_tcp
print('Target not filtered:')
joints_approx = joints # joints_approx must be within 20 deg
pose_target_filt, real_joints = robot.FilterTarget(pose_target, joints)
Once the robot has been calibrated, we usually need RoboDK to filter programs, therefore, a RoboDK license is required (a basic OLP license is enough for generating accurate robot programs once the robot has been calibrated). Filtering a program means that the targets in a program are altered/optimized to improve the accuracy of the robot, taking into account all the calibration parameters (about 30 parameters).
Alternatively, we can calibrate only the joint offsets plus the base and tool reference frames (4 joint offset parameters plus 6 parameters for the base frame plus 6 parameters for the tool frame). The calibration will not be as accurate as if we used the default complete calibration but it might allow entering certain parameters in the robot controller and not depend on RoboDK to generate robot programs.
To obtain the calibration only for the joint offsets we must select the Calib. Param. button, then the Mastering button (inside the robot calibration menu).
A new window will appear after we select Make mastering program. In this window we can select what axes we want to consider creating the new home position.
The button Make mastering program will appear in the robot calibration window. Select this button to generate a program that will bring the robot to the new home position. Transfer it to the robot and execute it, then, the new home position must be recorded.
If the robot and the PC are connected, we can right click the program and select Send Program to Robot to automatically send the program to the robot. Otherwise, we can select Generate robot program to see new joint values for the home position.
RoboDK provides some utilities to calibrate reference frames and tool frames. These tools can be accessed from Utilities➔Calibrate Reference frame and Utilities➔Calibrate Tool frame respectively.
To calibrate a reference frame or a tool frame (also known as User frame and TCP respectively) we need some robot configurations touching 3 or more points, these robot configurations can either be joint values or Cartesian coordinates (with orientation data in some cases). It is recommended to use the joint values instead of the Cartesian coordinates as it is easier to check the real robot configuration in RoboDK (by copy-pasting the robot joints to the RoboDK main screen).
Select Utilities➔Calibrate tool to calibrate the TCP using RoboDK. We can use as many points as desired, using different orientations. More points and larger orientation changes is better as we will get a better estimate of the TCP as well as a good estimate of the TCP error.
The following two options are available to calibrate a TCP:
● By touching one stationary point with the TCP with different orientations.
● By touching a plane with the TCP (like a touch probe).
It is recommended to calibrate by touching a plane reference if we have to calibrate a touch probe or a spindle. This method is more stable against user errors.
If the TCP is spherical, the center of the sphere is calculated as the new TCP (it is not necessary to provide the sphere diameter).
The following steps must be followed to calibrate the TCP with a plane (as seen in the picture):
1.Select the tool that needs to be calibrated.
2.Select the calibration method➔”Calib XYZ by plane”.
3.Select calibrate using “joints”.
4.Select the robot that is being used.
5.Select the number of configurations that we will use for TCP calibration (it is recommended to take 8 configurations or more).
6.Select an estimate of the reference plane. If the reference plane is not parallel to the robot XY plane (from the robot reference) we must add an estimate of this reference plane within ±20 degrees. The position of this plane is not important, only the orientation.
7.We can start filling the table of joint values. We can fill it manually or by doing copy/paste with the buttons (as shown in the image). We can also use the button “Get Jx” to get the current joint values from the robot in the simulator. If we are getting the joints from a real robot connected to the robot we must first select “Get current joints” from the robot connection menu (see image attached or the appendix for more information about connecting a robot with RoboDK). It is strongly recommended to keep a separate copy of the joints used for calibration (such as a text file, for example).
8.Once the table is filled we will see the new TCP values (X,Y,Z) as the “Calibrated TCP”, towards the end of the window. We can select “Update” and the new TCP will be updated in the RoboDK station. The orientation of the probe cannot be found using this method.
9.We can select “Show errors” and we will see the error of every configuration with respect to the calculated TCP (which is the average of all the configurations). We can delete one configuration if it has a larger error than the others.
10. We must manually update the values in the real robot controller (X,Y,Z only). If this TCP will be used in a program generated by RoboDK, it is not necessary to update the values in the robot controller.
Select Utilities➔Calibrate reference to calibrate a reference frame. It is possible to set a reference frame using different methods. In the example of the figure, a reference frame is defined by three points: point 1 and 2 define the X axis direction and point 3 defines the positive Y axis.
We must pay special attention if we want to recover the mastering/home values for axes 1 and 6. These values are directly related to the robot base frame for the axis 1 and a TCP reference for axis 6. Therefore, external measurements must be taken to properly set these values. This window appears after we select “Make mastering program” in the calibration menu.
The next two procedures must be followed to properly set the mastering parameters for these two axes.
We must use a reference target to properly set the “home” position of axis 6. The angle offset will be the rotation around the Z axis of the tool flange needed to best fit the measured TCP (X,Y,Z) with the known TCP reference. The measured TCP (see the following image) is one of the TCPs that were measured in the step two of the calibration procedure. The reference TCP is a known reference that corresponds to one of the TCP for the calibration tool being used.
Ideally, the reference TCP must be measured by the CMM with respect to the tool flange (a replica of the robot tool flange would be best). Alternatively, we can use a new robot to measure (step two of the calibration procedure) the TCP for the first time and use one measured TCP as the reference. It is important to use a dowel pin and/or appropriate tool flange referencing to make sure that the end effector is always placed at the same position.
We must properly measure three base targets before starting a robot calibration if we want to align the axis 1 with the real robot base frame. These base targets must be chosen so that the reference frame can be found with respect to the robot.
The “home” position of axis 1 directly depends on the three base targets as well as the robot base setup. The robot base setup is the first calibration step, where the base frame of the measurement system is placed with respect to the robot base frame by moving and measuring axis 1 and 2.
The base targets of the measurement system can be set by pressing “Set base targets” (see following image). These are 3 measurements that will define the desired robot reference frame (the first 2 measurements define the X axis and the third point the positive Y axis). We should use appropriate reference points related to the robot base so that this procedure is repeatable.
The correction angle for joint 1 will be the angle between the X axis of the base reference measured through 3 points and the base reference measured by moving the robot axes 1 and 2. Of course, both vectors are previously projected to the XY plane of the base reference obtained by touching the tree points.