transform-tree 0.0.5__tar.gz → 0.0.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. transform_tree-0.0.7/Cargo.toml +123 -0
  2. {transform_tree-0.0.5/crates/tf_tree_core → transform_tree-0.0.7}/NOTICE +2 -1
  3. transform_tree-0.0.7/PKG-INFO +169 -0
  4. transform_tree-0.0.7/README.md +148 -0
  5. transform_tree-0.0.7/crates/tf_tree/Cargo.toml +74 -0
  6. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/NOTICE +2 -1
  7. transform_tree-0.0.7/crates/tf_tree/README.md +104 -0
  8. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/examples/control_loop.rs +17 -100
  9. transform_tree-0.0.7/crates/tf_tree/examples/gen_domain_fixture.rs +94 -0
  10. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/examples/two_processes.rs +13 -80
  11. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/src/bin/rendezvous_child.rs +83 -138
  12. transform_tree-0.0.7/crates/tf_tree/src/cache.rs +581 -0
  13. transform_tree-0.0.7/crates/tf_tree/src/cbor.rs +151 -0
  14. transform_tree-0.0.7/crates/tf_tree/src/frozen.rs +211 -0
  15. transform_tree-0.0.7/crates/tf_tree/src/lib.rs +204 -0
  16. transform_tree-0.0.7/crates/tf_tree/src/open.rs +1053 -0
  17. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/src/tree.rs +102 -1827
  18. transform_tree-0.0.7/crates/tf_tree/src/unstable.rs +52 -0
  19. transform_tree-0.0.7/crates/tf_tree/tests/await_frames.rs +134 -0
  20. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/tests/batch.rs +30 -196
  21. transform_tree-0.0.7/crates/tf_tree/tests/batch_phases.rs +845 -0
  22. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/tests/behavior.rs +31 -159
  23. transform_tree-0.0.7/crates/tf_tree/tests/clock_offset.rs +308 -0
  24. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/tests/common/mod.rs +9 -19
  25. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/tests/construction.rs +17 -66
  26. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/tests/counters.rs +49 -110
  27. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/tests/derivatives.rs +48 -228
  28. transform_tree-0.0.7/crates/tf_tree/tests/enumeration.rs +112 -0
  29. transform_tree-0.0.7/crates/tf_tree/tests/error_payloads.rs +206 -0
  30. transform_tree-0.0.7/crates/tf_tree/tests/feature_gates.rs +119 -0
  31. transform_tree-0.0.7/crates/tf_tree/tests/frozen.rs +516 -0
  32. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/tests/lookup.rs +22 -61
  33. transform_tree-0.0.7/crates/tf_tree/tests/math_reexports.rs +92 -0
  34. transform_tree-0.0.7/crates/tf_tree/tests/owned_writer.rs +240 -0
  35. transform_tree-0.0.7/crates/tf_tree/tests/plan_cache_identity.rs +259 -0
  36. transform_tree-0.0.7/crates/tf_tree/tests/rendezvous.rs +4005 -0
  37. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/tests/tsan.rs +5 -30
  38. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/tests/wide_stamps.rs +10 -56
  39. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_arena/NOTICE +2 -1
  40. transform_tree-0.0.7/crates/tf_tree_arena/README.md +45 -0
  41. transform_tree-0.0.7/crates/tf_tree_arena/src/check.rs +463 -0
  42. transform_tree-0.0.7/crates/tf_tree_arena/src/frozen.rs +939 -0
  43. transform_tree-0.0.7/crates/tf_tree_arena/src/header.rs +253 -0
  44. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_arena/src/heap.rs +41 -137
  45. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_arena/src/layout.rs +108 -145
  46. transform_tree-0.0.7/crates/tf_tree_arena/src/lib.rs +58 -0
  47. transform_tree-0.0.7/crates/tf_tree_arena/src/mapped.rs +603 -0
  48. transform_tree-0.0.7/crates/tf_tree_arena/src/render_test.rs +67 -0
  49. transform_tree-0.0.7/crates/tf_tree_arena/tests/heap_alignment.rs +99 -0
  50. transform_tree-0.0.7/crates/tf_tree_bridge/Cargo.toml +29 -0
  51. transform_tree-0.0.7/crates/tf_tree_bridge/examples/offer_cost.rs +180 -0
  52. transform_tree-0.0.7/crates/tf_tree_bridge/src/authority.rs +347 -0
  53. transform_tree-0.0.7/crates/tf_tree_bridge/src/clock.rs +738 -0
  54. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_bridge/src/config.rs +44 -515
  55. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_bridge/src/discover.rs +25 -178
  56. transform_tree-0.0.7/crates/tf_tree_bridge/src/edgeindex.rs +280 -0
  57. transform_tree-0.0.7/crates/tf_tree_bridge/src/edgemap.rs +34 -0
  58. transform_tree-0.0.7/crates/tf_tree_bridge/src/ingest.rs +2066 -0
  59. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_bridge/src/interner.rs +5 -41
  60. transform_tree-0.0.7/crates/tf_tree_bridge/src/lib.rs +213 -0
  61. transform_tree-0.0.7/crates/tf_tree_bridge/src/names.rs +207 -0
  62. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_bridge/src/statics.rs +150 -135
  63. transform_tree-0.0.7/crates/tf_tree_bridge/src/stats.rs +117 -0
  64. transform_tree-0.0.7/crates/tf_tree_bridge/tests/steady_state_alloc.rs +191 -0
  65. transform_tree-0.0.7/crates/tf_tree_core/Cargo.toml +63 -0
  66. {transform_tree-0.0.5 → transform_tree-0.0.7/crates/tf_tree_core}/NOTICE +2 -1
  67. transform_tree-0.0.7/crates/tf_tree_core/README.md +48 -0
  68. transform_tree-0.0.7/crates/tf_tree_core/src/arena_view.rs +532 -0
  69. transform_tree-0.0.7/crates/tf_tree_core/src/bench_probe.rs +22 -0
  70. transform_tree-0.0.7/crates/tf_tree_core/src/buffer.rs +304 -0
  71. transform_tree-0.0.7/crates/tf_tree_core/src/counters.rs +139 -0
  72. transform_tree-0.0.7/crates/tf_tree_core/src/crash.rs +114 -0
  73. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_core/src/crash_tests.rs +43 -216
  74. transform_tree-0.0.7/crates/tf_tree_core/src/edge.rs +411 -0
  75. transform_tree-0.0.7/crates/tf_tree_core/src/error.rs +453 -0
  76. transform_tree-0.0.7/crates/tf_tree_core/src/frame.rs +439 -0
  77. transform_tree-0.0.7/crates/tf_tree_core/src/layout.rs +286 -0
  78. transform_tree-0.0.7/crates/tf_tree_core/src/lib.rs +108 -0
  79. transform_tree-0.0.7/crates/tf_tree_core/src/loom_tests.rs +1056 -0
  80. transform_tree-0.0.7/crates/tf_tree_core/src/participant.rs +353 -0
  81. transform_tree-0.0.7/crates/tf_tree_core/src/plan.rs +1977 -0
  82. transform_tree-0.0.7/crates/tf_tree_core/src/sample.rs +522 -0
  83. transform_tree-0.0.7/crates/tf_tree_core/src/sync.rs +28 -0
  84. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_core/src/tests.rs +164 -1109
  85. transform_tree-0.0.7/crates/tf_tree_core/src/topology.rs +583 -0
  86. transform_tree-0.0.7/crates/tf_tree_ingest/Cargo.toml +65 -0
  87. transform_tree-0.0.7/crates/tf_tree_ingest/examples/gen_zstd_conformance.rs +124 -0
  88. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ingest/src/cdr.rs +17 -171
  89. transform_tree-0.0.7/crates/tf_tree_ingest/src/decompress.rs +1225 -0
  90. transform_tree-0.0.7/crates/tf_tree_ingest/src/fixture.rs +1292 -0
  91. transform_tree-0.0.7/crates/tf_tree_ingest/src/ingest.rs +1046 -0
  92. transform_tree-0.0.7/crates/tf_tree_ingest/src/lib.rs +315 -0
  93. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ingest/src/report.rs +132 -106
  94. transform_tree-0.0.7/crates/tf_tree_ingest/src/source.rs +622 -0
  95. transform_tree-0.0.7/crates/tf_tree_ingest/src/spill.rs +550 -0
  96. transform_tree-0.0.7/crates/tf_tree_ingest/src/tft.rs +33 -0
  97. transform_tree-0.0.7/crates/tf_tree_ingest/testdata/ATTRIBUTION.md +35 -0
  98. transform_tree-0.0.7/crates/tf_tree_ingest/tests/anomaly_corpus.rs +250 -0
  99. transform_tree-0.0.7/crates/tf_tree_ingest/tests/codec_free.rs +108 -0
  100. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ingest/tests/frozen_bag.rs +7 -29
  101. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ingest/tests/ingest.rs +434 -1006
  102. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ingest/tests/memory.rs +22 -36
  103. transform_tree-0.0.7/crates/tf_tree_ingest/tests/record_ceiling.rs +447 -0
  104. transform_tree-0.0.7/crates/tf_tree_ipc/Cargo.toml +40 -0
  105. transform_tree-0.0.7/crates/tf_tree_ipc/NOTICE +31 -0
  106. transform_tree-0.0.7/crates/tf_tree_ipc/README.md +55 -0
  107. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ipc/src/bin/ipc_child.rs +12 -46
  108. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ipc/src/client.rs +104 -92
  109. transform_tree-0.0.7/crates/tf_tree_ipc/src/error.rs +1047 -0
  110. transform_tree-0.0.7/crates/tf_tree_ipc/src/fork.rs +82 -0
  111. transform_tree-0.0.7/crates/tf_tree_ipc/src/identity.rs +297 -0
  112. transform_tree-0.0.7/crates/tf_tree_ipc/src/lib.rs +92 -0
  113. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ipc/src/lockfile.rs +45 -187
  114. transform_tree-0.0.7/crates/tf_tree_ipc/src/ofd.rs +161 -0
  115. transform_tree-0.0.7/crates/tf_tree_ipc/src/open.rs +697 -0
  116. transform_tree-0.0.7/crates/tf_tree_ipc/src/procstat.rs +281 -0
  117. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ipc/src/rendezvous.rs +12 -36
  118. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ipc/src/runtime_dir.rs +28 -107
  119. transform_tree-0.0.7/crates/tf_tree_ipc/src/server.rs +465 -0
  120. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ipc/src/wire.rs +36 -114
  121. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ipc/tests/multiprocess.rs +46 -199
  122. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_math/Cargo.toml +7 -0
  123. transform_tree-0.0.7/crates/tf_tree_math/NOTICE +31 -0
  124. transform_tree-0.0.7/crates/tf_tree_math/README.md +75 -0
  125. transform_tree-0.0.7/crates/tf_tree_math/src/dualquat.rs +388 -0
  126. transform_tree-0.0.7/crates/tf_tree_math/src/helicoid_backend.rs +284 -0
  127. transform_tree-0.0.7/crates/tf_tree_math/src/interp.rs +447 -0
  128. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_math/src/iso3.rs +18 -121
  129. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_math/src/lib.rs +7 -22
  130. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_math/src/quat.rs +71 -49
  131. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_math/src/twist.rs +23 -92
  132. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_math/tests/proptests.rs +16 -59
  133. transform_tree-0.0.7/crates/tf_tree_math/tests/slerp_public.rs +486 -0
  134. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_py/Cargo.lock +29 -8
  135. transform_tree-0.0.7/crates/tf_tree_py/Cargo.toml +68 -0
  136. transform_tree-0.0.7/crates/tf_tree_py/src/errors.rs +919 -0
  137. transform_tree-0.0.7/crates/tf_tree_py/src/ingest.rs +114 -0
  138. transform_tree-0.0.7/crates/tf_tree_py/src/lib.rs +169 -0
  139. transform_tree-0.0.7/crates/tf_tree_py/src/offline.rs +317 -0
  140. transform_tree-0.0.7/crates/tf_tree_py/src/tree.rs +1645 -0
  141. transform_tree-0.0.7/pyproject.toml +65 -0
  142. transform_tree-0.0.7/python/tf_tree/__init__.py +112 -0
  143. transform_tree-0.0.7/python/tf_tree/_core.pyi +664 -0
  144. transform_tree-0.0.5/Cargo.toml +0 -231
  145. transform_tree-0.0.5/PKG-INFO +0 -536
  146. transform_tree-0.0.5/README.md +0 -515
  147. transform_tree-0.0.5/crates/tf_tree/Cargo.toml +0 -303
  148. transform_tree-0.0.5/crates/tf_tree/README.md +0 -188
  149. transform_tree-0.0.5/crates/tf_tree/examples/gen_domain_fixture.rs +0 -131
  150. transform_tree-0.0.5/crates/tf_tree/src/cache.rs +0 -1110
  151. transform_tree-0.0.5/crates/tf_tree/src/cbor.rs +0 -213
  152. transform_tree-0.0.5/crates/tf_tree/src/frozen.rs +0 -326
  153. transform_tree-0.0.5/crates/tf_tree/src/lib.rs +0 -383
  154. transform_tree-0.0.5/crates/tf_tree/src/open.rs +0 -1827
  155. transform_tree-0.0.5/crates/tf_tree/src/unstable.rs +0 -99
  156. transform_tree-0.0.5/crates/tf_tree/tests/await_frames.rs +0 -203
  157. transform_tree-0.0.5/crates/tf_tree/tests/clock_offset.rs +0 -447
  158. transform_tree-0.0.5/crates/tf_tree/tests/enumeration.rs +0 -171
  159. transform_tree-0.0.5/crates/tf_tree/tests/feature_gates.rs +0 -171
  160. transform_tree-0.0.5/crates/tf_tree/tests/frozen.rs +0 -705
  161. transform_tree-0.0.5/crates/tf_tree/tests/math_reexports.rs +0 -138
  162. transform_tree-0.0.5/crates/tf_tree/tests/owned_writer.rs +0 -363
  163. transform_tree-0.0.5/crates/tf_tree/tests/plan_cache_identity.rs +0 -353
  164. transform_tree-0.0.5/crates/tf_tree/tests/rendezvous.rs +0 -5088
  165. transform_tree-0.0.5/crates/tf_tree_arena/README.md +0 -91
  166. transform_tree-0.0.5/crates/tf_tree_arena/src/check.rs +0 -312
  167. transform_tree-0.0.5/crates/tf_tree_arena/src/frozen.rs +0 -1017
  168. transform_tree-0.0.5/crates/tf_tree_arena/src/header.rs +0 -415
  169. transform_tree-0.0.5/crates/tf_tree_arena/src/lib.rs +0 -65
  170. transform_tree-0.0.5/crates/tf_tree_arena/src/mapped.rs +0 -870
  171. transform_tree-0.0.5/crates/tf_tree_arena/tests/heap_alignment.rs +0 -139
  172. transform_tree-0.0.5/crates/tf_tree_bridge/Cargo.toml +0 -68
  173. transform_tree-0.0.5/crates/tf_tree_bridge/examples/offer_cost.rs +0 -268
  174. transform_tree-0.0.5/crates/tf_tree_bridge/src/authority.rs +0 -549
  175. transform_tree-0.0.5/crates/tf_tree_bridge/src/clock.rs +0 -1333
  176. transform_tree-0.0.5/crates/tf_tree_bridge/src/edgeindex.rs +0 -430
  177. transform_tree-0.0.5/crates/tf_tree_bridge/src/edgemap.rs +0 -54
  178. transform_tree-0.0.5/crates/tf_tree_bridge/src/ingest.rs +0 -3407
  179. transform_tree-0.0.5/crates/tf_tree_bridge/src/lib.rs +0 -380
  180. transform_tree-0.0.5/crates/tf_tree_bridge/src/names.rs +0 -306
  181. transform_tree-0.0.5/crates/tf_tree_bridge/src/stats.rs +0 -200
  182. transform_tree-0.0.5/crates/tf_tree_bridge/tests/steady_state_alloc.rs +0 -420
  183. transform_tree-0.0.5/crates/tf_tree_core/Cargo.toml +0 -116
  184. transform_tree-0.0.5/crates/tf_tree_core/README.md +0 -92
  185. transform_tree-0.0.5/crates/tf_tree_core/src/arena_view.rs +0 -782
  186. transform_tree-0.0.5/crates/tf_tree_core/src/bench_probe.rs +0 -57
  187. transform_tree-0.0.5/crates/tf_tree_core/src/buffer.rs +0 -410
  188. transform_tree-0.0.5/crates/tf_tree_core/src/counters.rs +0 -210
  189. transform_tree-0.0.5/crates/tf_tree_core/src/crash.rs +0 -167
  190. transform_tree-0.0.5/crates/tf_tree_core/src/edge.rs +0 -646
  191. transform_tree-0.0.5/crates/tf_tree_core/src/error.rs +0 -602
  192. transform_tree-0.0.5/crates/tf_tree_core/src/frame.rs +0 -658
  193. transform_tree-0.0.5/crates/tf_tree_core/src/layout.rs +0 -390
  194. transform_tree-0.0.5/crates/tf_tree_core/src/lib.rs +0 -238
  195. transform_tree-0.0.5/crates/tf_tree_core/src/loom_tests.rs +0 -1127
  196. transform_tree-0.0.5/crates/tf_tree_core/src/participant.rs +0 -480
  197. transform_tree-0.0.5/crates/tf_tree_core/src/plan.rs +0 -3305
  198. transform_tree-0.0.5/crates/tf_tree_core/src/sample.rs +0 -758
  199. transform_tree-0.0.5/crates/tf_tree_core/src/sync.rs +0 -47
  200. transform_tree-0.0.5/crates/tf_tree_core/src/topology.rs +0 -849
  201. transform_tree-0.0.5/crates/tf_tree_ingest/Cargo.toml +0 -187
  202. transform_tree-0.0.5/crates/tf_tree_ingest/examples/gen_zstd_conformance.rs +0 -196
  203. transform_tree-0.0.5/crates/tf_tree_ingest/src/decompress.rs +0 -2268
  204. transform_tree-0.0.5/crates/tf_tree_ingest/src/fixture.rs +0 -1956
  205. transform_tree-0.0.5/crates/tf_tree_ingest/src/ingest.rs +0 -1410
  206. transform_tree-0.0.5/crates/tf_tree_ingest/src/lib.rs +0 -477
  207. transform_tree-0.0.5/crates/tf_tree_ingest/src/source.rs +0 -826
  208. transform_tree-0.0.5/crates/tf_tree_ingest/src/spill.rs +0 -761
  209. transform_tree-0.0.5/crates/tf_tree_ingest/src/tft.rs +0 -51
  210. transform_tree-0.0.5/crates/tf_tree_ingest/testdata/ATTRIBUTION.md +0 -103
  211. transform_tree-0.0.5/crates/tf_tree_ingest/tests/codec_free.rs +0 -175
  212. transform_tree-0.0.5/crates/tf_tree_ingest/tests/record_ceiling.rs +0 -135
  213. transform_tree-0.0.5/crates/tf_tree_ipc/Cargo.toml +0 -80
  214. transform_tree-0.0.5/crates/tf_tree_ipc/NOTICE +0 -30
  215. transform_tree-0.0.5/crates/tf_tree_ipc/README.md +0 -101
  216. transform_tree-0.0.5/crates/tf_tree_ipc/src/error.rs +0 -652
  217. transform_tree-0.0.5/crates/tf_tree_ipc/src/fork.rs +0 -161
  218. transform_tree-0.0.5/crates/tf_tree_ipc/src/identity.rs +0 -411
  219. transform_tree-0.0.5/crates/tf_tree_ipc/src/lib.rs +0 -133
  220. transform_tree-0.0.5/crates/tf_tree_ipc/src/ofd.rs +0 -233
  221. transform_tree-0.0.5/crates/tf_tree_ipc/src/open.rs +0 -1004
  222. transform_tree-0.0.5/crates/tf_tree_ipc/src/procstat.rs +0 -392
  223. transform_tree-0.0.5/crates/tf_tree_ipc/src/server.rs +0 -678
  224. transform_tree-0.0.5/crates/tf_tree_math/NOTICE +0 -30
  225. transform_tree-0.0.5/crates/tf_tree_math/README.md +0 -142
  226. transform_tree-0.0.5/crates/tf_tree_math/src/dualquat.rs +0 -557
  227. transform_tree-0.0.5/crates/tf_tree_math/src/interp.rs +0 -807
  228. transform_tree-0.0.5/crates/tf_tree_math/tests/slerp_public.rs +0 -654
  229. transform_tree-0.0.5/crates/tf_tree_py/Cargo.toml +0 -152
  230. transform_tree-0.0.5/crates/tf_tree_py/src/errors.rs +0 -1138
  231. transform_tree-0.0.5/crates/tf_tree_py/src/ingest.rs +0 -187
  232. transform_tree-0.0.5/crates/tf_tree_py/src/lib.rs +0 -355
  233. transform_tree-0.0.5/crates/tf_tree_py/src/offline.rs +0 -645
  234. transform_tree-0.0.5/crates/tf_tree_py/src/tree.rs +0 -2711
  235. transform_tree-0.0.5/pyproject.toml +0 -91
  236. transform_tree-0.0.5/python/tf_tree/__init__.py +0 -126
  237. transform_tree-0.0.5/python/tf_tree/_core.pyi +0 -818
  238. {transform_tree-0.0.5 → transform_tree-0.0.7}/LICENSE-APACHE +0 -0
  239. {transform_tree-0.0.5 → transform_tree-0.0.7}/LICENSE-MIT +0 -0
  240. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/LICENSE-APACHE +0 -0
  241. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree/LICENSE-MIT +0 -0
  242. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_arena/Cargo.toml +0 -0
  243. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_arena/LICENSE-APACHE +0 -0
  244. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_arena/LICENSE-MIT +0 -0
  245. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_core/LICENSE-APACHE +0 -0
  246. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_core/LICENSE-MIT +0 -0
  247. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ingest/testdata/zstd_conformance.mcap +0 -0
  248. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ipc/LICENSE-APACHE +0 -0
  249. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_ipc/LICENSE-MIT +0 -0
  250. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_math/LICENSE-APACHE +0 -0
  251. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_math/LICENSE-MIT +0 -0
  252. {transform_tree-0.0.5 → transform_tree-0.0.7}/crates/tf_tree_math/src/reference.rs +0 -0
  253. {transform_tree-0.0.5 → transform_tree-0.0.7}/python/tf_tree/py.typed +0 -0
