Tutorial: Interpolated Coordinate System Backend
This tutorial is under construction.
Overview
This advanced tutorial demonstrates how to implement a custom coordsys_backend
that interpolates between two parent coordinate systems in SE(3),
using linear interpolation (lerp) for translations
and spherical linear interpolation (slerp) for orientations.
The Code
#include <cmath>
#include <memory>
#include <print>
import ninbot;
using namespace nin;
using namespace nin::R3;
class coordsys_interp : public coordsys_backend<position_coordsys_traits>
{
public:
using CT = position_coordsys_traits;
coordsys<CT> parent_t_0, parent_t_1;
double t;
coordsys_interp( coordsys<CT> const& A,
coordsys<CT> const& B, double t = 0 )
: parent_t_0{A.linked_copy()}, parent_t_1{B.linked_copy()}, t{t} { }
CT::tf_data_type offset(unsigned hop_limit) const override
{
if (t == 0) return parent_t_0.tf_to_WCS(hop_limit);
if (t == 1) return parent_t_1.tf_to_WCS(hop_limit);
rigid_tf tf_0 = parent_t_0.tf_to_WCS(hop_limit);
rigid_tf tf_1 = parent_t_1.tf_to_WCS(hop_limit);
translation const& tr0 = tf_0.translation;
translation const& tr1 = tf_1.translation;
translation lerped_tr { lerp(tr0.Δx, tr1.Δx, t),
lerp(tr0.Δy, tr1.Δy, t),
lerp(tr0.Δz, tr1.Δz, t) };
orientation_qty ori_0 = tf_0.rotation(orientation_qty{});
orientation_qty ori_1 = tf_1.rotation(orientation_qty{});
orientation_qty slerped_ori = slerp(ori_0, ori_1, t);
rotation slerped_rot = {{}, slerped_ori};
return rigid_tf{lerped_tr, slerped_rot};
}
std::shared_ptr<coordsys_backend<CT>> clone() const override
{
return std::make_shared<coordsys_interp>(parent_t_0, parent_t_1, t);
}
};
int main()
{
position_coordsys_child CS_A {WCS, { { 0_m, 0_m, 0_m}, {} }};
position_coordsys_child CS_B {WCS, { {10_m, 0_m, 0_m}, {} }};
coordsys_generic<coordsys_interp> CS_interp {CS_A, CS_B};
point P = {CS_interp, {0_m, 0_m, 10_cm}};
CS_interp->t = 0.0; std::println("t = 0.0: {}", P.map_to(WCS));
CS_interp->t = 0.5; std::println("t = 0.5: {}", P.map_to(WCS));
CS_interp->t = 0.8; std::println("t = 0.8: {}", P.map_to(WCS));
return 0;
}
Building the code
cmake_minimum_required(VERSION 4.0)
project(interpolated-backend LANGUAGES CXX)
find_package(Ninbot REQUIRED)
add_executable(interpolated-backend interpolated-backend.c++)
target_link_libraries(interpolated-backend PRIVATE ninbot::ninbot)
Applications
This code can be used to integrate into POS the CS of a virtual object composed of two different objects. Then the CS would be the centroid of those two objects: t = M1/(M0+M1)
It can also be used as a switch of parent by fixing t to {0,1}: At t=0 the parent is the first parent_CS, at t=1 the parent is the sencod parent_cs. Then hooking another coordsys, so there is no need to change the parent directly, just switch t. Further optimizations are possible in this case. For example, you can attach a camera and you have simple camera switch method worry-free with just one camera.