An academic-grade serialization package implementing forward kinematics solvers, spatial
In modern robotics research pipelines, engineers must be fluent across two distinct programming domains: prototyping complex analytical algorithms from scratch in highly flexible environments (Python/NumPy) and deploying verified system architectures to physical or co-simulated robotic structures interacting with networks (MATLAB/Simulink/ROS).
This repository showcases a parallel implementation engineered to bridge these domains:
- The Python Track (
python_scratch/): Built strictly from first principles using raw numerical arrays via NumPy. It implements foundational algebraic transforms, Shepperd's branch selection to eliminate quaternion coordinate mapping singularities, and active numerical domain saturation guards. - The MATLAB Track (
matlab_toolbox/): Utilizes the optimized Robotics System Toolbox and ROS Toolbox ecosystems. It handles fast architectural compilation, rigid body frame transformations, and dynamic UI slider polling designed to interface directly with hardware networks or broadcast transformation metrics over/tftrees to visualization clients like RViz.
To translate a continuous axis-angle configuration vector (an element of the Lie Algebra
Where
For the inverse mapping (the matrix logarithm), the scalar rotation angle is decoupled from the matrix trace:
-
Machine Epsilon Boundary Protection (
$\theta \to 0$ ): Handled via standard limit approximations to protect stability. -
Antipodal Boundary Singularity (
$\theta \to \pi$ ): As$\sin(\theta) \to 0$ , standard matrix axis extraction triggers a division-by-zero error. The engine resolves this by switching to an alternative mathematical branch extracted from the symmetric component of the manifold$R + I_3 = 2\hat{n}\hat{n}^T$ , selecting the dominant diagonal element to maximize numerical safety. -
Domain Clamping: Truncation errors in floating-point arithmetic can cause a calculated matrix trace to equal
$3.000000000002$ , forcing the domain argument of$\arccos(x)$ out of bounds and returning complex numbers ornanfields. The engine applies an explicit saturation filter:val = np.clip((trace_R - 1.0) / 2.0, -1.0, 1.0).
Linear interpolation (LERP) of spatial orientations cuts through the interior of the unit hypersphere, introducing non-uniform angular velocities. To achieve smooth trajectories, Spherical Linear Interpolation (SLERP) computes path steps along a great-circle arc directly on the
Where
-
Shortest-Path Guard: Quaternions double-cover the 3D rotation space ($SO(3)$), meaning
$q$ and$-q$ represent the exact same physical position. If the dot product$\cos\Omega < 0$ , the engine negates$q_1$ ($q_1 \leftarrow -q_1$ ) to enforce the shortest path, eliminating unintended$270^\circ$ joint whipping. -
Small Angle Approximation: If
$\cos\Omega \ge 0.9995$ , the separation angle is less than$3^\circ$ . To prevent a division-by-zero disaster as$\sin\Omega \to 0$ , the algorithm safely falls back to standard normalized LERP.
Multi-body linkage transformation maps are parameterized sequentially using four parameters: link length
The complete forward kinematics solution mapping the joint vector space configuration to the end-effector pose relative to the fixed ground origin is evaluated via post-multiplied transformation matrix chaining:
To resolve the end-effector position
- Jacobian Velocity MappingThe relationship between joint velocities
$\dot{q}$ and end-effector velocities$v$ is governed by the Analytical Jacobian$J(q)$ :$$v = J(q) \dot{q}$$
The engine constructs the
- Damped Least-Squares (DLS) & Singularity RobustnessStandard pseudo-inverse solvers fail at workspace boundaries where
$J$ becomes singular, causing infinite joint velocity commands. This implementation employs Damped Least-Squares (DLS) to regularize the inversion:
-
Trajectory Tracking via Warm-Starting: For continuous path integration (e.g., circular trajectories), the engine utilizes Warm-Starting. Instead of initializing the solver from a blind guess at every time step, we use the joint configuration
$q_{k-1}$ from the previous frame as the initial seed for frame$q_k$ - Efficiency : This reduces convergence iterations per step to
$O(1)$ in smooth trajectory regions. - Continuity: Ensures smooth, non-oscillatory joint trajectories suitable for real-world automation hardware.
- Efficiency : This reduces convergence iterations per step to
The project codebase is organized into cleanly separated functional modules, keeping custom low-level mathematical structures independent of high-level visualizers and external engineering toolboxes:
Kinematic_Engine_and_Interactive_Visualizer/
|----- core
| |------ kinematics.m
| |------ spatial_math.m
|
|------ Python
| |------ Kinematics
| | |------ __init__.py
| | |------ chain.py
| | |------ transform.py
| | |------ ik_solver.py
| | |------ jacobian.py
| |
| |
| |
| |------ test
| | |------ test1.py
| | |------ test2.py
| | |------ test3.py
| | |------ testp2_1.py
| | |------ testp2_2.py
| | |------ testp2_3.py
| |
| |
| |------ GUI_gif.py
| |------ demo.gif
| |------ visualizer.py
|
|
|------ fk_toolbox.m
|------ interactive_visualizer.m
|------ slerp_toolbox.m
|------ transform_toolbox.m
|------ ur5_parameters.m
|------ dls.m
|------ ik_toolbox.m
|------ jacobian_toolbox.m
