ltcodecs 4.2.1__tar.gz → 4.3.0__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 (65) hide show
  1. ltcodecs-4.3.0/.gitlab-ci.yml +65 -0
  2. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/PKG-INFO +1 -1
  3. ltcodecs-4.3.0/docs/codec_configs.rst +284 -0
  4. ltcodecs-4.3.0/docs/index.rst +26 -0
  5. ltcodecs-4.3.0/docs/quickstart.rst +230 -0
  6. ltcodecs-4.2.1/docs/index.rst → ltcodecs-4.3.0/docs/reference/codec_aliases.rst +25 -17
  7. ltcodecs-4.3.0/docs/reference/codecs.rst +109 -0
  8. ltcodecs-4.3.0/docs/reference/config_schema.rst +152 -0
  9. ltcodecs-4.2.1/docs/ltcodecs.rst → ltcodecs-4.3.0/docs/reference/python_api.rst +24 -5
  10. ltcodecs-4.3.0/docs/requirements.txt +3 -0
  11. ltcodecs-4.3.0/docs/ros_messages.rst +203 -0
  12. ltcodecs-4.3.0/docs/tests.rst +21 -0
  13. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/__init__.py +4 -0
  14. ltcodecs-4.3.0/src/ltcodecs/dict_codec.py +184 -0
  15. ltcodecs-4.3.0/src/ltcodecs/dict_field_codec.py +158 -0
  16. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/exponentialgolomb_integer_codec.py +1 -1
  17. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/fixed_len_array_codec.py +14 -5
  18. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/fixedint_codec.py +19 -10
  19. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/float_codec.py +19 -5
  20. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/ieee_float_codec.py +15 -7
  21. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/linspace_float_codec.py +19 -4
  22. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/optional_field_codec.py +19 -15
  23. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/padding_codec.py +12 -5
  24. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/ros_message_codec.py +55 -7
  25. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/ros_msg_field_codec.py +143 -65
  26. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/string_codecs.py +22 -5
  27. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/variable_len_array_codec.py +21 -9
  28. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/varint_codec.py +21 -5
  29. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs.egg-info/PKG-INFO +1 -1
  30. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs.egg-info/SOURCES.txt +15 -5
  31. ltcodecs-4.3.0/src/ltcodecs.egg-info/scm_file_list.json +55 -0
  32. ltcodecs-4.3.0/src/ltcodecs.egg-info/scm_version.json +8 -0
  33. ltcodecs-4.3.0/tests/dict_codec.yaml +19 -0
  34. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/tests/test_codecs.py +75 -9
  35. ltcodecs-4.3.0/tests/test_dict_codec.py +104 -0
  36. ltcodecs-4.2.1/.gitlab-ci.yml +0 -197
  37. ltcodecs-4.2.1/docker/auto-docs.Dockerfile +0 -28
  38. ltcodecs-4.2.1/docker/tests.Dockerfile.ros1 +0 -22
  39. ltcodecs-4.2.1/docker/tests.Dockerfile.ros2 +0 -10
  40. ltcodecs-4.2.1/docs/tests.rst +0 -21
  41. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/.gitignore +0 -0
  42. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/.gitlab/merge_request_templates/Default.md +0 -0
  43. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/CONTRIBUTING.md +0 -0
  44. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/LICENSE +0 -0
  45. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/README.md +0 -0
  46. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/docs/Makefile +0 -0
  47. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/docs/conf.py +0 -0
  48. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/pyproject.toml +0 -0
  49. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/requirements.txt +0 -0
  50. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/setup.cfg +0 -0
  51. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/bool_codec.py +0 -0
  52. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/bytes_codec.py +0 -0
  53. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/ccl_latlon_bcd_codec.py +0 -0
  54. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/ccl_latlon_codec.py +0 -0
  55. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/exceptions.py +0 -0
  56. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/field_codec.py +0 -0
  57. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/lzma_codec.py +0 -0
  58. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/multiple_field_codec.py +0 -0
  59. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/rostime_codec.py +0 -0
  60. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs/string_enum_codec.py +0 -0
  61. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs.egg-info/dependency_links.txt +0 -0
  62. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs.egg-info/requires.txt +0 -0
  63. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/src/ltcodecs.egg-info/top_level.txt +0 -0
  64. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/tests/__init__.py +0 -0
  65. {ltcodecs-4.2.1 → ltcodecs-4.3.0}/tests/string_msg_codec.yaml +0 -0