@@ -0,0 +1,123 @@
1
+ [workspace]
2
+ resolver = "2"
3
+ members = [
4
+ "crates/tf_tree_math",
5
+ "crates/tf_tree_arena",
6
+ "crates/tf_tree_core",
7
+ "crates/tf_tree_ipc",
8
+ "crates/tf_tree",
9
+ "crates/tf_tree_bench",
10
+ "crates/tf_tree_cli",
11
+ "crates/tf_tree_bridge",
12
+ "crates/tf_tree_ingest",
13
+ "crates/tf_tree_c",
14
+ "xtask",
15
+ ]
16
+ # `tf_tree_tf2_sys` (ROS 2) and `tf_tree_py` (libpython) are excluded so
17
+ # `cargo build --workspace` works on every host.
18
+ exclude = [
19
+ "crates/tf_tree_py","crates/tf_tree_tf2_sys"]
20
+
21
+ [workspace.package]
22
+ # 0.0.x: every release may break every other (`SUPPORT.md`).
23
+ version = "0.0.7"
24
+ edition = "2021"
25
+ # 1.87 is forced by `ruzstd 0.9.0` (`tf_tree_ingest`). The `msrv` job reads this
26
+ # field; policy in `SUPPORT.md`.
27
+ rust-version = "1.87"
28
+ # Publishable crates symlink `LICENSE-*` and `NOTICE`; publish from Linux.
29
+ license = "MIT OR Apache-2.0"
30
+ repository = "https://github.com/NoeFontana/tf_tree"
31
+ homepage = "https://github.com/NoeFontana/tf_tree"
32
+ authors = ["Noé Fontana <noe.fontana.pro@gmail.com>"]
33
+ keywords = ["robotics", "tf", "transform", "se3", "ros"]
34
+ categories = ["science::robotics", "no-std"]
35
+
36
+ [workspace.lints.clippy]
37
+ unwrap_used = "deny"
38
+ expect_used = "deny"
39
+ panic = "deny"
40
+ todo = "deny"
41
+ unimplemented = "deny"
42
+ dbg_macro = "deny"
43
+ print_stdout = "warn"
44
+ print_stderr = "warn"
45
+ needless_pass_by_value = "warn"
46
+ redundant_clone = "warn"
47
+ # 0007 rule 3: every `unsafe` block has a `// SAFETY:` comment directly above it.
48
+ # `tf_tree_py` and `tf_tree_tf2_sys` repeat it.
49
+ undocumented_unsafe_blocks = "deny"
50
+
51
+ [workspace.lints.rust]
52
+ missing_docs = "warn"
53
+ unreachable_pub = "warn"
54
+ unused_must_use = "deny"
55
+ # Registers `--cfg loom` so `-D warnings` accepts it.
56
+ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(loom)'] }
57
+
58
+ [workspace.dependencies]
59
+ # Intra-workspace crates.
60
+ tf_tree_math = { path = "crates/tf_tree_math", version = "0.0.7" }
61
+ tf_tree_arena = { path = "crates/tf_tree_arena", version = "0.0.7" }
62
+ # `shm` (`docs/PHASE2.md` §2): `linux_raw` backend, no C build; used only by `tf_tree_ipc`.
63
+ libc = "0.2"
64
+ rustix = { version = "1.1", default-features = false, features = ["mm", "fs", "std"] }
65
+ # `default-features = false` is load-bearing: without it `--no-default-features`
66
+ # downstream still enables `counters` (`docs/PHASE5.md` §5.5).
67
+ tf_tree_core = { path = "crates/tf_tree_core", version = "0.0.7", default-features = false }
68
+ tf_tree_ipc = { path = "crates/tf_tree_ipc", version = "0.0.7" }
69
+ tf_tree = { path = "crates/tf_tree", version = "0.0.7", default-features = false }
70
+ # publish = false crates; `default-features = false` as above.
71
+ tf_tree_bench = { path = "crates/tf_tree_bench", default-features = false }
72
+ tf_tree_bridge = { path = "crates/tf_tree_bridge" }
73
+ # `docs/PHASE5.md` §3. The CLI decides whether the engine counts.
74
+ tf_tree_ingest = { path = "crates/tf_tree_ingest", default-features = false }
75
+ # no_std numeric + POD casting (the entire core dependency budget, plus blake3).
76
+ libm = "0.2"
77
+ bytemuck = { version = "1", features = ["derive"] }
78
+ blake3 = { version = "1", default-features = false }
79
+ # `tf_tree_math`'s optional `helicoid` feature (`docs/decisions/0063`): off by default, so D14's budget holds for everyone who does not opt in.
80
+ helicoid = "=0.0.4"
81
+ helicoid-linalg = "=0.0.4"
82
+ # std-side facade / tooling only.
83
+ thiserror = "2"
84
+ anyhow = "1"
85
+ clap = { version = "4", features = ["derive"] }
86
+ # dev / bench only.
87
+ proptest = "1"
88
+ loom = "0.7"
89
+ criterion = { version = "0.5", features = ["html_reports"] }
90
+ serde_json = "1"
91
+
92
+ [profile.release]
93
+ lto = "thin"
94
+ codegen-units = 1
95
+ debug = "line-tables-only"
96
+ strip = "debuginfo"
97
+
98
+ [profile.dev]
99
+ opt-level = 0
100
+
101
+ [profile.bench]
102
+ lto = "thin"
103
+ codegen-units = 1
104
+
105
+ # Release codegen with debuginfo for profilers.
106
+ [profile.profiling]
107
+ inherits = "release"
108
+ debug = "full"
109
+ strip = "none"
110
+
111
+ # An embedder's `cargo build --release` (`docs/PHASE5.md` §9.2, `docs/API.md` §2.3):
112
+ # every default spelled out; `crates/tf_tree_bench/src/embed.rs` tests these values.
113
+ [profile.embedder]
114
+ inherits = "release"
115
+ opt-level = 3
116
+ lto = false
117
+ codegen-units = 16
118
+ debug = false
119
+ strip = "none"
120
+ debug-assertions = false
121
+ overflow-checks = false
122
+ incremental = false
123
+ panic = "unwind"
@@ -19,7 +19,8 @@ carries no third-party attributions of its own: `tf_tree` vendors no source and
19
19
  statically links no code it did not write. Its Rust dependencies are ordinary
