John Collins

John Collins

Developer

© 2024

A Very Basic Transform Libray for Clojure

I wrote a very simple transform library for Clojure(Script). Inspired by the ROS Transform library, it essentially helps you keep track of coordinate transform frames over time. It ends up being very easy to implement such a library in Clojure, as much of the dificulty is already taken care of by the persistent immutable datastructures provided by Clojure. There’s also a SkipList provided as part of an internal implementation structure for core.async channels, which is an ideal datastructure to store transforms in as it enables efficient lookup by time.

It’s easiest to see how it works with a bit of code:

(require '[tf-tree.core :as tf]
         '[tf-tree.utils :as tf-utils]
         '[clojure.core.matrix :as mat])

(def tree (tf/tf-tree))

;; Add a transform at time t=10 from child frame "planar_lidar" to parent frame "base_link".
(tf/put-transform! tree 10 "planar_lidar" "base_link" (mat/identity-matrix 4))
(tf/put-transform! tree 13 "planar_lidar" "base_link" (-> (mat/identity-matrix 4)
                                                          (mat/mmul (tf-utils/translation->matrix [1 2 3]))))

;; Lookup the nearest transform at time t=15 from "planar_lidar" to "base_link".
;; Note, unlike ROS tf, this library won't do any sophisticated bounds checking,
;; nor will it extrapolate with any kind of forward prediction model.
(mat/to-nested-vectors (tf/lookup-transform tree 15 "planar_lidar" "base_link"))
;; [[1 0 0 1] [0 1 0 2] [0 0 1 3] [0 0 0 1]]

(mat/to-nested-vectors (tf/lookup-transform tree 11 "planar_lidar" "base_link"))
;; [[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]

Hopefully this will help a curious clojure developer.