@@ -0,0 +1,65 @@
1
+ include:
2
+ - project: acomms/ci_templates
3
+ ref: v2.3.2
4
+ file:
5
+ - /templates/python-docs.yml
6
+ - /templates/python-tests.yml
7
+
8
+ workflow:
9
+ rules:
10
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
11
+ when: always
12
+ - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"'
13
+ when: never
14
+ - if: '$CI_COMMIT_BRANCH || $CI_COMMIT_TAG'
15
+ when: always
16
+
17
+ stages:
18
+ - prepare
19
+ - test
20
+ - deploy
21
+
22
+ variables:
23
+ PYTHON_DOCS_PDF_ARTIFACT: "ltcodecs.pdf"
24
+ PYTHON_DOCS_PDF_SOURCE: "docs/_build/latex/ltcodecs.pdf"
25
+
26
+ ROS_ACOMMS_REF: "devel"
27
+
28
+ PYTHON_PYTEST_ARGS: "-vv -rA --capture=tee-sys"
29
+ PYTHON_PYTEST_COVERAGE_ARGS: "--cov=ltcodecs"
30
+ PYTHON_PYTEST_TARGET: "tests/"
31
+
32
+ native_tests:
33
+ extends: .armw_native_pytest_template
34
+ variables:
35
+ NATIVE_TEST_SETUP_COMMANDS: |
36
+ pip install .
37
+
38
+ trigger-ros_acomms-pipeline:
39
+ stage: test
40
+ trigger:
41
+ project: acomms/ros_acomms
42
+ branch: $ROS_ACOMMS_REF
43
+ strategy: depend
44
+ variables:
45
+ LTCODEC_REF: $CI_COMMIT_SHA
46
+ PYACOMMS_REF: $PYACOMMS_REF
47
+ ARMW_REF: $ARMW_REF
48
+ ROS_SKIP_WORKSPACE_BUILD_IN_PIPELINES: "false"
49
+ ROS_SKIP_WORKSPACE_BUILD_ON_DEV_AUTODOCS: "false"
50
+ rules:
51
+ - if: '$CI_PIPELINE_SOURCE != "pipeline"'
52
+
53
+ pypi:
54
+ image: python:3.12
55
+ stage: deploy
56
+ script:
57
+ - pip install -r requirements.txt
58
+ - pip install build twine
59
+ - python -m build
60
+ - twine upload --username __token__ --password $PYPI_TOKEN dist/*
61
+ artifacts:
62
+ paths:
63
+ - dist/
64
+ only:
65
+ - tags
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ltcodecs
3
- Version: 4.2.1
3
+ Version: 4.3.0
4
4
  Summary: LT Codecs: Lightweight codecs for use over low-throughput links
5
5
  Author: Woods Hole Oceanographic Institution, Acoustic Communications Group
6
6
  License: LGPL-3.0-or-later
@@ -0,0 +1,284 @@
1
+ Codec Configurations
2
+ ====================
3
+
4
+ Most ``ltcodecs`` applications are configured with a field dictionary. In
5
+ Python this is a nested ``dict``. In files it is usually written as YAML.
6
+ Each top-level key is a field name, and each value is a mapping of parameters
7
+ for the codec that encodes that field.
8
+
9
+ Basic Shape
10
+ -----------
11
+
12
+ Every field needs a ``codec`` value. The value is one of the aliases listed in
13
+ :doc:`reference/codec_aliases`.
14
+
15
+ .. code-block:: yaml
16
+
17
+ field_name:
18
+ codec: string
19
+ max_length: 16
20
+
21
+ The remaining keys are passed to that field codec's constructor. For example,
22
+ ``max_length`` belongs to the string codec in the example above.
23
+
24
+ Scalar Fields
25
+ -------------
26
+
27
+ Use scalar codecs for values that encode as a single value in the message.
28
+
29
+ .. code-block:: yaml
30
+
31
+ name:
32
+ codec: string
33
+ max_length: 10
34
+ count:
35
+ codec: integer
36
+ min_value: 0
37
+ max_value: 100
38
+ enabled:
39
+ codec: bool
40
+ temperature:
41
+ codec: float
42
+ min_value: -5.0
43
+ max_value: 35.0
44
+ precision: 1
45
+ depth:
46
+ codec: linspace_float
47
+ min_value: 0.0
48
+ max_value: 100.0
49
+ resolution: 0.5
50
+
51
+ Common scalar aliases include ``string``, ``integer``, ``bool``, ``float``,
52
+ ``uint8``, ``uint16``, ``uint32``, ``int8``, ``int16``, ``float32``, and
53
+ ``float64``. Use ``float`` when a fixed number of decimal places is the
54
+ natural constraint, and ``linspace_float`` when a physical step size or number
55
+ of values is the natural constraint.
56
+
57
+ Nested Dictionaries
58
+ -------------------
59
+
60
+ Use ``dict`` when a field contains another mapping of named fields.
61
+
62
+ .. code-block:: yaml
63
+
64
+ vehicle:
65
+ codec: dict
66
+ fields:
67
+ id:
68
+ codec: uint8
69
+ name:
70
+ codec: string
71
+ max_length: 12
72
+
73
+ The input value for ``vehicle`` is a nested dictionary:
74
+
75
+ .. code-block:: python
76
+
77
+ {
78
+ "vehicle": {
79
+ "id": 7,
80
+ "name": "remus",
81
+ },
82
+ }
83
+
84
+ Nested ROS Messages
85
+ -------------------
86
+
87
+ Use ``msg`` when a field contains a nested ROS message.
88
+
89
+ .. code-block:: yaml
90
+
91
+ position:
92
+ codec: msg
93
+ ros_type: geometry_msgs/Point
94
+ fields:
95
+ x:
96
+ codec: float32
97
+ y:
98
+ codec: float32
99
+ z:
100
+ codec: float32
101
+
102
+ ``ros_type`` may use ROS 1 style names such as ``geometry_msgs/Point`` or ROS
103
+ 2 introspection names such as ``geometry_msgs/msg/Point``. ``ltcodecs``
104
+ normalizes ROS 2 names internally.
105
+
106
+ Variable-Length Arrays
107
+ ----------------------
108
+
109
+ Use ``variable_len_array`` for a list whose encoded length is included in the
110
+ bit stream.
111
+
112
+ .. code-block:: yaml
113
+
114
+ samples:
115
+ codec: variable_len_array
116
+ max_length: 10
117
+ element_type: uint8
118
+
119
+ ``max_length`` is required. Values longer than ``max_length`` are currently
120
+ truncated during encoding.
121
+
122
+ For element codecs that need parameters, put those parameters under
123
+ ``element_params``:
124
+
125
+ .. code-block:: yaml
126
+
127
+ labels:
128
+ codec: variable_len_array
129
+ max_length: 4
130
+ element_type: string
131
+ element_params:
132
+ max_length: 12
133
+
134
+ Set ``nullable: true`` when an empty list should encode as a single bit. When
135
+ ``nullable`` is false, the array length is always encoded.
136
+
137
+ .. code-block:: yaml
138
+
139
+ optional_samples:
140
+ codec: variable_len_array
141
+ max_length: 10
142
+ nullable: true
143
+ element_type: uint8
144
+
145
+ Fixed-Length Arrays
146
+ -------------------
147
+
148
+ Use ``fixed_len_array`` when the number of elements is known from the config.
149
+
150
+ .. code-block:: yaml
151
+
152
+ rgb:
153
+ codec: fixed_len_array
154
+ length: 3
155
+ element_type: uint8
156
+
157
+ The encoded stream does not include a length field. The decoder always reads
158
+ ``length`` elements.
159
+
160
+ Arrays of Messages
161
+ ------------------
162
+
163
+ Array elements can be nested dictionaries or ROS messages. Use
164
+ ``element_type: msg`` for ROS message elements and pass the message parameters
165
+ with ``element_params``.
166
+
167
+ .. code-block:: yaml
168
+
169
+ points:
170
+ codec: variable_len_array
171
+ max_length: 5
172
+ element_type: msg
173
+ element_params:
174
+ ros_type: geometry_msgs/Point
175
+ fields:
176
+ x:
177
+ codec: float32
178
+ y:
179
+ codec: float32
180
+ z:
181
+ codec: float32
182
+
183
+ Optional Fields
184
+ ---------------
185
+
186
+ Use ``optional`` when a boolean field controls whether additional fields are
187
+ present. The controlling field itself encodes as one bit. If it is true, each
188
+ field in ``target_fields`` is encoded immediately after it. If false, the
189
+ target fields use no bits.
190
+
191
+ .. code-block:: yaml
192
+
193
+ has_extra:
194
+ codec: optional
195
+ target_fields:
196
+ extra:
197
+ codec: uint8
198
+
199
+ The input dictionary or ROS message must contain both ``has_extra`` and
200
+ ``extra`` when ``has_extra`` is true.
201
+
202
+ Padding
203
+ -------
204
+
205
+ Use ``pad`` or ``padding`` to reserve a fixed number of zero bits.
206
+
207
+ .. code-block:: yaml
208
+
209
+ reserved:
210
+ codec: padding
211
+ num_bits: 8
212
+
213
+ Padding decodes to ``None``.
214
+
215
+ Metadata Fields
216
+ ---------------
217
+
218
+ Some codec aliases represent metadata rather than payload bits. These fields
219
+ are copied to or from packet metadata and are not encoded like ordinary fields.
220
+
221
+ This functionality is used by ``ros_acomms``, so the currently implemented metadata fields
222
+ are all related to encoding or decoding acoustic packet data.
223
+
224
+ Available metadata decoder aliases include ``src``, ``dest``,
225
+ ``dest_decoder``, ``toa``, and ``snr_in``. The metadata encoder alias
226
+ currently used by top-level codecs is ``dest``.
227
+
228
+ .. code-block:: yaml
229
+
230
+ dest:
231
+ codec: dest
232
+ data:
233
+ codec: string
234
+ max_length: 20
235
+
236
+ When encoding, the top-level codec returns the metadata dictionary as the
237
+ second value from ``encode()``.
238
+
239
+ Checksums
240
+ ---------
241
+
242
+ Checksums are configured on the top-level codec object, not inside each field.
243
+ Both :py:class:`ltcodecs.dict_codec.DictCodec` and
244
+ :py:class:`ltcodecs.ros_message_codec.RosMessageCodec` support ``crc8`` and
245
+ ``crc32``.
246
+
247
+ .. code-block:: python
248
+
249
+ codec = ltcodecs.DictCodec.from_codec_file(
250
+ "message_codec.yaml",
251
+ checksum="crc32",
252
+ )
253
+
254
+ The checksum is appended after the encoded payload. During decoding, a
255
+ mismatch raises ``ValueError``.
256
+
257
+ Complete Example
258
+ ----------------
259
+
260
+ .. code-block:: yaml
261
+
262
+ name:
263
+ codec: string
264
+ max_length: 10
265
+ count:
266
+ codec: integer
267
+ min_value: 0
268
+ max_value: 100
269
+ enabled:
270
+ codec: bool
271
+ nested:
272
+ codec: dict
273
+ fields:
274
+ value:
275
+ codec: uint8
276
+ has_extra:
277
+ codec: optional
278
+ target_fields:
279
+ extra:
280
+ codec: uint8
281
+
282
+ This config can be loaded with
283
+ :py:meth:`ltcodecs.dict_codec.DictCodec.from_codec_file` and used to encode a
284
+ dictionary with the same field names.
@@ -0,0 +1,26 @@
1
+ ltcodecs
2
+ ========
3
+
4
+ ``ltcodecs`` encodes Python dictionaries and ROS messages into compact
5
+ bitstreams using declarative codec configurations.
6
+
7
+ Start with :doc:`quickstart` if you are writing your first codec config. Use
8
+ :doc:`codec_configs` and :doc:`ros_messages` for the full user guide.
9
+
10
+ .. toctree::
11
+ :maxdepth: 2
12
+ :caption: User Guide
13
+
14
+ quickstart
15
+ codec_configs
16
+ ros_messages
17
+
18
+ .. toctree::
19
+ :maxdepth: 2
20
+ :caption: Reference
21
+
22
+ reference/codecs
23
+ reference/codec_aliases
24
+ reference/config_schema
25
+ reference/python_api
26
+ tests
@@ -0,0 +1,230 @@
1
+ Quick Start
2
+ ===========
3
+
4
+ ``ltcodecs`` encodes structured Python dictionaries and ROS messages into
5
+ compact bit streams. A codec is configured with a field dictionary: each field
6
+ name maps to a codec alias and the parameters for that field codec.
7
+
8
+ Install
9
+ -------
10
+
11
+ Install the package from PyPI:
12
+
13
+ .. code-block:: console
14
+
15
+ pip install ltcodecs
16
+
17
+ For local development, install the checkout in editable mode:
18
+
19
+ .. code-block:: console
20
+
21
+ pip install -e .
22
+
23
+ Encode a Dictionary
24
+ -------------------
25
+
26
+ The quickest way to use ``ltcodecs`` is with
27
+ :py:class:`ltcodecs.dict_codec.DictCodec`. This path does not require ROS.
28
+
29
+ .. code-block:: python
30
+
31
+ from bitstring import ConstBitStream
32
+ import ltcodecs
33
+
34
+ fields = {
35
+ "name": {
36
+ "codec": "string",
37
+ "max_length": 10,
38
+ },
39
+ "count": {
40
+ "codec": "integer",
41
+ "min_value": 0,
42
+ "max_value": 100,
43
+ },
44
+ "enabled": {
45
+ "codec": "bool",
46
+ },
47
+ }
48
+
49
+ message = {
50
+ "name": "test",
51
+ "count": 21,
52
+ "enabled": True,
53
+ }
54
+
55
+ codec = ltcodecs.DictCodec(fields)
56
+ bits, metadata = codec.encode(message)
57
+
58
+ decoded = codec.decode(ConstBitStream(bits))
59
+ assert decoded == message
60
+
61
+ The ``bits`` value is a ``bitstring.Bits`` object. The ``metadata`` return
62
+ value is usually ``None`` unless the field configuration includes one of the
63
+ metadata encoder aliases.
64
+
65
+ Encode Metadata
66
+ ---------------
67
+
68
+ ``encode()`` for the Message/Dictionary codecs returns a tuple of ``(bits, metadata)``.
69
+ The first value is the encoded bit stream.
70
+ The second value is a small metadata dictionary for values
71
+ that should travel outside the compressed payload, such as packet routing
72
+ fields. Most codecs return ``None`` for metadata, and you can ignore it.
73
+ It is possible to define fields that
74
+ use metadata encoders rather than (or in addition to) adding bits to the output stream.
75
+
76
+ Use YAML Configuration
77
+ ----------------------
78
+
79
+ Codec configurations are commonly stored as YAML. The same dictionary codec
80
+ above can be written as:
81
+
82
+ .. code-block:: yaml
83
+
84
+ name:
85
+ codec: string
86
+ max_length: 10
87
+ count:
88
+ codec: integer
89
+ min_value: 0
90
+ max_value: 100
91
+ enabled:
92
+ codec: bool
93
+
94
+ Load the YAML file with
95
+ :py:meth:`ltcodecs.dict_codec.DictCodec.from_codec_file`:
96
+
97
+ .. code-block:: python
98
+
99
+ from bitstring import ConstBitStream
100
+ import ltcodecs
101
+
102
+ codec = ltcodecs.DictCodec.from_codec_file("message_codec.yaml")
103
+
104
+ bits, _metadata = codec.encode({
105
+ "name": "test",
106
+ "count": 21,
107
+ "enabled": True,
108
+ })
109
+
110
+ decoded = codec.decode(ConstBitStream(bits))
111
+
112
+ Nested Dictionaries and Optional Fields
113
+ ---------------------------------------
114
+
115
+ A field can itself be a dictionary. Use the ``dict`` codec and provide a
116
+ nested ``fields`` mapping:
117
+
118
+ .. code-block:: yaml
119
+
120
+ nested:
121
+ codec: dict
122
+ fields:
123
+ value:
124
+ codec: uint8
125
+
126
+ Optional fields are controlled by a boolean field. If the controlling value is
127
+ true, the target fields are encoded. If false, those fields use no bits.
128
+
129
+ .. code-block:: yaml
130
+
131
+ has_extra:
132
+ codec: optional
133
+ target_fields:
134
+ extra:
135
+ codec: uint8
136
+
137
+ The input dictionary for that configuration would include both the controlling
138
+ field and the target field:
139
+
140
+ .. code-block:: python
141
+
142
+ message = {
143
+ "has_extra": True,
144
+ "extra": 42,
145
+ }
146
+
147
+ Encode a ROS Message
148
+ --------------------
149
+
150
+ Use :py:class:`ltcodecs.ros_message_codec.RosMessageCodec` for ROS messages.
151
+ If no field dictionary is provided, ``ltcodecs`` asks ARMW for the message
152
+ fields and chooses codecs from the ROS field types.
153
+
154
+ .. code-block:: python
155
+
156
+ from bitstring import ConstBitStream
157
+ import armw
158
+ import ltcodecs
159
+
160
+ String = armw.import_message("std_msgs", "String")
161
+
162
+ msg = String()
163
+ msg.data = "hello"
164
+
165
+ codec = ltcodecs.RosMessageCodec("std_msgs/String")
166
+ bits, metadata = codec.encode(msg)
167
+
168
+ decoded = codec.decode(ConstBitStream(bits))
169
+ assert decoded.data == "hello"
170
+
171
+ You can also provide a YAML field configuration for a ROS message:
172
+
173
+ .. code-block:: yaml
174
+
175
+ data:
176
+ codec: string
177
+ max_length: 10
178
+
179
+ .. code-block:: python
180
+
181
+ codec = ltcodecs.RosMessageCodec.from_codec_file(
182
+ "std_msgs/String",
183
+ "string_msg_codec.yaml",
184
+ )
185
+
186
+ ROS 1 and ROS 2 Type Names
187
+ --------------------------
188
+
189
+ ROS message fields may use ROS 1 style type names such as ``pkg/Msg`` and
190
+ ``pkg/Msg[]`` or ROS 2 introspection names such as ``pkg/msg/Msg`` and
191
+ ``sequence<pkg/msg/Msg>``. ``ltcodecs`` normalizes these forms when it infers
192
+ fields from a ROS message or when an explicit field config contains a ROS type.
193
+
194
+ For arrays, use the array codecs directly when writing explicit configs:
195
+
196
+ .. code-block:: yaml
197
+
198
+ samples:
199
+ codec: variable_len_array
200
+ max_length: 10
201
+ element_type: uint8
202
+
203
+ points:
204
+ codec: fixed_len_array
205
+ length: 3
206
+ element_type: msg
207
+ element_params:
208
+ ros_type: geometry_msgs/Point
209
+
210
+ Checksums
211
+ ---------
212
+
213
+ Top-level dictionary and ROS message codecs can append a checksum. Supported
214
+ values are ``crc8`` and ``crc32``.
215
+
216
+ .. code-block:: python
217
+
218
+ codec = ltcodecs.DictCodec(fields, checksum="crc8")
219
+ bits, _metadata = codec.encode(message)
220
+ decoded = codec.decode(ConstBitStream(bits))
221
+
222
+ If the received checksum does not match the encoded content, ``decode`` raises
223
+ ``ValueError``.
224
+
225
+ Next Steps
226
+ ----------
227
+
228
+ See :doc:`reference/codecs` for the codec reference,
229
+ :doc:`reference/codec_aliases` for the full alias table, and
230
+ :doc:`reference/python_api` for the generated API reference.
@@ -1,13 +1,9 @@
1
- .. ltcodecs documentation master file, created by
2
- sphinx-quickstart on Tue Jun 6 11:03:07 2023.
3
- You can adapt this file completely to your liking, but it should at least
4
- contain the root `toctree` directive.
1
+ Codec Aliases
2
+ =============
5
3
 
6
- Welcome to ltcodecs's documentation!
7
- ====================================
8
-
9
- There are aliases for each codec that can be used in codec yaml files.
10
- Note that there are multiple aliases for some codec classes.
4
+ Codec configurations use short aliases instead of Python class names. Some
5
+ codec classes have more than one alias for readability or compatibility with
6
+ existing configs.
11
7
 
12
8
  ======================== ====================================================
13
9
  Alias Codec Class
@@ -30,14 +26,17 @@ Alias Codec Class
30
26
  ``float32`` :py:class:`~ltcodecs.ieee_float_codec.IeeeFloat32Codec`
31
27
  ``float64`` :py:class:`~ltcodecs.ieee_float_codec.IeeeFloat64Codec`
32
28
  ``bool`` :py:class:`~ltcodecs.bool_codec.BoolCodec`
29
+ ``boolean`` :py:class:`~ltcodecs.bool_codec.BoolCodec`
33
30
  ``string`` :py:class:`~ltcodecs.string_codecs.AsciiStringCodec`
34
31
  ``ascii`` :py:class:`~ltcodecs.string_codecs.AsciiStringCodec`
35
32
  ``bytes`` :py:class:`~ltcodecs.bytes_codec.BytesCodec`
33
+ ``dict`` :py:class:`~ltcodecs.dict_field_codec.DictFieldCodec`
34
+ ``dictionary`` :py:class:`~ltcodecs.dict_field_codec.DictFieldCodec`
36
35
  ``msg`` :py:class:`~ltcodecs.ros_msg_field_codec.RosMsgFieldCodec`
37
36
  ``ros_msg`` :py:class:`~ltcodecs.ros_msg_field_codec.RosMsgFieldCodec`
38
37
  ``variable_len_array`` :py:class:`~ltcodecs.variable_len_array_codec.VariableLenArrayCodec`
39
38
  ``fixed_len_array`` :py:class:`~ltcodecs.fixed_len_array_codec.FixedLenArrayCodec`
40
- ``ccl_latlon`` :py:class:`~ltcodecs.ccl_latlon_codec.CclLatLonCodec`,
39
+ ``ccl_latlon`` :py:class:`~ltcodecs.ccl_latlon_codec.CclLatLonCodec`
41
40
  ``ccl_latlon_bcd`` :py:class:`~ltcodecs.ccl_latlon_bcd_codec.CclLatLonBcdCodec`
42
41
  ``pad`` :py:class:`~ltcodecs.padding_codec.PaddingCodec`
43
42
  ``padding`` :py:class:`~ltcodecs.padding_codec.PaddingCodec`
@@ -48,13 +47,22 @@ Alias Codec Class
48
47
  ``optional`` :py:class:`~ltcodecs.optional_field_codec.OptionalFieldCodec`
49
48
  ======================== ====================================================
50
49
 
50
+ Metadata Aliases
51
+ ----------------
51
52
 
52
- .. toctree::
53
- :maxdepth: 4
54
- :caption: Contents:
55
-
56
- ltcodecs
57
- tests
58
-
53
+ Metadata decoder aliases read values from packet metadata during decoding.
54
+ They do not consume bits from the payload.
59
55
 
56
+ ================ ========================
57
+ Alias Metadata attribute
58
+ ================ ========================
59
+ ``src`` ``packet.src``
60
+ ``dest`` ``packet.dest``
61
+ ``dest_decoder`` ``packet.dest``
62
+ ``toa`` ``cst.toa``
63
+ ``snr_in`` ``cst.snr_in``
64
+ ================ ========================
60
65
 
66
+ The metadata encoder alias currently supported by top-level codecs is
67
+ ``dest``. During encoding, it copies the configured field into the metadata
68
+ dictionary returned with the encoded bits.