20
20
  crates.io dependencies, each under its own licence, resolved at build time and
21
21
  enumerated in `Cargo.lock`; the set is constrained by `deny.toml` and checked by
22
- `cargo deny check`, which `just lint` runs.
22
+ `cargo deny check` — the recipe `just audit`, run in CI as its own step of the
23
+ job named `lint`.
23
24
 
24
25
  `tf_tree` is not affiliated with, endorsed by, or derived from the Open Source
25
26
  Robotics Foundation, ROS, or the `tf` / `tf2` packages. It is an independent
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.4
2
+ Name: transform_tree
3
+ Version: 0.0.7
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Programming Language :: Python :: 3.10
6
+ Classifier: Programming Language :: Python :: 3.13
7
+ Classifier: Programming Language :: Python :: 3.14
8
+ Classifier: Programming Language :: Rust
9
+ Classifier: Topic :: Scientific/Engineering
10
+ Requires-Dist: numpy>=2.2.6
11
+ License-File: LICENSE-APACHE
12
+ License-File: LICENSE-MIT
13
+ License-File: NOTICE
14
+ Summary: A transform tree engine — faster and more scalable than ROS tf2
15
+ Home-Page: https://github.com/NoeFontana/tf_tree
16
+ Author-email: Noé Fontana <noe.fontana.pro@gmail.com>
17
+ License-Expression: MIT OR Apache-2.0
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
20
+
21
+ # tf_tree
22
+
23
+ [![crates.io](https://img.shields.io/crates/v/tf_tree.svg?logo=rust)](https://crates.io/crates/tf_tree)
24
+ [![docs.rs](https://img.shields.io/docsrs/tf_tree?logo=docsdotrs)](https://docs.rs/tf_tree)
25
+ [![PyPI](https://img.shields.io/pypi/v/transform_tree.svg?logo=pypi&logoColor=white)](https://pypi.org/project/transform_tree/)
26
+ [![CI](https://github.com/NoeFontana/tf_tree/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/NoeFontana/tf_tree/actions/workflows/ci.yml)
27
+ [![Licence](https://img.shields.io/badge/licence-MIT%20OR%20Apache--2.0-blue.svg)](#licence)
28
+
29
+ A transform tree: it stores time-stamped poses between named frames and answers
30
+ "where was frame A relative to frame B at time t?". Use it in a control loop,
31
+ across processes on one host, or in a dataloader with no robot attached.
32
+
33
+ It is faster than ROS `tf2` (below) but is not `tf2`: no ROS dependency and no
34
+ drop-in `tf2_ros::Buffer`, only a one-way `/tf` ingest bridge
35
+ ([`0008`](./docs/decisions/0008-the-name-tf-tree.md)). Linux first: shared memory
36
+ and frozen `.tft` files are Linux-only (`shm` feature); the in-process engine is
37
+ portable.
38
+
39
+ **`0.0.x` promises nothing between releases.** Pin exactly ([`CHANGELOG.md`](./CHANGELOG.md)).
40
+
41
+ ## Install
42
+
43
+ - Rust: `cargo add tf_tree`
44
+ - Python: `pip install transform_tree`, then `import tf_tree`
45
+ - CLI (`tf_tree`, alias `tft`): a binary from the [latest release](https://github.com/NoeFontana/tf_tree/releases/latest), or `cargo install --path crates/tf_tree_cli --features shm`
46
+ - C ABI, C++ header, ROS 2 bridge: `just c-abi-check`, `just cpp-check`, `just ros-build`
47
+
48
+ ## Quickstart
49
+
50
+ Python, from scratch (`just quickstart` runs this). Stamps are integer nanoseconds; a pose is `[qw, qx, qy, qz, x, y, z]`.
51
+
52
+ ```python
53
+ import tf_tree
54
+
55
+ tree = tf_tree.build([("map", "base"), ("base", "cam")])
56
+ tf_tree.push(tree, "base", "map", 1_000, [1, 0, 0, 0, 1.0, 2.0, 3.0])
57
+ tf_tree.push(tree, "base", "map", 2_000, [1, 0, 0, 0, 3.0, 4.0, 5.0])
58
+
59
+ plan = tree.plan("map", "base") # compile the route once, reuse it
60
+ print(plan.at(1_500)[:3, 3]) # -> [2. 3. 4.]
61
+ ```
62
+
63
+ Rust:
64
+
65
+ ```rust
66
+ use tf_tree::{Capacity, EdgeCfg, Iso3, Quat, Stamp, TreeBuilder, Vec3};
67
+
68
+ let tree = TreeBuilder::new()
69
+ .static_edge("base_link", "lidar_top", &Iso3::IDENTITY) // (parent, child)
70
+ .dynamic_edge("odom", "base_link", EdgeCfg::new(Capacity::history(100.0, 10.0)))
71
+ .build()
72
+ .expect("layout");
73
+ let odom = tree.frame("odom").expect("declared");
74
+ let base_link = tree.frame("base_link").expect("declared");
75
+ let lidar_top = tree.frame("lidar_top").expect("declared");
76
+
77
+ let w = tree.claim(base_link, odom).expect("unclaimed"); // (child, parent)
78
+ let at_x = |x| Iso3::new(Quat::IDENTITY, Vec3::new(x, 0.0, 0.0));
79
+ w.push(1_000_000_000, &at_x(0.0)).expect("monotonic");
80
+ w.push(1_010_000_000, &at_x(1.0)).expect("monotonic");
81
+
82
+ let plan = tree.plan(odom, lidar_top).expect("connected");
83
+ let g = tree.guard();
84
+ let t: Stamp = Stamp::from_nanos(1_005_000_000);
85
+ let pose = plan.at(&g, t).expect("in range");
86
+ assert!((pose.t.x - 0.5).abs() < 1e-12);
87
+ ```
88
+
89
+ ## From a recorded bag
90
+
91
+ MCAP only (for `.db3`, run `ros2 bag convert` first):
92
+
93
+ ```sh
94
+ tft doctor --from-bag drive.mcap # what is wrong with this /tf traffic
95
+ tft freeze --from-bag drive.mcap -o drive.tft # index it
96
+ ```
97
+ ```python
98
+ tree = tf_tree.open_file("drive.tft") # an mmap; open per worker, after fork/spawn
99
+ poses = tree.plan("base_link", "lidar_top").at(stamps_ns, layout="quat_twist") # (N, 13)
100
+ ```
101
+
102
+ ## Against `tf2`
103
+
104
+ In-process, one thread, same interpolation, `tf2` called natively; 4-core EPYC-Milan,
105
+ not core-pinned. Both agree to 7e-15 on 50,000 recorded queries.
106
+
107
+ | | `tf_tree` | `tf2` | |
108
+ |---|---|---|---|
109
+ | Lookup, depth 3 | 94 ns | 253 ns | 2.7× |
110
+ | Lookup, depth 15 | 1193 ns | 7337 ns | 6.2× |
111
+ | Publish | 9.4 ns | 114 ns | 12.1× |
112
+
113
+ Without LTO the lookup gap is 1.8×; through the C ABI, 1.5×. Method:
114
+ [`tf2.md`](./docs/benchmarks/tf2.md); sources: [`EVIDENCE.md`](./docs/benchmarks/EVIDENCE.md).
115
+
116
+ ## Not for
117
+
118
+ | Need | Why | See |
119
+ |---|---|---|
120
+ | Drop-in `tf2_ros::Buffer` | gated, not scheduled | [`PHASE7.md`](./docs/PHASE7.md) |
121
+ | Covariance, multi-parent frames, loop closure | cut | [`0009`](./docs/decisions/0009-descoping-phase-6.md) |
122
+ | Transforms across hosts | not started | [`PROJECT.md`](./docs/PROJECT.md) §4 |
123
+ | Shared memory or `.tft` off Linux | not implemented | [`SUPPORT.md`](./SUPPORT.md) |
124
+ | A viewer, point-cloud deskewing | deliberately absent | [`PHASE5.md`](./docs/PHASE5.md) §8 |
125
+
126
+ ## Status
127
+
128
+ | Phase | | Status |
129
+ |---|---|---|
130
+ | 1 | Engine: arena, seqlock buffers, plans, SE(3) math | Implemented |
131
+ | 2 | Shared memory across processes | Implemented, with gaps |
132
+ | 3 | Python bindings | Implemented |
133
+ | 4 | C ABI, C++ wrapper, ROS 2 ingest, derivatives | Implemented, with gaps |
134
+ | 5 | Frozen `.tft`, bag ingestion, diagnostics, `tf_tree top` | Mostly implemented |
135
+ | 6–8 | Continuous time, `tf2` shim, multi-host | Not started |
136
+
137
+ The `§0.0` tables in [`PHASE2`](./docs/PHASE2.md#00-implementation-status),
138
+ [`PHASE4`](./docs/PHASE4.md#00-implementation-status) and
139
+ [`PHASE5`](./docs/PHASE5.md#00-implementation-status) win over this one.
140
+
141
+ ## Shared memory is not a sandbox
142
+
143
+ Processes sharing an arena trust each other: a read-write participant can corrupt
144
+ it ([`PHASE2.md`](./docs/PHASE2.md) §3.10; [`SECURITY.md`](./SECURITY.md)). A
145
+ read-only participant (the default for readers) cannot, and a crashed or hung one
146
+ cannot wedge the others.
147
+
148
+ `fork()` is the sharp edge: a child's inherited handles report `ChildDetached`.
149
+ Python's `multiprocessing` forks by default on Linux, so open the arena inside the
150
+ worker or use `spawn`. A frozen `.tft` survives a fork.
151
+
152
+ ## Layout
153
+
154
+ `crates/`: `tf_tree_math`, `tf_tree_arena`, `tf_tree_core`, `tf_tree` (facade),
155
+ `tf_tree_ipc`, `tf_tree_c`, `tf_tree_bridge`, `tf_tree_ingest`, `tf_tree_py`,
156
+ `tf_tree_bench`, `tf_tree_tf2_sys`, `tf_tree_cli`. `ros/` holds the ROS 2
157
+ packages. `tf_tree_py`, `tf_tree_tf2_sys` and `ros/` sit outside the cargo
158
+ workspace and have their own `just` recipes. Five crates publish: `tf_tree`,
159
+ `tf_tree_core`, `tf_tree_math`, `tf_tree_arena`, `tf_tree_ipc`. MSRV **1.87**.
160
+
161
+ Docs: [`docs/README.md`](./docs/README.md) ·
162
+ [`CONTRIBUTING.md`](./CONTRIBUTING.md) · [`SUPPORT.md`](./SUPPORT.md) ·
163
+ [`SECURITY.md`](./SECURITY.md) · [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md)
164
+
165
+ ## Licence
166
+
167
+ Dual [MIT](./LICENSE-MIT) / [Apache-2.0](./LICENSE-APACHE), at your option. See
168
+ [`NOTICE`](./NOTICE).
169
+
@@ -0,0 +1,148 @@
1
+ # tf_tree
2
+
3
+ [![crates.io](https://img.shields.io/crates/v/tf_tree.svg?logo=rust)](https://crates.io/crates/tf_tree)
4
+ [![docs.rs](https://img.shields.io/docsrs/tf_tree?logo=docsdotrs)](https://docs.rs/tf_tree)
5
+ [![PyPI](https://img.shields.io/pypi/v/transform_tree.svg?logo=pypi&logoColor=white)](https://pypi.org/project/transform_tree/)
6
+ [![CI](https://github.com/NoeFontana/tf_tree/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/NoeFontana/tf_tree/actions/workflows/ci.yml)
7
+ [![Licence](https://img.shields.io/badge/licence-MIT%20OR%20Apache--2.0-blue.svg)](#licence)
8
+
9
+ A transform tree: it stores time-stamped poses between named frames and answers
10
+ "where was frame A relative to frame B at time t?". Use it in a control loop,
11
+ across processes on one host, or in a dataloader with no robot attached.
12
+
13
+ It is faster than ROS `tf2` (below) but is not `tf2`: no ROS dependency and no
14
+ drop-in `tf2_ros::Buffer`, only a one-way `/tf` ingest bridge
15
+ ([`0008`](./docs/decisions/0008-the-name-tf-tree.md)). Linux first: shared memory
16
+ and frozen `.tft` files are Linux-only (`shm` feature); the in-process engine is
17
+ portable.
18
+
19
+ **`0.0.x` promises nothing between releases.** Pin exactly ([`CHANGELOG.md`](./CHANGELOG.md)).
20
+
21
+ ## Install
22
+
23
+ - Rust: `cargo add tf_tree`
24
+ - Python: `pip install transform_tree`, then `import tf_tree`
25
+ - CLI (`tf_tree`, alias `tft`): a binary from the [latest release](https://github.com/NoeFontana/tf_tree/releases/latest), or `cargo install --path crates/tf_tree_cli --features shm`
26
+ - C ABI, C++ header, ROS 2 bridge: `just c-abi-check`, `just cpp-check`, `just ros-build`
27
+
28
+ ## Quickstart
29
+
30
+ Python, from scratch (`just quickstart` runs this). Stamps are integer nanoseconds; a pose is `[qw, qx, qy, qz, x, y, z]`.
31
+
32
+ ```python
33
+ import tf_tree
34
+
35
+ tree = tf_tree.build([("map", "base"), ("base", "cam")])
36
+ tf_tree.push(tree, "base", "map", 1_000, [1, 0, 0, 0, 1.0, 2.0, 3.0])
37
+ tf_tree.push(tree, "base", "map", 2_000, [1, 0, 0, 0, 3.0, 4.0, 5.0])
38
+
39
+ plan = tree.plan("map", "base") # compile the route once, reuse it
40
+ print(plan.at(1_500)[:3, 3]) # -> [2. 3. 4.]
41
+ ```
42
+
43
+ Rust:
44
+
45
+ ```rust
46
+ use tf_tree::{Capacity, EdgeCfg, Iso3, Quat, Stamp, TreeBuilder, Vec3};
47
+
48
+ let tree = TreeBuilder::new()
49
+ .static_edge("base_link", "lidar_top", &Iso3::IDENTITY) // (parent, child)
50
+ .dynamic_edge("odom", "base_link", EdgeCfg::new(Capacity::history(100.0, 10.0)))
51
+ .build()
52
+ .expect("layout");
53
+ let odom = tree.frame("odom").expect("declared");
54
+ let base_link = tree.frame("base_link").expect("declared");
55
+ let lidar_top = tree.frame("lidar_top").expect("declared");
56
+
57
+ let w = tree.claim(base_link, odom).expect("unclaimed"); // (child, parent)
58
+ let at_x = |x| Iso3::new(Quat::IDENTITY, Vec3::new(x, 0.0, 0.0));
59
+ w.push(1_000_000_000, &at_x(0.0)).expect("monotonic");
60
+ w.push(1_010_000_000, &at_x(1.0)).expect("monotonic");
61
+
62
+ let plan = tree.plan(odom, lidar_top).expect("connected");
63
+ let g = tree.guard();
64
+ let t: Stamp = Stamp::from_nanos(1_005_000_000);
65
+ let pose = plan.at(&g, t).expect("in range");
66
+ assert!((pose.t.x - 0.5).abs() < 1e-12);
67
+ ```
68
+
69
+ ## From a recorded bag
70
+
71
+ MCAP only (for `.db3`, run `ros2 bag convert` first):
72
+
73
+ ```sh
74
+ tft doctor --from-bag drive.mcap # what is wrong with this /tf traffic
75
+ tft freeze --from-bag drive.mcap -o drive.tft # index it
76
+ ```
77
+ ```python
78
+ tree = tf_tree.open_file("drive.tft") # an mmap; open per worker, after fork/spawn
79
+ poses = tree.plan("base_link", "lidar_top").at(stamps_ns, layout="quat_twist") # (N, 13)
80
+ ```
81
+
82
+ ## Against `tf2`
83
+
84
+ In-process, one thread, same interpolation, `tf2` called natively; 4-core EPYC-Milan,
85
+ not core-pinned. Both agree to 7e-15 on 50,000 recorded queries.
86
+
87
+ | | `tf_tree` | `tf2` | |
88
+ |---|---|---|---|
89
+ | Lookup, depth 3 | 94 ns | 253 ns | 2.7× |
90
+ | Lookup, depth 15 | 1193 ns | 7337 ns | 6.2× |
91
+ | Publish | 9.4 ns | 114 ns | 12.1× |
92
+
93
+ Without LTO the lookup gap is 1.8×; through the C ABI, 1.5×. Method:
94
+ [`tf2.md`](./docs/benchmarks/tf2.md); sources: [`EVIDENCE.md`](./docs/benchmarks/EVIDENCE.md).
95
+
96
+ ## Not for
97
+
98
+ | Need | Why | See |
99
+ |---|---|---|
100
+ | Drop-in `tf2_ros::Buffer` | gated, not scheduled | [`PHASE7.md`](./docs/PHASE7.md) |
101
+ | Covariance, multi-parent frames, loop closure | cut | [`0009`](./docs/decisions/0009-descoping-phase-6.md) |
102
+ | Transforms across hosts | not started | [`PROJECT.md`](./docs/PROJECT.md) §4 |
103
+ | Shared memory or `.tft` off Linux | not implemented | [`SUPPORT.md`](./SUPPORT.md) |
104
+ | A viewer, point-cloud deskewing | deliberately absent | [`PHASE5.md`](./docs/PHASE5.md) §8 |
105
+
106
+ ## Status
107
+
108
+ | Phase | | Status |
109
+ |---|---|---|
110
+ | 1 | Engine: arena, seqlock buffers, plans, SE(3) math | Implemented |
111
+ | 2 | Shared memory across processes | Implemented, with gaps |
112
+ | 3 | Python bindings | Implemented |
113
+ | 4 | C ABI, C++ wrapper, ROS 2 ingest, derivatives | Implemented, with gaps |
114
+ | 5 | Frozen `.tft`, bag ingestion, diagnostics, `tf_tree top` | Mostly implemented |
115
+ | 6–8 | Continuous time, `tf2` shim, multi-host | Not started |
116
+
117
+ The `§0.0` tables in [`PHASE2`](./docs/PHASE2.md#00-implementation-status),
118
+ [`PHASE4`](./docs/PHASE4.md#00-implementation-status) and
119
+ [`PHASE5`](./docs/PHASE5.md#00-implementation-status) win over this one.
120
+
121
+ ## Shared memory is not a sandbox
122
+
123
+ Processes sharing an arena trust each other: a read-write participant can corrupt
124
+ it ([`PHASE2.md`](./docs/PHASE2.md) §3.10; [`SECURITY.md`](./SECURITY.md)). A
125
+ read-only participant (the default for readers) cannot, and a crashed or hung one
126
+ cannot wedge the others.
127
+
128
+ `fork()` is the sharp edge: a child's inherited handles report `ChildDetached`.
129
+ Python's `multiprocessing` forks by default on Linux, so open the arena inside the
130
+ worker or use `spawn`. A frozen `.tft` survives a fork.
131
+
132
+ ## Layout
133
+
134
+ `crates/`: `tf_tree_math`, `tf_tree_arena`, `tf_tree_core`, `tf_tree` (facade),
135
+ `tf_tree_ipc`, `tf_tree_c`, `tf_tree_bridge`, `tf_tree_ingest`, `tf_tree_py`,
136
+ `tf_tree_bench`, `tf_tree_tf2_sys`, `tf_tree_cli`. `ros/` holds the ROS 2
137
+ packages. `tf_tree_py`, `tf_tree_tf2_sys` and `ros/` sit outside the cargo
138
+ workspace and have their own `just` recipes. Five crates publish: `tf_tree`,
139
+ `tf_tree_core`, `tf_tree_math`, `tf_tree_arena`, `tf_tree_ipc`. MSRV **1.87**.
140
+
141
+ Docs: [`docs/README.md`](./docs/README.md) ·
142
+ [`CONTRIBUTING.md`](./CONTRIBUTING.md) · [`SUPPORT.md`](./SUPPORT.md) ·
143
+ [`SECURITY.md`](./SECURITY.md) · [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md)
144
+
145
+ ## Licence
146
+
147
+ Dual [MIT](./LICENSE-MIT) / [Apache-2.0](./LICENSE-APACHE), at your option. See
148
+ [`NOTICE`](./NOTICE).
@@ -0,0 +1,74 @@
1
+ [package]
2
+ name = "tf_tree"
3
+ description = "std facade for the tf_tree transform engine: ergonomic builder, lookups, and Display errors."
4
+ # Per-crate crates.io front page (see `tf_tree_math`'s manifest).
5
+ readme = "README.md"
6
+ version.workspace = true
7
+ edition.workspace = true
8
+ rust-version.workspace = true
9
+ license.workspace = true
10
+ repository.workspace = true
11
+ homepage.workspace = true
12
+ authors.workspace = true
13
+ keywords.workspace = true
14
+ # Drops the inherited `no-std`: this is the `std` facade.
15
+ categories = ["science::robotics"]
16
+
17
+ [lints]
18
+ workspace = true
19
+
20
+ [package.metadata.docs.rs]
21
+ all-features = true
22
+ rustdoc-args = ["--cfg", "docsrs"]
23
+
24
+ [features]
25
+ default = ["counters"]
26
+ # Passthrough to `tf_tree_core` (`docs/PHASE5.md` §5.5).
27
+ counters = ["tf_tree_core/counters"]
28
+ pure-hash = ["tf_tree_core/pure-hash"]
29
+ # `docs/PHASE2.md` §11.3's fault injection; arms `crate::CRASH_SITES` too.
30
+ crash-points = ["tf_tree_core/crash-points"]
31
+ # `TreeBuilder::build_shared` / `Tree::attach_shared`. Linux-only.
32
+ shm = ["tf_tree_arena/shm", "dep:tf_tree_ipc"]
33
+ # `docs/API.md` §6's Rust mirror of `tf_tree_unstable.h` (`docs/PHASE4.md` §3.1).
34
+ # Enabling is the waiver: nothing behind it is covered by semver.
35
+ #
36
+ # Enabling consumers, checked by `just stable-tier-check` against this comment and
37
+ # `docs/API.md` §6 row 4: `tf_tree_cli`, `tf_tree_c`, `tf_tree_bench`, `tf_tree_py`.
38
+ unstable = []
39
+ # `#[doc(hidden)]` test seams: `CLAIM_WINDOW_HOOK` (`docs/decisions/0005` §5) and
40
+ # `reclamation_verdict_for_test` (`docs/decisions/0028` step 2). Run by `just shm-rendezvous`.
41
+ test-hooks = []
42
+
43
+ [dependencies]
44
+ tf_tree_core.workspace = true
45
+ tf_tree_math.workspace = true
46
+ tf_tree_arena.workspace = true
47
+ thiserror.workspace = true
48
+
49
+ # The rendezvous (`docs/decisions/0005`); gated on `shm` and Linux.
50
+ [target.'cfg(target_os = "linux")'.dependencies]
51
+ tf_tree_ipc = { workspace = true, optional = true }
52
+
53
+ [dev-dependencies]
54
+ # No self dev-dependency: `cargo package` strips it. Tests gate `arena_view` call
55
+ # sites with `#[cfg(feature = "unstable")]` (`tests/feature_gates.rs`).
56
+ tf_tree_ipc = { workspace = true }
57
+ proptest.workspace = true
58
+
59
+ # `tests/rendezvous.rs`'s second process. Published, so the name is prefixed;
60
+ # `cargo install --features shm` writes it to `~/.cargo/bin` (`README.md`). It
61
+ # stays here because `env!("CARGO_BIN_EXE_…")` needs this package's executable.
62
+ [[bin]]
63
+ name = "tf_tree_rendezvous_child"
64
+ path = "src/bin/rendezvous_child.rs"
65
+ required-features = ["shm"]
66
+
67
+ [[test]]
68
+ name = "rendezvous"
69
+ required-features = ["shm"]
70
+
71
+ # `docs/PHASE5.md` §2; Linux-only, behind `shm`.
72
+ [[test]]
73
+ name = "frozen"
74
+ required-features = ["shm"]
@@ -19,7 +19,8 @@ carries no third-party attributions of its own: `tf_tree` vendors no source and
19
19
  statically links no code it did not write. Its Rust dependencies are ordinary
20
20
  crates.io dependencies, each under its own licence, resolved at build time and
21
21
  enumerated in `Cargo.lock`; the set is constrained by `deny.toml` and checked by
22
- `cargo deny check`, which `just lint` runs.
22
+ `cargo deny check` — the recipe `just audit`, run in CI as its own step of the
23
+ job named `lint`.
23
24
 
24
25
  `tf_tree` is not affiliated with, endorsed by, or derived from the Open Source
25
26
  Robotics Foundation, ROS, or the `tf` / `tf2` packages. It is an independent
@@ -0,0 +1,104 @@
1
+ # tf_tree
2
+
3
+ [![crates.io](https://img.shields.io/crates/v/tf_tree.svg?logo=rust)](https://crates.io/crates/tf_tree)
4
+ [![docs.rs](https://img.shields.io/docsrs/tf_tree?logo=docsdotrs)](https://docs.rs/tf_tree)
5
+ [![Licence](https://img.shields.io/badge/licence-MIT%20OR%20Apache--2.0-blue.svg)](#licence)
6
+
7
+ A transform tree engine: store time-stamped rigid-body transforms between named
8
+ coordinate frames and answer *"where was frame A relative to frame B at time
9
+ t?"* — from a control loop, from many processes at once, or offline.
10
+
11
+ **This is the crate to depend on**: the `std` facade over the `no_std` engine
12
+ ([`tf_tree_core`](https://crates.io/crates/tf_tree_core)). **It is not `tf2` and
13
+ not affiliated with ROS**; there is no drop-in `tf2_ros::Buffer` shim.
14
+
15
+ ## Install
16
+
17
+ ```sh
18
+ cargo add tf_tree
19
+ ```
20
+
21
+ Shared arenas, the frozen `.tft` reader and `tf_tree::open()` are behind the
22
+ default-off, **Linux-only** `shm` feature: `cargo add tf_tree --features shm`.
23
+ Python: `pip install transform_tree`.
24
+
25
+ ## In full
26
+
27
+ ```rust
28
+ use tf_tree::{Capacity, EdgeCfg, Iso3, Quat, Stamp, TreeBuilder, Vec3};
29
+
30
+ // Topology is declared up front; nothing allocates after `build()`.
31
+ let tree = TreeBuilder::new()
32
+ .static_edge("base_link", "lidar_top", &Iso3::IDENTITY)
33
+ .dynamic_edge("odom", "base_link", EdgeCfg::new(Capacity::history(100.0, 10.0)))
34
+ .build()
35
+ .expect("layout");
36
+
37
+ let odom = tree.frame("odom").expect("declared");
38
+ let base_link = tree.frame("base_link").expect("declared");
39
+ let lidar_top = tree.frame("lidar_top").expect("declared");
40
+
41
+ // One writer per edge, enforced by the claim table.
42
+ let w = tree.claim(base_link, odom).expect("unclaimed"); // (child, parent)
43
+ let at_x = |x| Iso3::new(Quat::IDENTITY, Vec3::new(x, 0.0, 0.0));
44
+ w.push(1_000_000_000, &at_x(0.0)).expect("monotonic"); // integer nanoseconds
45
+ w.push(1_010_000_000, &at_x(1.0)).expect("monotonic");
46
+
47
+ // Compile the route once, evaluate it many times.
48
+ let plan = tree.plan(odom, lidar_top).expect("connected");
49
+ let g = tree.guard();
50
+
51
+ // The annotation pins the default `SystemDomain`.
52
+ let t: Stamp = Stamp::from_nanos(1_005_000_000);
53
+ match plan.at(&g, t) {
54
+ Ok(pose) => println!("x = {}", pose.t.x), // -> x = 0.5
55
+ Err(e) => println!("{}", tree.describe(e)),
56
+ }
57
+
58
+ let late: Stamp = Stamp::from_nanos(3_000_000_000);
59
+ match plan.at(&g, late) {
60
+ Ok(_) => unreachable!(),
61
+ // -> lookup on odom->base_link (edge#2) would extrapolate:
62
+ // requested 3000000000 ns, history [1000000000, 1010000000] ns
63
+ Err(e) => println!("{}", tree.describe(e)),
64
+ }
65
+ ```
66
+
67
+ **Stamps are integer nanoseconds and carry a domain in the type**; **`plan()` is
68
+ the object you keep** (`lookup()` by name caches one); **errors are `Copy`
69
+ identifiers naming the offending edge**, also `Display` and `std::error::Error`.
70
+
71
+ ## Features
72
+
73
+ | Feature | Default | What it does |
74
+ |---|---|---|
75
+ | `counters` | **on** | Diagnostic counters; off does not fork the layout hash |
76
+ | `shm` | off | `TreeBuilder::build_shared`, `Tree::attach_shared`, `tf_tree::open()`, the frozen `.tft` reader. **Linux only** |
77
+ | `unstable` | off | Arena-shaped introspection (`tf_tree::unstable`, `Tree::arena_view`); **enabling it is the waiver** of semver |
78
+ | `test-hooks` | off | An injection point inside `Tree::claim` for the repository's tests. Not for shipped builds |
79
+
80
+ ## Shared memory is not a sandbox
81
+
82
+ Processes sharing an arena are **mutually trusting, same-user, cooperating
83
+ processes**; a read-write participant can corrupt any part of the arena
84
+ ([`SECURITY.md`](https://github.com/NoeFontana/tf_tree/blob/main/SECURITY.md)).
85
+ `fork()` is the sharp edge: a shared arena is mapped `MADV_DONTFORK`, so a child's
86
+ handles report `ChildDetached`; open inside the worker. A frozen `.tft` is
87
+ inherited intact.
88
+
89
+ ## Version and docs
90
+
91
+ **`0.0.x` promises nothing**: pin exactly
92
+ ([`CHANGELOG.md`](https://github.com/NoeFontana/tf_tree/blob/main/CHANGELOG.md)).
93
+ MSRV is **1.87**
94
+ ([`SUPPORT.md`](https://github.com/NoeFontana/tf_tree/blob/main/SUPPORT.md)).
95
+
96
+ The CLI, C ABI and C++ wrapper, MCAP ingest, ROS 2 bridge and Python bindings are
97
+ built from source; `cargo install tf_tree` installs no command. See the repository
98
+ [`README.md`](https://github.com/NoeFontana/tf_tree/blob/main/README.md),
99
+ [`docs/PROJECT.md`](https://github.com/NoeFontana/tf_tree/blob/main/docs/PROJECT.md)
100
+ and [`docs/API.md`](https://github.com/NoeFontana/tf_tree/blob/main/docs/API.md).
101
+
102
+ ## Licence
103
+
104
+ Dual [MIT](LICENSE-MIT) / [Apache-2.0](LICENSE-APACHE), at your option; see [`NOTICE`](NOTICE).