{"id":28466082,"url":"https://github.com/ifl-camp/tf_bag","last_synced_at":"2025-06-30T20:33:50.428Z","repository":{"id":49047903,"uuid":"103269073","full_name":"IFL-CAMP/tf_bag","owner":"IFL-CAMP","description":"Utilities to transparently use tf data recorded with rosbag in Python scripts","archived":false,"fork":false,"pushed_at":"2024-04-15T08:27:21.000Z","size":162,"stargazers_count":90,"open_issues_count":2,"forks_count":24,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-07T06:08:21.278Z","etag":null,"topics":["python","ros","rosbag","tf"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IFL-CAMP.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-12T12:41:18.000Z","updated_at":"2025-01-09T12:42:52.000Z","dependencies_parsed_at":"2023-01-30T00:46:02.004Z","dependency_job_id":null,"html_url":"https://github.com/IFL-CAMP/tf_bag","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/IFL-CAMP/tf_bag","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IFL-CAMP%2Ftf_bag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IFL-CAMP%2Ftf_bag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IFL-CAMP%2Ftf_bag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IFL-CAMP%2Ftf_bag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IFL-CAMP","download_url":"https://codeload.github.com/IFL-CAMP/tf_bag/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IFL-CAMP%2Ftf_bag/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262625867,"owners_count":23339246,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python","ros","rosbag","tf"],"created_at":"2025-06-07T06:08:26.203Z","updated_at":"2025-06-30T20:33:50.414Z","avatar_url":"https://github.com/IFL-CAMP.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tf_bag\n\n\nUtilities to transparently use tf data recorded with rosbag\n\nQuerying tf for an arbitrary transformation is very comfortable\nat runtime thanks to its tooling (`tf_echo` from the console and\nthe `TransformListener` programmatically). The programs included in the\ntf package implement a background recording of the messages incoming on\nthe `/tf` topic and assemblying them in a Direct Acyclic Graph, which\ncan then be looked up between two arbitrary nodes.\n\nWhile it is possible to include the `/tf` and `/tf_static` topics to the \nones recorded by rosbag, no tool is provided to use this data. So the \nmost common solution is to play the rosbag and let a program poll tf regularly. \nThis is not an ideal solution, especially for scripting.\n\nThis package includes a `BagTfTransformer` which is able to use tf data\nfrom a recorded rosbag by feeding a tf `TransformerROS`.\nIt supports looking up a transform at a given time,\nwaiting for a transform since a specific time, and much more. The API was\nthought to be as similar as possible as the tf classes. The performance\nwas optimized for scripting purposes (e.g. linear scans over time).\n\n## Getting started\n- install ROS, as described in the [official documentation](http://wiki.ros.org/ROS/Installation)\n- install this package into a Catkin workspace\n```bash\n# source the installation workspace (replace \u003cROSDISTRO\u003e with your distro, e.g. noetic)\nsource /opt/ros/\u003cROSDISTRO\u003e/setup.bash\n# create a catkin workspace\nmkdir -p ~/ros/catkin_ws/src\n# check out this package\ncd ~/ros/catkin_ws/src\ngit clone https://github.com/IFL-CAMP/tf_bag.git\n# install the dependencies and compile\ncd ~/ros/catkin_ws\nrosdep install -ryi --from-paths . --ignore-src\ncatkin_make # (or catkin build)\n```\n- profit!\n```bash\n# source the workspace, to make the packages available to your shell\nsource ~/ros/catkin_ws/devel/setup.bash\nrospython\n\u003e\u003e\u003e import tf_bag\n```\n\n## Common tasks\n\n#### Recording data into a bag file\n```bash\n# save to a custom location, compress on the fly\nrosbag record -O PATH_TO_MY_BAG/data.bag --lz4 /tf /tf_static MY_TOPIC1 MY_TOPIC2 \u003c...\u003e\n```\n\n#### Loading data from a bag file\n```python\nimport rosbag\nfrom tf_bag import BagTfTransformer\n\nbag_file_path = '/path/to/some.bag'\n\nbag = rosbag.Bag(bag_file_path)\n\nbag_transformer = BagTfTransformer(bag)\n```\n\nOr alternatively:\n\n```python\nfrom tf_bag import BagTfTransformer\n\nbag_transformer = BagTfTransformer('/path/to/some.bag')\n```\n\n#### Displaying the transforms included in a bag\n```python\nprint(bag_transformer.getTransformGraphInfo())\n```\n\n#### Looking up a transform\n```python\ntranslation, quaternion = bag_transformer.lookupTransform(frame1_id, frame2_id, time)\n```\n\nThe transformer takes care of \"waiting\" for the transform for up to 0.1\nseconds.\n\n#### Waiting for a transform\n```python\nfirst_transform_time = bag_transformer.waitForTransform(frame1_id, frame2_id, start_time)\n```\n\nThe start_time parameter can be omitted: in that case, the transformer will\nstart waiting from the beginning of the bag data.\n\n#### Processing a transform\n\nIn order to process a transform, it is necessary to specify the times at\nwhich it should be sampled. If the two frames are directly connected, the\ntransform will be sampled at every update (that is, at the timestamp of\nwhich message on the tf topic having the source frame as the header.stamp.frame_id\nattribute and the target frame as the child_frame_id attribute). If the\ntwo frames are not directly connected, an alternate \"trigger\" source or target\nframe (or both) must be specified.\n\n```python\n# the two frames are directly connected in the tf tree\naverage_translation, average_quaternion = bag_transformer.averageTransform(frame1_id, frame2_id)\n\n # the transform will be sampled at every update of the transform between frame1 and frame2\naverage_translation, average_quaternion = bag_transformer.averageTransform(frame3, frame6,\n                                                                           trigger_orig_frame=frame1_id,\n                                                                           trigger_dest_frame=frame2_id)\n```\n\nFor particular needs, a callback can be provided:\n```python\ntranslation_z_over_time = bag_transformer.processTransform(lambda time, transform: transform[0][2], \n                                                           frame1_id, frame2_id, start_time)\n```\n\n#### Visualization\n\nThe translation of a transform can be visualized in a matplotlib graph.\nIf no axis is specified, a 3D plot will be drawn:\n```python\nbag_transformer.plotTranslation(frame1, frame2)\n```\n\nOtherwise, the value of the translation in one axis will be plotted over time:\n```python\nbag_transformer.plotTranslation(frame1, frame2, axis='z')\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fifl-camp%2Ftf_bag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fifl-camp%2Ftf_bag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fifl-camp%2Ftf_bag/lists"}