├── .devcontainer └── devcontainer.json ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── .vscode ├── extensions.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── clean.sh ├── compile.sh ├── render_dsdl.py ├── render_list_of_void_and_primitive_types.py ├── requirements.txt └── specification ├── .gitignore ├── Cyphal_Specification.tex ├── appendices ├── appendices.tex └── crc.tex ├── application ├── NED_ECEF.eps ├── NED_ECEF.svg ├── aircraft_principal_axes.eps ├── aircraft_principal_axes.svg ├── application.tex ├── conventions.tex ├── functions.tex └── requirements.tex ├── basic └── basic.tex ├── cc-by.eps ├── cyphal_logo.eps ├── cyphal_logo.svg ├── cyphaldoc.cls ├── dsdl ├── architecture.tex ├── attributes.tex ├── compatibility.tex ├── conventions.tex ├── directives.tex ├── dsdl.tex ├── expression_types.tex ├── grammar.parsimonious ├── grammar.tex ├── serializable_types.tex └── serialization.tex ├── introduction └── introduction.tex ├── sdt └── sdt.tex └── transport ├── abstract.tex ├── can └── can.tex ├── cyclic_transfer_id_redundant_transport.pdf ├── serial └── serial.tex ├── transport.tex └── udp └── udp.tex /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LaTeX authoring and publishing environment", 3 | "image": "ghcr.io/opencyphal/texer:te22.4.1", 4 | "customizations": { 5 | "vscode": { 6 | "extensions": [ 7 | "James-Yu.latex-workshop", 8 | "uavcan.dsdl", 9 | "ban.spellright" 10 | ] 11 | } 12 | }, 13 | "forwardPorts": [41491], 14 | "workspaceFolder": "/repo", 15 | "workspaceMount": "source=${localWorkspaceFolder},target=/repo,type=bind,consistency=delegated", 16 | "mounts": [ 17 | "source=profile,target=/root,type=volume", 18 | "target=/root/.vscode-server,type=volume" 19 | ], 20 | "postCreateCommand": "pip3 install pydsdl" 21 | } 22 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # A workflow to create the Cyphal Specification PDF 2 | 3 | name: CI 4 | on: push 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | name: Build PDF file using LaTeX 10 | 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | with: 15 | submodules: recursive 16 | 17 | - name: Run texer container 18 | uses: docker://ghcr.io/opencyphal/texer:te22.4.1 19 | with: 20 | entrypoint: /bin/bash 21 | args: > 22 | -c " 23 | git config --global --add safe.directory '*' && 24 | pip install -U setuptools && 25 | pip install -r requirements.txt && 26 | ./compile.sh 27 | " 28 | 29 | - name: Upload pdf as an artifact 30 | uses: actions/upload-artifact@v4 31 | with: 32 | name: Cyphal Specification 33 | path: specification/Cyphal_Specification.pdf 34 | if-no-files-found: error 35 | 36 | - name: Upload diagnostic snapshot 37 | uses: actions/upload-artifact@v4 38 | if: always() 39 | with: 40 | name: workspace-${{github.job}} 41 | path: '*' 42 | retention-days: 3 43 | 44 | - name: Upload GitHub Pages artifact 45 | uses: actions/upload-pages-artifact@v3 46 | with: 47 | path: specification/ 48 | deploy: 49 | environment: 50 | name: github-pages 51 | needs: build 52 | if: github.ref == 'refs/heads/main' 53 | runs-on: ubuntu-latest 54 | permissions: 55 | pages: write 56 | id-token: write 57 | steps: 58 | - name: Deploy to GitHub Pages 59 | uses: actions/deploy-pages@v4 60 | with: 61 | token: ${{ secrets.GITHUB_TOKEN }} 62 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.tmp 2 | *.cache 3 | .mypy_cache 4 | .DS_Store 5 | .idea -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dsdl"] 2 | path = dsdl 3 | url = https://github.com/UAVCAN/public_regulated_data_types 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "James-Yu.latex-workshop", 6 | "uavcan.dsdl", 7 | "ms-vscode-remote.vscode-remote-extensionpack" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.rulers": [ 3 | 120 4 | ], 5 | "remote.containers.workspaceMountConsistency": "delegated", 6 | "latex-workshop.view.pdf.hand": true, 7 | "latex-workshop.view.autoFocus.enabled": false, 8 | "latex-workshop.latex.autoBuild.run": "never", 9 | "latex-workshop.latex.recipes": [ 10 | { 11 | "name": "pdflatex incremental", 12 | "tools": [ 13 | "pdflatex" 14 | ] 15 | }, 16 | { 17 | "name": "pdflatex full", 18 | "tools": [ 19 | "pdflatex", 20 | "pdflatex", 21 | "pdflatex" 22 | ] 23 | } 24 | ], 25 | "latex-workshop.latex.tools": [ 26 | { 27 | "name": "pdflatex", 28 | "command": "pdflatex", 29 | "args": [ 30 | "-synctex=1", 31 | "-interaction=nonstopmode", 32 | "-file-line-error", 33 | "--halt-on-error", 34 | "--shell-escape", 35 | "%DOC%" 36 | ] 37 | }, 38 | { 39 | "name": "bibtex", 40 | "command": "bibtex", 41 | "args": [ 42 | "%DOCFILE%" 43 | ] 44 | } 45 | ], 46 | "latex-workshop.viewer.pdf.internal.port": 41491, 47 | "spellright.documentTypes": [ ], 48 | "cSpell.words": [ 49 | "aa", 50 | "aaa", 51 | "aaaa", 52 | "abc", 53 | "abcdef", 54 | "ABCDEF", 55 | "ACK", 56 | "ad-hoc", 57 | "ahrs", 58 | "aperiodic", 59 | "API", 60 | "App", 61 | "arg", 62 | "ascii", 63 | "attrib", 64 | "Autoconfigured", 65 | "autodetect", 66 | "AUTOSAR", 67 | "AWG", 68 | "Backus-Naur", 69 | "baremetal", 70 | "baz", 71 | "BAZ", 72 | "BCI", 73 | "BEDA", 74 | "big-endian", 75 | "Bitwise", 76 | "BLS", 77 | "bool", 78 | "boolean", 79 | "booleans", 80 | "bootloader", 81 | "bootloaders", 82 | "bootup", 83 | "broadcasted", 84 | "bytearray", 85 | "bytewise", 86 | "canadensis", 87 | "CANaerospace", 88 | "CANopen", 89 | "Cardinality", 90 | "cassert", 91 | "Castagnoli", 92 | "CCITT", 93 | "cfg", 94 | "CLI", 95 | "cmp", 96 | "com-mu-ni-ca-tion", 97 | "concretizations", 98 | "concretized", 99 | "config", 100 | "const", 101 | "constexpr", 102 | "cout", 103 | "crc", 104 | "CRC", 105 | "creativecommons", 106 | "CRLF", 107 | "CRYOBOX", 108 | "cryopod", 109 | "CSMA", 110 | "cstddef", 111 | "cstdint", 112 | "cyber", 113 | "Cyphal", 114 | "datagram", 115 | "datagrams", 116 | "Datasheet", 117 | "DCD", 118 | "dd", 119 | "de", 120 | "dec", 121 | "Deconflicts", 122 | "deconstructed", 123 | "deduplicated", 124 | "deduplication", 125 | "delayable", 126 | "deserialization", 127 | "deserialize", 128 | "deserialized", 129 | "deserializer", 130 | "detokenize", 131 | "devcontainer", 132 | "DLC", 133 | "downcasting", 134 | "dq", 135 | "driverless", 136 | "Dronecode", 137 | "DSCP", 138 | "DSDL", 139 | "DTH", 140 | "DTID", 141 | "DTMVN", 142 | "duplications", 143 | "ECEF", 144 | "Elementwise", 145 | "EMI", 146 | "endian", 147 | "endl", 148 | "enqueue", 149 | "enum", 150 | "Epilog", 151 | "equ", 152 | "equivalency", 153 | "Erlangen", 154 | "evolvable", 155 | "extensibility", 156 | "extensionpack", 157 | "FFFFU", 158 | "FFFFUL", 159 | "fn", 160 | "foo", 161 | "FOO", 162 | "Forsberg", 163 | "fortytwo", 164 | "functools", 165 | "fw", 166 | "ga", 167 | "geq", 168 | "Gergeleit", 169 | "GH", 170 | "gigajoule", 171 | "github", 172 | "GJ", 173 | "GLONASS", 174 | "GND", 175 | "GNSS", 176 | "golgafrincham", 177 | "Golgafrincham", 178 | "GPGGA", 179 | "GPGSA", 180 | "GPGSV", 181 | "GPRMC", 182 | "GPS", 183 | "grt", 184 | "HCHDG", 185 | "hhmmss", 186 | "HMC", 187 | "homonymous", 188 | "hw", 189 | "hyphal", 190 | "IDE", 191 | "IEC", 192 | "IETF", 193 | "iface", 194 | "IGMP", 195 | "ijk", 196 | "imp-lem-en-ta-ti-on-de-fin-ed", 197 | "Implementers", 198 | "incrementing", 199 | "Inkscape", 200 | "intdd", 201 | "integrators", 202 | "internetwork", 203 | "interoperate", 204 | "Intra", 205 | "intravehicular", 206 | "inv", 207 | "invariance", 208 | "invariants", 209 | "iostream", 210 | "IP", 211 | "ISCSI", 212 | "JST", 213 | "JTAG", 214 | "kbit", 215 | "Kbps", 216 | "Kirienko", 217 | "korovan", 218 | "LAWICEL", 219 | "leq", 220 | "lexerless", 221 | "Libuavcan", 222 | "LIS3MDL", 223 | "Liskov", 224 | "LNA", 225 | "loopback", 226 | "lossy", 227 | "lpt", 228 | "LSB", 229 | "lss", 230 | "lstrip", 231 | "LUT", 232 | "Mainz", 233 | "MAVLink", 234 | "Mbit", 235 | "Mbps", 236 | "MDL", 237 | "memoryview", 238 | "merchantability", 239 | "metadata", 240 | "metaserializable", 241 | "metatype", 242 | "microarchitectures", 243 | "microcontroller", 244 | "microcontrollers", 245 | "milliampere", 246 | "minipage", 247 | "mmm", 248 | "MSB", 249 | "MSL", 250 | "MTTF", 251 | "MTU", 252 | "mul", 253 | "multicasting", 254 | "mycorrhizal", 255 | "NACK", 256 | "NAK", 257 | "namespace", 258 | "namespaces", 259 | "nano", 260 | "nanosatellites", 261 | "natively", 262 | "ned", 263 | "neq", 264 | "Netw", 265 | "NMEA", 266 | "NMI", 267 | "nodiscard", 268 | "noexcept", 269 | "nq", 270 | "ns", 271 | "nul", 272 | "num", 273 | "nz", 274 | "oct", 275 | "octothorp", 276 | "OFFLINE", 277 | "ok", 278 | "Ongaro", 279 | "online", 280 | "opencyphal", 281 | "ord", 282 | "org", 283 | "Ousterhout", 284 | "param", 285 | "parameterization", 286 | "parameterized", 287 | "paukan", 288 | "PHY", 289 | "pinout", 290 | "pnp", 291 | "polymorphically", 292 | "polymorphism", 293 | "pos", 294 | "POSIX", 295 | "prepended", 296 | "prepending", 297 | "println", 298 | "priori", 299 | "prioritization", 300 | "prn", 301 | "Protobuf", 302 | "pseudocode", 303 | "pseudorandom", 304 | "PSU", 305 | "py", 306 | "pycyphal", 307 | "pydsdl", 308 | "Pygments", 309 | "quaternion", 310 | "quaternions", 311 | "regex", 312 | "repres", 313 | "representable", 314 | "retransmission", 315 | "retransmit", 316 | "reusability", 317 | "RMC", 318 | "RPC", 319 | "rstrip", 320 | "RTCM", 321 | "runtime", 322 | "sats", 323 | "schemaless", 324 | "schemas", 325 | "semver.org", 326 | "Sep", 327 | "serializable", 328 | "setuptools", 329 | "Sheremet", 330 | "si", 331 | "significand", 332 | "sirius_cyber_corp", 333 | "SLCAN", 334 | "SMD", 335 | "stderr", 336 | "stdout", 337 | "str", 338 | "Streich", 339 | "struct", 340 | "Subminiature", 341 | "submodules", 342 | "suboptimal", 343 | "subtype", 344 | "Subtype", 345 | "subtypes", 346 | "subtyping", 347 | "supercapacitor", 348 | "Supercapacitor", 349 | "superset", 350 | "supertype", 351 | "supertypes", 352 | "surjective", 353 | "SVG", 354 | "sw", 355 | "SWD", 356 | "SWDCLK", 357 | "SWDIO", 358 | "symbionts", 359 | "syn-chro-ni-za-tion", 360 | "sz", 361 | "TBD", 362 | "tesla", 363 | "texer", 364 | "texlive", 365 | "th", 366 | "tid", 367 | "timestamp", 368 | "timestamping", 369 | "tmp", 370 | "TODO", 371 | "TPWR", 372 | "TTCAN", 373 | "TTFF", 374 | "Tx", 375 | "Typ", 376 | "u-Blox", 377 | "UART", 378 | "UAV", 379 | "UAVCAN", 380 | "uavcan.org", 381 | "UCS", 382 | "UDP", 383 | "UID", 384 | "uint", 385 | "uintdd", 386 | "Unary", 387 | "uncomment", 388 | "uncommented", 389 | "unicast", 390 | "unitless", 391 | "unresolvable", 392 | "unscaled", 393 | "uptime", 394 | "USB", 395 | "USENIX", 396 | "UTC", 397 | "UTF", 398 | "vcs", 399 | "versioned", 400 | "versioning", 401 | "Versioning", 402 | "vscode", 403 | "vv", 404 | "WAIC", 405 | "WGS84", 406 | "Whitespace", 407 | "whitespaces", 408 | "xor", 409 | "xxx", 410 | "xxxx", 411 | "xxxxx", 412 | "xxxxxx", 413 | "XYZ", 414 | "YAML", 415 | "YXXDR", 416 | "yyyy", 417 | "Zubax" 418 | ], 419 | } 420 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "build", 8 | "type": "shell", 9 | "command": "./compile.sh", 10 | "group": { 11 | "kind": "build", 12 | "isDefault": true 13 | }, 14 | "presentation": { 15 | "clear": true, 16 | "focus": true 17 | } 18 | }, 19 | { 20 | "label": "clean", 21 | "type": "shell", 22 | "command": "./clean.sh", 23 | "group": "build", 24 | "presentation": { 25 | "clear": true, 26 | "focus": true 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cyphal specification 2 | 3 | [![CI](https://github.com/OpenCyphal/specification/actions/workflows/build.yml/badge.svg)](https://github.com/OpenCyphal/specification/actions) 4 | [![Forum](https://img.shields.io/discourse/https/forum.opencyphal.org/users.svg)](https://forum.opencyphal.org) 5 | 6 | The sources of the Cyphal specification and other related documents are contained here. 7 | 8 | When cloning this repository, don't forget to initialize the Git submodules: 9 | `git submodule update --init --recursive`. 10 | 11 | ## Governance 12 | 13 | The Cyphal specification is community-managed and completely open. Anyone can propose changes but only Cyphal maintainers may commit changes to this repository where the contents of the HEAD revision of the primary branch constitutes the latest version of the specification in-effect. 14 | 15 | ### Request For Comments (RFC) Process 16 | 17 | Changes to the specification shall use the following, community-driven RFC process: 18 | 19 | 1. An RFC is posted on the [OpenCyphal forum's specification section](https://forum.opencyphal.org/c/dev/spec/15) with the details of the proposed change. The title of this post should start with "RFC: " to indicate it is the start of a proposed change to the specification. 20 | 2. RFCs will remain on the forum for at least 10 days to ensure interested parties have time to discover and review them. 21 | 3. After some discussion and review by the community, the RFC is either accepted or rejected by at least one OpenCyphal maintainer. 22 | 4. Once accepted the RFC is implemented in the specification as a pull-request and is considered adopted once the PR has been merged. 23 | 24 | ## Editing guide 25 | 26 | ### Style 27 | 28 | Follow the Zubax LaTeX guide: . 29 | **Do not edit the document without the spell checker.** 30 | 31 | Write in American English. 32 | 33 | Critical definitions (behaviors, constraints, assumptions, etc.) shall be written in the main body of the document. 34 | Optional content (clarifications, examples, elaborations) is placed either into footnotes or into blue remark boxes 35 | which can be defined using `\begin{remark}...\end{remark}`. 36 | 37 | Never address the reader directly. 38 | Do not hesitate to use passive voice. 39 | For example, instead of "you can find the data type X here", say "the data type X can be found here". 40 | 41 | Follow [RFC2119](https://tools.ietf.org/rfc/rfc2119.txt). 42 | 43 | Do not use title case. Headings and captions are to be written in regular sentence case. 44 | Generally, capitalized words can only be used in the beginning of a sentence and in proper names. 45 | 46 | Do not put a full stop after a caption unless it contains any other punctuation or is more than one sentence long. 47 | 48 | Always insert a non-breakable space before reference: `refer to section~\ref{sec:chapter_section}`. 49 | 50 | When referring to a category of identifiers, put a hyphen before "ID"; for example: "node-ID" is correct, "node ID" is not. 51 | 52 | Avoid introduction of new acronyms unless you really must. 53 | It is better to say "transfer-ID" or "data type hash" rather than TID or DTH. 54 | Excessive reliance on acronyms may impede comprehension. 55 | 56 | ### Rigging 57 | 58 | In order to refer to a DSDL definition, use macro `\DSDLReference{}`. 59 | To include a DSDL definition or a namespace index, use macro `\DSDL{}`. 60 | Refer to the existing usages for an example. 61 | 62 | ### Structure and cross-referencing 63 | 64 | Each chapter is located in a dedicated directory, whose name is a single lowercase word. 65 | The main file of the chapter is located in a file under the same name as the directory. 66 | For example: `chapter/chapter.tex` (where "chapter" is the chapter name placeholder). 67 | 68 | When defining a new label, you must use the prefix following the pattern `kind:chapter`, where: 69 | 70 | - "kind" is the kind of the labeled item, such as `fig`, `table`, or `sec`; 71 | - "chapter" is the name of the directory where the chapter is contained. 72 | 73 | The label that contains only the prefix points to the chapter itself using the kind `sec`. 74 | For example, if the chapter is named "Transport layer", its label would be `sec:transport`. 75 | 76 | Items contained inside the chapter (sections, figures, tables) are named using free form 77 | appended to the prefix. 78 | For example, one could refer to a figure contained inside the chapter "Chapter" as `fig:chapter_my_figure`. 79 | 80 | The above rules are crucial to follow to keep cross-references usable. 81 | Without strict conventions in place, they quickly become unmanageable. 82 | 83 | ### Source formatting 84 | 85 | - One level of nesting shall be indented with 4 spaces. Tabs shall not be used anywhere in the source. 86 | - There shall be no more than 120 characters per line. 87 | - There shall be exactly one blank line at the end of the file. 88 | - There shall be no more than one consecutive blank line. 89 | - There shall be at most one chapter per source file. 90 | - There shall be one blank line above and below a section header, 91 | unless the section header is at the top of the source file. 92 | - Multi-line content enclosed in curly braces should be indented. 93 | - If a list item spills on the next line, the spilled text should be indented on the same level with `\item`. 94 | 95 | ```tex 96 | \begin{itemize} 97 | \item This list item is sufficiently long to exceed the limit of 120 characters per line, 98 | so it has to spill onto the next line. 99 | The spilled part is indented correctly. 100 | 101 | \item Another item. 102 | \end{itemize} 103 | 104 | % The next line contains a comment to remove the whitespace in the beginning of the footnote. 105 | Regulated non-standard definitions\footnote{% 106 | I.e., public definitions contributed by vendors and other users 107 | of the specification, as explained in section~\ref{sec:basic_data_type_regulation}. 108 | } are not included in this list. 109 | ``` 110 | 111 | ## Tools 112 | 113 | ### Compiling 114 | 115 | A GNU/Linux-based operating system is assumed. 116 | The described instructions may be valid for other operating systems but this is not guaranteed. 117 | 118 | In order to compile the document, install TeX Live 119 | (Ubuntu packages: [`texlive-full`](https://packages.ubuntu.com/xenial/texlive-full) and `lyx`) 120 | and the Python packages listed in `requirements.txt`. 121 | 122 | When done, run `./compile.sh`. 123 | 124 | #### Using texer 125 | 126 | You can use our texer container to build the specification if you don't want to setup your own build environment. 127 | Please consult with the CI/CD workflow to find out which container version should be used. 128 | To enter the container from a local shell, go roughly like this: 129 | 130 | ```sh 131 | docker run -it --rm -v $(pwd):/repo -e LOCAL_USER_ID=`id -u` ghcr.io/opencyphal/texer:te22.4.1 bash 132 | ``` 133 | 134 | ### IDE setup 135 | 136 | First, ensure that you can compile the document as described above. 137 | Do not proceed further until that requirement is satisfied. 138 | 139 | Use Visual Studio Code with the recommended extensions for editing. 140 | More info in the [Zubax Knowledge Base](https://kb.zubax.com/x/IYEh). 141 | 142 | #### L33t IDE Setup 143 | 144 | If you want to use our [texer container](https://hub.docker.com/repository/docker/uavcan/texer) with vscode then install the ["ms-vscode-remote.vscode-remote-extensionpack"](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) and Docker. When you open vscode in this repository it should prompt you to "open this folder in container?". Otherwise `F1` or `CMD+SHIFT+P` and select `Remote-Containers: Reopen Locally`. Once within the container you can simply `F1` or `CMD+SHIFT+P` and `LaTeX Workshop: Build LaTeX project` to build the specification PDF. 145 | 146 | The above [may not work](https://github.com/microsoft/vscode-remote-release/issues/1097) if you are running an OSS build of VSCode (e.g., from Arch AUR). It is recommended to use the official binaries from Micro$oft. 147 | -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd specification 4 | 5 | rm -f *.aux *.lof *.lot *.out *.toc *.log *.tmp *.gz *.cache *-converted-to.* 6 | rm -rf _minted-* 7 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SRC=Cyphal_Specification 4 | 5 | # https://tex.stackexchange.com/a/52994/132781 6 | export max_print_line=1000 7 | export error_line=254 8 | export half_error_line=238 9 | 10 | function once() 11 | { 12 | pdflatex -interaction=nonstopmode -file-line-error --halt-on-error --shell-escape $@ 13 | } 14 | 15 | ./clean.sh || exit 1 16 | 17 | cd specification 18 | once $SRC.tex || exit 1 19 | #bibtex $SRC || exit 1 20 | once $SRC.tex || exit 1 21 | once $SRC.tex || exit 1 22 | 23 | echo 'Success.' 24 | -------------------------------------------------------------------------------- /render_dsdl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # This script accepts the name of a DSDL definition, or a DSDL namespace followed by a glob asterisk, 4 | # and prints its LaTeX representation into stdout. Usage examples: 5 | # 6 | # ./render_dsdl.py uavcan.node.* --index-only 7 | # Prints an index table of the namespace "uavcan.node". The index table will be accessible via the 8 | # reference label "table:dsdl:uavcan.node". 9 | # 10 | # ./render_dsdl.py uavcan.node.Heartbeat 11 | # Prints the source text of the definition "uavcan.node.Heartbeat" and prepends it with a brief 12 | # explanatory text. 13 | # 14 | # ./render_dsdl.py uavcan.* 15 | # Generates an index table of the namespace "uavcan", and then provides a sequence of sections 16 | # containing the source text of the data type definitions contained in this namespace. 17 | # Each definition is provided with a label of the form like "sec:dsdl:uavcan.node.Heartbeat". 18 | # 19 | # For more info just read the code. 20 | # 21 | 22 | import os 23 | import re 24 | import sys 25 | import pydsdl 26 | import pickle 27 | import subprocess 28 | from fnmatch import fnmatch 29 | from functools import partial 30 | from collections import OrderedDict 31 | 32 | SOURCE_ROOT_DIRECTORY = os.path.abspath(os.path.dirname(__file__)) 33 | 34 | ROOT_NAMESPACE_SUPERDIRECTORY = os.path.join(SOURCE_ROOT_DIRECTORY, 'dsdl') 35 | 36 | CACHE_FILE_NAME_SUFFIX = '.dsdl.cache' 37 | 38 | 39 | sys.stderr = sys.stdout 40 | 41 | 42 | def die(why: str) -> None: 43 | print(why, file=sys.stderr) 44 | exit(1) 45 | 46 | 47 | def escape(s: str) -> str: 48 | return s.replace('_', r'\_') 49 | 50 | 51 | def get_dsdl_submodule_commit_hash() -> str: 52 | return subprocess.check_output(['git', 'rev-parse', 'HEAD'], 53 | cwd=ROOT_NAMESPACE_SUPERDIRECTORY).decode('ascii').strip() 54 | 55 | 56 | def render_dsdl_info(t: pydsdl.CompositeType) -> str: 57 | if isinstance(t, pydsdl.ServiceType): 58 | return ( 59 | r'\begin{itemize}' + 60 | r'\item Request: ' + render_dsdl_info(t.request_type) + 61 | r'\item Response: ' + render_dsdl_info(t.response_type) + 62 | r'\end{itemize}' 63 | ) 64 | 65 | fin = t.inner_type if isinstance(t, pydsdl.DelimitedType) else t 66 | bls_bytes = {(x + 7) // 8 for x in fin.bit_length_set} 67 | length = str(max(bls_bytes)) if len(bls_bytes) == 1 else (r'$%d\ldots{}%d$' % (min(bls_bytes), max(bls_bytes))) 68 | 69 | if isinstance(t, pydsdl.DelimitedType): 70 | return 'Size without delimiter header: %s bytes; extent %d bytes.' % ( 71 | length, 72 | t.extent / 8, 73 | ) 74 | else: 75 | return 'Size %s bytes; sealed.' % ( 76 | length, 77 | ) 78 | 79 | def render_dsdl_definition(t: pydsdl.CompositeType) -> str: 80 | minted_params = r'fontsize=\scriptsize, numberblanklines=true, baselinestretch=0.9, autogobble=false' 81 | return '\n'.join([ 82 | r'\begin{minted}[%s]{python}' % minted_params, 83 | open(t.source_file_path).read(), 84 | r'\end{minted}', 85 | ]) 86 | 87 | 88 | try: 89 | index_only = False 90 | if '--index-only' in sys.argv: 91 | sys.argv.remove('--index-only') 92 | index_only = True 93 | 94 | pattern = sys.argv[1] 95 | except IndexError: 96 | die('Expected full type name glob, e.g., "uavcan.node.Heartbeat" or "uavcan.file.*"') 97 | 98 | # Find out which namespace directories to read 99 | root_namespaces = list(filter(os.path.isdir, 100 | map(partial(os.path.join, ROOT_NAMESPACE_SUPERDIRECTORY), 101 | os.listdir(ROOT_NAMESPACE_SUPERDIRECTORY)))) 102 | 103 | # Read all namespaces and join the results into one big list 104 | cache_file_name = get_dsdl_submodule_commit_hash() + CACHE_FILE_NAME_SUFFIX 105 | try: 106 | types = pickle.load(open(cache_file_name, 'rb')) 107 | except Exception as ex: 108 | if not isinstance(ex, FileNotFoundError): 109 | with open('cache_read_error.tmp', 'w') as f: 110 | f.write(repr(ex)) 111 | types = sum([pydsdl.read_namespace(ns, root_namespaces) for ns in root_namespaces], []) 112 | pickle.dump(types, open(cache_file_name, 'wb')) 113 | 114 | # Filter according to the specified pattern 115 | matching = list(filter(lambda t: fnmatch(t.full_name, pattern), types)) 116 | if not matching: 117 | die('No types match the pattern: %s' % pattern) 118 | 119 | # Natural sorting by name and version (numerical ordering, not lexicographical); 120 | # newest version first, oldest version last. 121 | matching.sort(key=lambda t: ([int(c) if c.isdigit() else c for c in re.split(r'(\d+)', t.full_name)] + 122 | [-t.version.major, -t.version.minor])) 123 | 124 | # See if we were asked to render a particular type only. 125 | # If that is the case, output an abridged form, provide a reference, and then exit. 126 | # The output should contain the latest non-deprecated definition. 127 | if '*' not in pattern: 128 | matching_except_deprecated = list(filter(lambda t: not t.deprecated, matching)) 129 | if not matching_except_deprecated: 130 | die('All versions of the type %s are deprecated, nothing to display' % pattern) 131 | 132 | t = matching_except_deprecated[0] # Due to sorting, newest version ends up first 133 | service_or_subject = 'service' if isinstance(t, pydsdl.ServiceType) else 'subject' 134 | print(r'The DSDL source text of \verb|%s|' % t.full_name) 135 | print('version %d.%d' % t.version) 136 | if len(matching) > 2: 137 | print('(there are', len(matching) - 1, 'older versions)') 138 | elif len(matching) > 1: 139 | print('(there is one older version)') 140 | else: 141 | print('(this is the only version)') 142 | 143 | if t.has_fixed_port_id: 144 | print('with a fixed', service_or_subject, 'ID', t.fixed_port_id) 145 | else: 146 | print('without fixed', service_or_subject, 'ID') 147 | 148 | print(r'is provided below.') 149 | print(r'More information is available in') 150 | print(r'section \ref{sec:dsdl:%s} on page \pageref{sec:dsdl:%s}.' % (t.full_name, t.full_name)) 151 | print(r'\pagebreak[2]{}') # This is needed to discourage page breaks within the listings 152 | print(render_dsdl_definition(t)) 153 | exit(0) 154 | 155 | # Group by namespace and by type name (i.e., all versions grouped together by name). 156 | # We re-sort (remember, the sorting is stable) to move types that have at least one version with a fixed port ID 157 | # to the top. 158 | grouped = OrderedDict() 159 | for t in sorted(matching, key=lambda t: not t.has_fixed_port_id): 160 | grouped.setdefault(t.full_namespace, OrderedDict()).setdefault(t.full_name, []).append(t) 161 | 162 | # Render short reference 163 | naked_pattern = pattern.strip('.*') 164 | is_nested_namespace = '.' in naked_pattern 165 | 166 | # We avoid using longtabu unless we really have to because it's a bloody disaster. Its caption is always misaligned 167 | # vertically (requires hacking with \abovecaptionskip to fix) and it tends to run over text and footnotes below it. 168 | table_environment = 'tabu' if is_nested_namespace else 'longtabu' 169 | 170 | if is_nested_namespace: 171 | # Confine nested namespace indexes to one page, assuming that they are always compact enough to fit. 172 | print(r'{\parindent=-\leftskip\begin{minipage}{\textwidth}\centering') 173 | 174 | print(r'\begin{ThreePartTable}') 175 | print(r"\captionof{table}{Index of the %s namespace ``%s''}%%" % 176 | ('nested' if is_nested_namespace else 'root', naked_pattern)) 177 | print(r'\label{table:dsdl:%s}%%' % naked_pattern) 178 | print(r'\footnotesize\setlength\tabcolsep{3pt}\setlength{\tabulinesep}{-1pt}\setlength{\extrarowsep}{-1pt}%') 179 | print(r'\begin{%s}{|l r r|c c|l|}\rowfont{\bfseries}\hline' % table_environment) 180 | print(r'Namespace tree & Ver. & FPID &', 181 | r'max(BLS) bytes &', 182 | r'Extent bytes &', 183 | r'Full name \\\hline') 184 | prefix = '.' 185 | at_least_one_type_emitted = False 186 | INDENT_BLOCK = r'\quad{}' 187 | for namespace, ns_type_mapping in grouped.items(): 188 | # Hint LaTeX that it's a good place to begin a new page if necessary because we're beginning a new namespace 189 | if at_least_one_type_emitted: 190 | print(r'\pagebreak[2]{}') 191 | 192 | # Walk up and down the tree levels, emitting tree mark rows in the process 193 | current_prefix = '.' + namespace + '.' 194 | while prefix != current_prefix: 195 | if current_prefix.startswith(prefix): 196 | new_comp = current_prefix[len(prefix):].strip('.').split('.')[0] 197 | print(INDENT_BLOCK * (prefix.count('.') - 1) + r'\texttt{%s}' % escape(new_comp), r'&&&&&\\', sep='') 198 | prefix += new_comp 199 | else: 200 | prefix = '.' + '.'.join(prefix.strip('.').split('.')[:-1]) 201 | 202 | prefix += '.' 203 | 204 | # Render all types in this namespace 205 | for type_name, versions in ns_type_mapping.items(): 206 | # Render all versions of this type, sorted newest first 207 | versions.sort(key=lambda t: -t.version.major * 1000 - t.version.minor) 208 | for index, t in enumerate(versions): 209 | is_first = index == 0 210 | is_service = isinstance(t, pydsdl.ServiceType) 211 | at_least_one_type_emitted = True 212 | 213 | # Allow page breaks only when switching namespaces 214 | print(r'\nopagebreak[4]{}') 215 | 216 | # Layout information 217 | b2b = lambda x: (x + 7) // 8 218 | is_sealed = lambda t: not isinstance(t, pydsdl.DelimitedType) 219 | annotate_sealing = lambda t, x: r'\textit{sealed}' if is_sealed(t) else str(x) 220 | if is_service: 221 | ser_max_bytes = r'$%d \rightleftharpoons{} %d$' % ( 222 | b2b(max(t.request_type.bit_length_set)), 223 | b2b(max(t.response_type.bit_length_set)) 224 | ) 225 | extent_bytes = r'$%s \rightleftharpoons{} %s$' % ( 226 | annotate_sealing(t.request_type, b2b(t.request_type.extent)), 227 | annotate_sealing(t.response_type, b2b(t.response_type.extent)) 228 | ) 229 | else: 230 | ser_max_bytes = r'$%d$' % b2b(max(t.bit_length_set)) 231 | extent_bytes = r'$%s$' % annotate_sealing(t, b2b(t.extent)) 232 | 233 | weak = lambda s: r'\emph{\color{gray}%s}' % s 234 | 235 | if is_first: 236 | print((INDENT_BLOCK * (prefix.count('.') - 1)) + r'\texttt{%s}' % t.short_name, '&') 237 | else: 238 | print((INDENT_BLOCK * prefix.count('.')) + weak('older version'), '&') 239 | 240 | print('%d.%d' % t.version, '&', 241 | t.fixed_port_id if t.has_fixed_port_id else '', '&', 242 | ser_max_bytes, '&', 243 | extent_bytes, '&') 244 | 245 | if is_first: 246 | print(r'\hyperref[sec:dsdl:%s]{\texttt{%s}}' % (t.full_name, escape(t.full_name)), r'\\') 247 | else: 248 | print(weak(r'$\cdots{}$'), r'\\') 249 | 250 | print(r'\hline\end{%s}' % table_environment) 251 | print(r'\end{ThreePartTable}') 252 | if is_nested_namespace: 253 | print(r'\end{minipage}}') 254 | 255 | if index_only: 256 | exit(0) 257 | 258 | # Render definitions 259 | labeled_namespaces = set() 260 | for namespace, children in grouped.items(): 261 | # New section for each new sub-root namespace 262 | if namespace.strip('. ').count('.') < 2: 263 | print(r'\clearpage') 264 | 265 | print(r'\section{%s}' % escape(namespace)) 266 | 267 | # Generate labels for all namespaces, starting from the root one. 268 | # Each label points to the first appearance of its namespace. 269 | for ns in ['.'.join(namespace.split('.')[:i]) for i in range(1, namespace.count('.') + 2)]: 270 | if ns not in labeled_namespaces: 271 | labeled_namespaces.add(ns) 272 | print(r'\label{sec:dsdl:%s}' % ns) 273 | 274 | for full_name, versions in children.items(): 275 | is_service = isinstance(versions[0], pydsdl.ServiceType) 276 | 277 | print(r'\pagebreak[3]{}') 278 | print(r'\subsection{%s}' % full_name.split(pydsdl.CompositeType.NAME_COMPONENT_SEPARATOR)[-1]) 279 | print(r'\label{sec:dsdl:%s}' % full_name) 280 | print(r'Full %s type name: {\bfseries\texttt{%s}}' % 281 | ('service' if is_service else 'message', escape(full_name))) 282 | 283 | for t in versions: 284 | title = 'Version %d.%d' % t.version 285 | 286 | if t.has_fixed_port_id: 287 | service_or_subject = 'service' if is_service else 'subject' 288 | title += ', fixed %s ID %d' % (service_or_subject, t.fixed_port_id) 289 | 290 | if t.deprecated: 291 | title += ', DEPRECATED' 292 | 293 | print(r'\subsubsection{%s}' % title) 294 | print(render_dsdl_info(t)) 295 | print(r'\pagebreak[2]{}') # This is needed to discourage page breaks within the listings 296 | print(render_dsdl_definition(t)) 297 | -------------------------------------------------------------------------------- /render_list_of_void_and_primitive_types.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This script simply outputs the full set of void and primitive types ordered by bit length. 4 | # 5 | 6 | print(r'\begin{enumerate}') 7 | for i in range(1, 65): 8 | print(' ' * 4 + r'\item ' + r' \quad{} '.join(filter(None, [ 9 | (r'\verb|void%-3d|') % i, 10 | (r'\verb|int%-3d|' % i) if i >= 2 else None, 11 | (r'\verb|uint%-3d|' % i) if i >= 1 else None, 12 | (r'\verb|float%-3d|' % i) if i in (16, 32, 64) else None, 13 | (r'\verb|bool|') if i == 1 else None, 14 | ]))) 15 | print(r'\end{enumerate}') 16 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # This file lists the Python dependencies that are necessary to build the specification. 2 | pygments 3 | pydsdl ~= 1.16 4 | -------------------------------------------------------------------------------- /specification/.gitignore: -------------------------------------------------------------------------------- 1 | ## Core latex/pdflatex auxiliary files: 2 | *.aux 3 | *.lof 4 | *.log 5 | *.lot 6 | *.fls 7 | *.out 8 | *.toc 9 | *.fmt 10 | *.fot 11 | *.cb 12 | *.cb2 13 | 14 | ## Intermediate documents: 15 | *.dvi 16 | *-converted-to.* 17 | # these rules might exclude image files for figures etc. 18 | # *.ps 19 | # *.eps 20 | # *.pdf 21 | 22 | ## Bibliography auxiliary files (bibtex/biblatex/biber): 23 | *.bbl 24 | *.bcf 25 | *.blg 26 | *-blx.aux 27 | *-blx.bib 28 | *.brf 29 | *.run.xml 30 | 31 | ## Build tool auxiliary files: 32 | *.fdb_latexmk 33 | *.synctex* 34 | *.pdfsync 35 | 36 | ## Auxiliary and intermediate files from other packages: 37 | # algorithms 38 | *.alg 39 | *.loa 40 | 41 | # achemso 42 | acs-*.bib 43 | 44 | # amsthm 45 | *.thm 46 | 47 | # beamer 48 | *.nav 49 | *.snm 50 | *.vrb 51 | 52 | # cprotect 53 | *.cpt 54 | 55 | # fixme 56 | *.lox 57 | 58 | #(r)(e)ledmac/(r)(e)ledpar 59 | *.end 60 | *.?end 61 | *.[1-9] 62 | *.[1-9][0-9] 63 | *.[1-9][0-9][0-9] 64 | *.[1-9]R 65 | *.[1-9][0-9]R 66 | *.[1-9][0-9][0-9]R 67 | *.eledsec[1-9] 68 | *.eledsec[1-9]R 69 | *.eledsec[1-9][0-9] 70 | *.eledsec[1-9][0-9]R 71 | *.eledsec[1-9][0-9][0-9] 72 | *.eledsec[1-9][0-9][0-9]R 73 | 74 | # glossaries 75 | *.acn 76 | *.acr 77 | *.glg 78 | *.glo 79 | *.gls 80 | *.glsdefs 81 | 82 | # gnuplottex 83 | *-gnuplottex-* 84 | 85 | # hyperref 86 | *.brf 87 | 88 | # knitr 89 | *-concordance.tex 90 | # TODO Comment the next line if you want to keep your tikz graphics files 91 | *.tikz 92 | *-tikzDictionary 93 | 94 | # listings 95 | *.lol 96 | 97 | # makeidx 98 | *.idx 99 | *.ilg 100 | *.ind 101 | *.ist 102 | 103 | # minitoc 104 | *.maf 105 | *.mlf 106 | *.mlt 107 | *.mtc 108 | *.mtc[0-9] 109 | *.mtc[1-9][0-9] 110 | 111 | # minted 112 | _minted* 113 | *.pyg 114 | 115 | # morewrites 116 | *.mw 117 | 118 | # mylatexformat 119 | *.fmt 120 | 121 | # nomencl 122 | *.nlo 123 | 124 | # sagetex 125 | *.sagetex.sage 126 | *.sagetex.py 127 | *.sagetex.scmd 128 | 129 | # sympy 130 | *.sout 131 | *.sympy 132 | sympy-plots-for-*.tex/ 133 | 134 | # pdfcomment 135 | *.upa 136 | *.upb 137 | 138 | # pythontex 139 | *.pytxcode 140 | pythontex-files-*/ 141 | 142 | # thmtools 143 | *.loe 144 | 145 | # TikZ & PGF 146 | *.dpth 147 | *.md5 148 | *.auxlock 149 | 150 | # todonotes 151 | *.tdo 152 | 153 | # xindy 154 | *.xdy 155 | 156 | # xypic precompiled matrices 157 | *.xyc 158 | 159 | # endfloat 160 | *.ttt 161 | *.fff 162 | 163 | # Latexian 164 | TSWLatexianTemp* 165 | 166 | ## Editors: 167 | # WinEdt 168 | *.bak 169 | *.sav 170 | 171 | # Texpad 172 | .texpadtmp 173 | 174 | # Kile 175 | *.backup 176 | 177 | # KBibTeX 178 | *~[0-9]* 179 | 180 | # Outputs 181 | *-converted-to.* 182 | Cyphal_Specification.pdf 183 | -------------------------------------------------------------------------------- /specification/Cyphal_Specification.tex: -------------------------------------------------------------------------------- 1 | % !TEX root 2 | % 3 | % Copyright (c) OpenCyphal 4 | % 5 | 6 | \documentclass{cyphaldoc} 7 | 8 | \usepackage{multirow} 9 | \usepackage{tabularx} 10 | \usepackage{amsmath} 11 | \usepackage{amssymb} 12 | \usepackage{amsfonts} 13 | \usepackage{longtable} 14 | \usepackage{diagbox} 15 | 16 | \urlstyle{same} 17 | 18 | % This macro embeds the selected DSDL definition or the contents of a DSDL namespace into the document. 19 | % It accepts one mandatory argument which is either a full DSDL type name, e.g. uavcan.node.Heartbeat, 20 | % or a full type name glob expression, e.g., uavcan.node.*. 21 | \newcommand{\DSDL}[1]{% 22 | % Clean up beforehand to ensure clean initial state. 23 | \immediate\write18{rm -f ../*.tmp}% 24 | % Invoke the target command and save the useful output into a file; ignore error output 25 | \immediate\write18{../render_dsdl.py #1 > ../dsdl.tmp}% 26 | % Now, if the above command has failed, the output file would be empty. We remove empty file to escalate error. 27 | % Escalation is very important as it allows us to abort compilation on failure instead of generating invalid 28 | % documents silently. 29 | \immediate\write18{find .. -type f -name '*.tmp' -size 0 -delete}% 30 | % Read the file. This command fails if the file was empty, which is exactly want we want. 31 | \immediate\input{../dsdl.tmp}% 32 | % Clean up afterwards to prevent accidental reuse if the command fails the next time we invoke it. 33 | \immediate\write18{rm -f ../*.tmp}% 34 | } 35 | 36 | \newcommand{\DSDLReference}[1]{% We use detokenize to permit underscores 37 | \mbox{\texttt{\detokenize{#1}}} (section~\ref{sec:dsdl:#1} on page~\pageref{sec:dsdl:#1})% 38 | } 39 | 40 | \title{Specification v1.0} 41 | 42 | \hbadness=10000 43 | 44 | \begin{document} 45 | \frontmatter 46 | 47 | \begin{titlepage} 48 | 49 | \section*{Overview} 50 | 51 | Cyphal is an open technology for real-time intravehicular distributed computing and communication based on 52 | modern networking standards (Ethernet, CAN FD, etc.). 53 | It was created to address the challenge of on-board deterministic computing and data distribution in 54 | next-generation intelligent vehicles: manned and unmanned aircraft, spacecraft, robots, and cars. 55 | 56 | Features: 57 | 58 | \begin{itemize} 59 | \item Democratic network -- no bus master, no single point of failure. 60 | \item Publish/subscribe and request/response (RPC\footnote{Remote procedure call.}) com\-mu\-ni\-ca\-tion semantics. 61 | \item Efficient exchange of large data structures with automatic decomposition and reassembly. 62 | \item Lightweight, deterministic, easy to implement, and easy to validate. 63 | \item Suitable for deeply embedded, resource constrained, hard real-time systems. 64 | \item Supports dual and triply modular redundant transports. 65 | \item Supports high-precision network-wide time syn\-chro\-ni\-za\-tion. 66 | \item Provides rich data type and interface abstractions -- an interface description language is a core part of 67 | the technology which allows deeply embedded sub-systems to interface with higher-level systems directly and 68 | in a maintainable manner while enabling simulation and functional testing. 69 | \item The specification and high quality reference implementations in popular programming languages are free, 70 | open source, and available for commercial use under the permissive MIT license. 71 | \end{itemize} 72 | 73 | \BeginRightColumn 74 | 75 | \section*{License} 76 | 77 | Cyphal is a standard open to everyone, and it will always remain this way. 78 | No authorization or approval of any kind is necessary for its implementation, distribution, or use. 79 | 80 | % The following statement looks a bit archaic, but it is the recommended form according to 81 | % https://creativecommons.org/choose/results-one?license_code=by&jurisdiction=&version=4.0&lang=en 82 | This work is licensed under the Creative Commons Attribution 4.0 International License. 83 | To view a copy of this license, visit 84 | \href{http://creativecommons.org/licenses/by/4.0/}{creativecommons.org/licenses/by/4.0} 85 | or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. 86 | 87 | \hspace*{\fill}\includegraphics[height=1.75\baselineskip]{cc-by}\hspace*{\fill} 88 | 89 | \section*{Disclaimer of warranty} 90 | 91 | Note well: this Specification is provided on an ``as is'' basis, without warranties or conditions of any kind, 92 | express or implied, including, without limitation, any warranties or conditions of 93 | title, non-infringement, merchantability, or fitness for a particular purpose. 94 | 95 | \section*{Limitation of liability} 96 | 97 | In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, 98 | unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, 99 | shall any author of this Specification be liable for damages, 100 | including any direct, indirect, special, incidental, or consequential damages of any character arising 101 | from, out of, or in connection with the Specification or the implementation, deployment, 102 | or other use of the Specification (including but not limited to damages for loss of goodwill, 103 | work stoppage, equipment failure or malfunction, injuries to persons, death, 104 | or any and all other commercial damages or losses), 105 | even if such author has been made aware of the possibility of such damages. 106 | 107 | \end{titlepage} 108 | 109 | \tableofcontents 110 | \clearpage\onecolumn\listoftables 111 | \clearpage\onecolumn\listoffigures 112 | 113 | \mainmatter 114 | 115 | \input{introduction/introduction.tex} 116 | \input{basic/basic.tex} 117 | \input{dsdl/dsdl.tex} 118 | \input{transport/transport.tex} 119 | \input{application/application.tex} 120 | \input{sdt/sdt.tex} 121 | \input{appendices/appendices.tex} 122 | 123 | \end{document} 124 | -------------------------------------------------------------------------------- /specification/appendices/appendices.tex: -------------------------------------------------------------------------------- 1 | \appendix 2 | \input{appendices/crc.tex} 3 | -------------------------------------------------------------------------------- /specification/appendices/crc.tex: -------------------------------------------------------------------------------- 1 | \chapter{CRC algorithm implementations} 2 | 3 | \section{CRC-16/CCITT-FALSE}\label{sec:appendix_crc16ccitt_false} 4 | 5 | This algorithm is also known as CRC-16/AUTOSAR or CRC-16/IBM-3740. 6 | Not to be confused with CRC-16/KERMIT. 7 | 8 | This algorithm has the following parameters: 9 | \begin{itemize} 10 | \item width: 16 bits; 11 | \item polynomial: $\mathrm{1021}_{16}$; 12 | \item initial value: $\mathrm{FFFF}_{16}$; 13 | \item input not reflected; 14 | \item output not reflected; 15 | \item no output XOR; 16 | \item the native byte order is big endian. 17 | \end{itemize} 18 | 19 | The value for the input sequence $\left(49, 50, \ldots, 56, 57\right)$ is $\mathrm{29B1}_{16}$. 20 | 21 | \subsection{C++, bitwise} 22 | 23 | \begin{samepage} 24 | \begin{minted}{cpp} 25 | #include 26 | #include 27 | #include 28 | 29 | class CRC16_CCITT_False final 30 | { 31 | public: 32 | void add(const std::uint8_t byte) 33 | { 34 | value_ ^= static_cast(byte) << 8U; 35 | for (std::uint8_t bit = 8; bit > 0; --bit) 36 | { 37 | if ((value_ & 0x8000U) != 0) 38 | { 39 | value_ = (value_ << 1U) ^ 0x1021U; 40 | } 41 | else 42 | { 43 | value_ = value_ << 1U; 44 | } 45 | } 46 | } 47 | 48 | void add(const std::uint8_t* bytes, std::size_t length) 49 | { 50 | while (length --> 0) 51 | { 52 | add(*bytes++); 53 | } 54 | } 55 | 56 | [[nodiscard]] std::uint16_t get() const { return value_; } 57 | 58 | [[nodiscard]] std::array getBytes() const noexcept 59 | { 60 | const auto x = get(); 61 | return {static_cast(x >> 8U), static_cast(x & 0xFFU)}; 62 | } 63 | 64 | private: 65 | std::uint16_t value_ = 0xFFFFU; 66 | }; 67 | \end{minted} 68 | \end{samepage} 69 | 70 | \subsection{Python, bytewise} 71 | 72 | \begin{samepage} 73 | \begin{minted}{python} 74 | class CRC16CCITT: 75 | def __init__(self) -> None: 76 | self._value = 0xFFFF 77 | 78 | def add(self, data: bytes | bytearray | memoryview) -> None: 79 | val = self._value 80 | for x in data: 81 | val = ((val << 8) & 0xFFFF) ^ self._TABLE[(val >> 8) ^ x] 82 | self._value = val 83 | 84 | def check_residue(self) -> bool: 85 | return self._value == 0 86 | 87 | @property 88 | def value(self) -> int: 89 | return self._value 90 | 91 | @property 92 | def value_as_bytes(self) -> bytes: 93 | return self.value.to_bytes(2, "big") 94 | 95 | _TABLE = [ 96 | 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 97 | 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 98 | 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 99 | 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 100 | 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 101 | 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 102 | 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 103 | 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 104 | 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 105 | 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 106 | 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 107 | 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 108 | 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 109 | 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 110 | 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 111 | 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 112 | 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 113 | 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 114 | 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 115 | 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 116 | 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 117 | 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 118 | 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 119 | 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 120 | 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 121 | 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 122 | 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 123 | 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 124 | 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 125 | 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 126 | 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 127 | 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, 128 | ] 129 | \end{minted} 130 | \end{samepage} 131 | 132 | \newpage 133 | \section{CRC-32C}\label{sec:appendix_crc32c} 134 | 135 | This algorithm is also known as CRC-32/ISCSI, CRC-32/CASTAGNOLI, CRC-32/BASE91-C, or CRC-32/INTERLAKEN. 136 | 137 | This algorithm has the following parameters: 138 | \begin{itemize} 139 | \item width: 32 bits; 140 | \item polynomial: $\mathrm{1EDC6F41}_{16}$; 141 | \item initial value: $\mathrm{FFFFFFFF}_{16}$; 142 | \item input reflected; 143 | \item output reflected; 144 | \item output XOR: $\mathrm{FFFFFFFF}_{16}$; 145 | \item residue: $\mathrm{B798B438}_{16}$ before output XOR, $\mathrm{48674BC7}_{16}$ after output XOR; 146 | \item the native byte order is little endian. 147 | \end{itemize} 148 | 149 | The value for the input sequence $\left(49, 50, \ldots, 56, 57\right)$ is $\mathrm{E3069283}_{16}$. 150 | 151 | \subsection{C++, bitwise} 152 | 153 | \begin{samepage} 154 | \begin{minted}{cpp} 155 | #include 156 | #include 157 | #include 158 | 159 | class CRC32C final 160 | { 161 | public: 162 | static constexpr std::size_t Size = 4; 163 | 164 | void update(const std::uint8_t b) noexcept 165 | { 166 | value_ ^= static_cast(b); 167 | for (auto i = 0U; i < 8U; i++) 168 | { 169 | value_ = ((value_ & 1U) != 0) ? ((value_ >> 1U) ^ ReflectedPoly) : (value_ >> 1U); 170 | } 171 | } 172 | 173 | [[nodiscard]] std::uint32_t get() const noexcept { return value_ ^ Xor; } 174 | 175 | [[nodiscard]] std::array getBytes() const noexcept 176 | { 177 | const auto x = get(); 178 | return { 179 | static_cast(x >> (8U * 0U)), 180 | static_cast(x >> (8U * 1U)), 181 | static_cast(x >> (8U * 2U)), 182 | static_cast(x >> (8U * 3U)), 183 | }; 184 | } 185 | 186 | [[nodiscard]] auto isResidueCorrect() const noexcept { return value_ == Residue; } 187 | 188 | private: 189 | static constexpr std::uint32_t Xor = 0xFFFF'FFFFUL; 190 | static constexpr std::uint32_t ReflectedPoly = 0x82F6'3B78UL; 191 | static constexpr std::uint32_t Residue = 0xB798'B438UL; 192 | 193 | std::uint32_t value_ = Xor; 194 | }; 195 | \end{minted} 196 | \end{samepage} 197 | 198 | \subsection{Python, bytewise} 199 | 200 | \begin{samepage} 201 | \begin{minted}{python} 202 | class CRC32C: 203 | def __init__(self) -> None: 204 | self._value = 0xFFFFFFFF 205 | 206 | def add(self, data: bytes | bytearray | memoryview) -> None: 207 | val = self._value 208 | for x in data: 209 | val = (val >> 8) ^ self._TABLE[x ^ (val & 0xFF)] 210 | self._value = val 211 | 212 | def check_residue(self) -> bool: 213 | return self._value == 0xB798B438 # Checked before the output XOR is applied. 214 | 215 | @property 216 | def value(self) -> int: 217 | return self._value ^ 0xFFFFFFFF 218 | 219 | @property 220 | def value_as_bytes(self) -> bytes: 221 | return self.value.to_bytes(4, "little") 222 | 223 | _TABLE = [ 224 | 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 225 | 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 226 | 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 227 | 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 228 | 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 229 | 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 230 | 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 231 | 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 232 | 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 233 | 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 234 | 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 235 | 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 236 | 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 237 | 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 238 | 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 239 | 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 240 | 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 241 | 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 242 | 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 243 | 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 244 | 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 245 | 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 246 | 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 247 | 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 248 | 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 249 | 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 250 | 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 251 | 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 252 | 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 253 | 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 254 | 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 255 | 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, 256 | ] 257 | \end{minted} 258 | \end{samepage} 259 | -------------------------------------------------------------------------------- /specification/application/application.tex: -------------------------------------------------------------------------------- 1 | \chapter{Application layer}\label{sec:application} 2 | 3 | Previous chapters of this specification define a set of basic concepts that are the foundation of the protocol: 4 | they allow one to define data types and exchange data objects over the bus in a robust and deterministic manner. 5 | This chapter is focused on higher-level concepts: rules, conventions, and standard functions that are to be 6 | respected by applications utilizing Cyphal to maximize cross-vendor compatibility, avoid ambiguities, and 7 | prevent some common design pitfalls. 8 | 9 | The rules, conventions, and standard functions defined in this chapter are designed to be an acceptable middle 10 | ground for any sensible aerospace or robotic system. 11 | Cyphal favors no particular domain or kind of system among targeted applications. 12 | 13 | \begin{itemize} 14 | \item Section~\ref{sec:application_requirements} contains a set of mandatory rules that shall be 15 | followed by all Cyphal implementations. 16 | 17 | \item Section~\ref{sec:application_conventions} contains a set of conventions and recommendations that 18 | are not mandatory to follow. Every deviation, however, should be justified and well-documented. 19 | 20 | \item Section~\ref{sec:application_functions} contains a full list of high-level functions defined on 21 | top of Cyphal. Formal specification of such functions is provided in the DSDL data type definition files that 22 | those functions are based on (see chapter~\ref{sec:sdt}). 23 | \end{itemize} 24 | 25 | \clearpage\input{application/requirements.tex} 26 | \clearpage\input{application/conventions.tex} 27 | \clearpage\input{application/functions.tex} 28 | -------------------------------------------------------------------------------- /specification/application/conventions.tex: -------------------------------------------------------------------------------- 1 | \section{Application-level conventions}\label{sec:application_conventions} 2 | 3 | This section describes a set of high-level conventions designed to enhance compatibility 4 | of applications leveraging Cyphal. 5 | The conventions described here are not mandatory to follow; 6 | however, every deviation should be justified and documented. 7 | 8 | \subsection{Node identifier distribution} 9 | 10 | An overview of related concepts is provided in chapter~\ref{sec:basic}. 11 | 12 | Valid values of node-ID range from 0 up to a transport-specific upper boundary 13 | which is guaranteed to be above 127 for any transport. 14 | 15 | Node-ID values of 126 and 127 are reserved for diagnostic and debugging tools. 16 | These values should not be used in fielded systems. 17 | 18 | \subsection{Service latency} 19 | 20 | If the server uses a significant part of the timeout period to process the request, 21 | the client might drop the request before receiving the response. 22 | Servers should minimize the request processing time; that is, 23 | the time between reception of a service request transfer and 24 | the transmission of the corresponding service response transfer. 25 | 26 | The worst-case request processing time should be documented for each server-side service port. 27 | 28 | \subsection{Coordinate frames} 29 | 30 | Cyphal follows the conventions that are widely accepted in relevant applications. 31 | Adherence to the coordinate frame conventions described here maximizes compatibility and 32 | reduces the amount of computations for conversions between incompatible coordinate systems and 33 | representations. 34 | It is recognized, however, that some applications may find the advised conventions unsuitable, 35 | in which case deviations are permitted. 36 | Any such deviations shall be explicitly documented. 37 | 38 | All coordinate systems defined in this section are right-handed. 39 | If application-specific coordinate systems are introduced, they should be right-handed as well. 40 | 41 | \begin{figure}[hbt] 42 | \centering 43 | % The source image is released under CC0, public domain, no attribution required: 44 | % https://commons.wikimedia.org/wiki/File:ECEF_ENU_Longitude_Latitude_relationships.svg 45 | \includegraphics[width=0.45\textwidth]{application/NED_ECEF} 46 | % The source image is released under CC0, public domain, no attribution required: 47 | % https://pixabay.com/en/airplane-plane-aircraft-propeller-40374/ 48 | % The final image is drawn by me. The source Inkscape SVG file is located in the same directory. 49 | \includegraphics[width=0.45\textwidth]{application/aircraft_principal_axes} 50 | North-East-Down (NED) frame and body frame conventions. All systems are right-handed. 51 | \caption{Coordinate frame conventions\label{fig:application_conventions_coordinate_frame}} 52 | \end{figure} 53 | 54 | \subsubsection{World frame} 55 | 56 | For world fixed frames, the \emph{North-East-Down} (NED) right-handed notation is preferred: 57 | X -- northward, Y -- eastward, Z -- downward. 58 | 59 | \subsubsection{Body frame} 60 | 61 | In relation to a body, the convention is as follows, right-handed\footnote{% 62 | This convention is widely used in aeronautic applications. 63 | }: 64 | X -- forward, Y -- rightward, Z -- downward. 65 | 66 | \subsubsection{Optical frame} 67 | 68 | In the case of cameras, the following right-handed convention is preferred\footnote{% 69 | This convention is widely used in various applications involving computer vision systems. 70 | }: 71 | X -- rightward, Y -- downward, Z -- towards the scene along the optical axis. 72 | 73 | \subsection{Rotation representation} 74 | 75 | All applications should represent rotations using quaternions with the elements ordered as follows\footnote{% 76 | Assuming $w + x\boldsymbol{i} + y\boldsymbol{j} + z\boldsymbol{k}$. 77 | }: W, X, Y, Z. 78 | Other forms of rotation representation should be avoided. 79 | 80 | Angular velocities should be represented using the right-handed, fixed-axis (extrinsic) convention: 81 | X (roll), Y (pitch), Z (yaw). 82 | 83 | \begin{remark} 84 | Quaternions are considered to offer the optimal trade-off between bandwidth efficiency, 85 | computation complexity, and explicitness: 86 | \begin{itemize} 87 | \item Euler angles are not self-contained, requiring applications to agree on a particular 88 | convention beforehand; a convention would be difficult to establish considering different 89 | demands of various use cases. 90 | 91 | \item Euler angles and fixed axis rotations typically cannot be used for computations directly 92 | due to angular interpolation issues and singularities; thus, to make use of such 93 | representations, one often has to convert them to a different form (e.g., quaternion); 94 | such conversions are computationally heavy. 95 | 96 | \item Rotation matrices are highly redundant. 97 | \end{itemize} 98 | \end{remark} 99 | 100 | \subsection{Matrix representation} 101 | 102 | \subsubsection{General} 103 | 104 | Matrices should be represented as flat arrays in the row-major order. 105 | 106 | \begin{remark} 107 | $ 108 | \begin{bmatrix} 109 | x_{11} & x_{12} & x_{13} \\ 110 | x_{21} & x_{22} & x_{23} \\ 111 | \end{bmatrix} \rightarrow \left(x_{11}, x_{12}, x_{13}, x_{21}, x_{22}, x_{23}\right) 112 | $ 113 | \end{remark} 114 | 115 | \subsubsection{Square matrices} 116 | 117 | There are standard compressed representations of an $n \times n$ square matrix. 118 | 119 | An array of size $n^2$ represents a full square matrix. 120 | This is equivalent to the general case reviewed above. 121 | 122 | An array of $\frac{(1 + n) n}{2}$ elements represents a symmetric matrix, 123 | where array members represent the elements of the upper-right triangle arranged in the row-major order. 124 | \begin{remark} 125 | $ 126 | \begin{bmatrix} 127 | a & b & c \\ 128 | b & d & e \\ 129 | c & e & f \\ 130 | \end{bmatrix} \rightarrow \left(a, b, c, d, e, f\right) 131 | $ 132 | 133 | This form is well-suited for covariance matrix representation. 134 | \end{remark} 135 | 136 | An array of $n$ elements represents a diagonal matrix, 137 | where an array member at position $i$ (where $i=1$ for the first element) 138 | represents the matrix element $x_{i, i}$ (where $x_{1, 1}$ is the upper-left element). 139 | \begin{remark} 140 | $ 141 | \begin{bmatrix} 142 | a & 0 & 0 \\ 143 | 0 & b & 0 \\ 144 | 0 & 0 & c \\ 145 | \end{bmatrix} \rightarrow \left(a, b, c\right) 146 | $ 147 | \end{remark} 148 | 149 | An array of one element represents a scalar matrix. 150 | \begin{remark} 151 | $ 152 | \begin{bmatrix} 153 | a & 0 & 0 \\ 154 | 0 & a & 0 \\ 155 | 0 & 0 & a \\ 156 | \end{bmatrix} \rightarrow a 157 | $ 158 | \end{remark} 159 | 160 | An empty array represents a zero matrix. 161 | 162 | \subsubsection{Covariance matrices} 163 | 164 | A zero covariance matrix represents an unknown covariance\footnote{% 165 | As described above, an empty array represents a zero matrix, 166 | from which follows that an empty array represents unknown covariance. 167 | }. 168 | 169 | Infinite error variance means that the associated value is undefined. 170 | 171 | \subsection{Physical quantity representation} 172 | 173 | \subsubsection{Units} 174 | 175 | All units should be SI\footnote{International System of Units.} units (base or derived). 176 | Usage of any other units is strongly discouraged. 177 | 178 | When defining data types, fields and constants that represent unscaled quantities in SI units 179 | should not have suffixes indicating the unit, since that would be redundant. 180 | 181 | On the other hand, fields and constants that contain quantities in 182 | non-SI units\footnote{E.g., degree Celsius instead of kelvin.} 183 | or scaled SI units\footnote{E.g., microsecond instead of second.} 184 | should be suffixed with the standard abbreviation of the unit\footnote{E.g., kg for kilogram, J for joule.} 185 | and its metric prefix\footnote{E.g., M for mega, n for nano.} 186 | (if any), maintaining the proper letter case of the abbreviation. 187 | In other words, the letter case of the suffix is independent of the letter case of 188 | the attribute it is attached to. 189 | 190 | Scaling coefficients should not be chosen arbitrarily; 191 | instead, the choice should be limited to the standard metric prefixes defined by the 192 | International System of Units. 193 | 194 | All standard metric prefixes have well-defined abbreviations that are constructed from ASCII characters, 195 | except for one: the micro prefix is abbreviated as a Greek letter ``\textmu{}'' (mu). 196 | When defining data types, ``\textmu{}'' should be replaced with the lowercase Latin letter ``u''. 197 | 198 | Irrespective of the suffix, it is recommended to always specify units for every field in the comments. 199 | 200 | \begin{remark} 201 | \begin{minted}{python} 202 | float16 temperature # [kelvin] Suffix not needed because an unscaled SI unit is used here. 203 | 204 | uint24 delay_us # [microsecond] Scaled SI unit, suffix required. Mu replaced with "u". 205 | uint24 MAX_DELAY_us = 600000 # [microsecond] Notice the letter case. 206 | 207 | float32 kinetic_energy_GJ # [gigajoule] Notice the letter case. 208 | 209 | float16 estimated_charge_mAh # [milliampere hour] Scaled non-SI unit. Discouraged, use coulomb. 210 | float16 MAX_CHARGE_mAh = 1e4 # [milliampere hour] Notice the letter case. 211 | \end{minted} 212 | \end{remark} 213 | 214 | \subsubsection{Enhanced type safety} 215 | 216 | In the interest of improving type safety and reducing the possibility of a human error, 217 | it is recommended to avoid reliance on raw scalar types (such as \verb|float32|) 218 | when defining fields containing physical quantities. 219 | Instead, the explicitly typed alternatives defined in the standard DSDL namespace 220 | \DSDLReference{uavcan.si.unit} (also see section~\ref{sec:application_functions_si}) should be used. 221 | 222 | \begin{remark} 223 | \begin{minted}{python} 224 | float32[4] kinetic_energy # [joule] Not recommended. 225 | uavcan.si.unit.energy.Scalar.1.0[4] kinetic_energy # This is the recommended practice. 226 | # Kinetic energy of four bodies. 227 | 228 | float32[3] velocity # [meter/second] Not recommended. 229 | uavcan.si.unit.velocity.Vector3.1.0 # This is the recommended practice. 230 | # 3D velocity vector. 231 | \end{minted} 232 | \end{remark} 233 | -------------------------------------------------------------------------------- /specification/application/requirements.tex: -------------------------------------------------------------------------------- 1 | \section{Application-level requirements}\label{sec:application_requirements} 2 | 3 | This section describes a set of high-level rules that shall be obeyed by all Cyphal implementations. 4 | 5 | \subsection{Port identifier distribution} 6 | 7 | An overview of related concepts is provided in chapter~\ref{sec:basic}. 8 | 9 | The subject and service identifier values are segregated into three ranges: 10 | \begin{itemize} 11 | \item unregulated port identifiers that can be freely chosen by users and integrators (both fixed and non-fixed); 12 | \item regulated fixed identifiers for non-standard data type definitions 13 | that are assigned by the Cyphal maintainers for publicly released data types; 14 | \item regulated identifiers of the standard data types that are an integral part of the Cyphal specification. 15 | \end{itemize} 16 | 17 | More information on the subject of data type regulation is provided in section~\ref{sec:basic_data_type_regulation}. 18 | 19 | The ranges are summarized in table~\ref{table:application_requirements_port_id_distribution}. 20 | The ranges may be expanded, but not contracted, in a future version of the document. 21 | 22 | \begin{CyphalSimpleTable}{Port identifier distribution}{|l l X|}% 23 | \label{table:application_requirements_port_id_distribution} 24 | Subject-ID & Service-ID & Purpose \\ 25 | $[0, 6143]$ & $[0, 255]$ & Unregulated identifiers (both fixed and non-fixed). \\ 26 | $[6144, 7167]$ & $[256, 383]$ & Non-standard fixed regulated identifiers (i.e., vendor-specific). \\ 27 | $[7168, 8191]$ & $[384, 511]$ & Standard fixed regulated identifiers. \\ 28 | \end{CyphalSimpleTable} 29 | 30 | \subsection{Port compatibility} 31 | 32 | % https://github.com/OpenCyphal/specification/pull/64#discussion_r357771739 33 | 34 | The system integrator shall ensure that nodes participating in data exchange via a given port\footnote{% 35 | I.e., subject or service. 36 | } use data type definitions that are sufficiently congruent so that the resulting behavior of the involved nodes 37 | is predictable and the possibility of unintended behaviors caused by misinterpretation of exchanged serialized 38 | objects is eliminated. 39 | 40 | \begin{remark} 41 | Let there be type $A$: 42 | 43 | \begin{minted}{python} 44 | void1 45 | uint7 demand_factor_pct # [percent] 46 | # Values above 100% are not allowed. 47 | \end{minted} 48 | 49 | And type $B$: 50 | 51 | \begin{minted}{python} 52 | uint8 demand_factor_pct # [percent] 53 | # Values above 100% indicate overload. 54 | \end{minted} 55 | 56 | The data types are not semantically compatible, but they can be used on the same subject nevertheless: 57 | a subscriber expecting $B$ can accept $A$. 58 | The reverse is not true, however. 59 | 60 | This example shows that even semantically incompatible types can facilitate 61 | behaviorally correct interoperability of nodes. 62 | \end{remark} 63 | 64 | \begin{remark} 65 | Compatibility of subjects and services is completely independent from the names of the involved data types. 66 | Data types can be moved between namespaces and freely renamed and re-versioned 67 | without breaking compatibility with existing deployments. 68 | Nodes provided by different vendors that utilize differently named data types may 69 | still interoperate if such data types happen to be compatible. 70 | The duty of ensuring the compatibility lies on the system integrator. 71 | \end{remark} 72 | 73 | \subsection{Standard namespace} 74 | 75 | An overview of related concepts is provided in chapter~\ref{sec:dsdl}. 76 | 77 | This specification defines a set of standard regulated DSDL data types located under 78 | the root namespace named ``\verb"uavcan"''% 79 | \footnote{The standard root namespace is named \texttt{uavcan}, not \texttt{cyphal}, for historical reasons.} 80 | (section~\ref{sec:sdt}). 81 | 82 | Vendor-specific, user-specific, or any other data types not defined by this specification 83 | shall not be defined inside the standard root namespace\footnote{Custom data type definitions shall be located 84 | inside vendor-specific or user-specific namespaces instead.}. 85 | -------------------------------------------------------------------------------- /specification/basic/basic.tex: -------------------------------------------------------------------------------- 1 | \chapter{Basic concepts}\label{sec:basic} 2 | 3 | \section{Main principles} 4 | 5 | \subsection{Communication} 6 | 7 | \subsubsection{Architecture} 8 | 9 | A Cyphal network is a decentralized peer network, where each peer (node) has a unique 10 | numeric identifier\footnote{% 11 | Here and elsewhere in this specification, \emph{ID} and \emph{identifier} are used 12 | interchangeably unless specifically indicated otherwise. 13 | } --- \emph{node-ID} --- ranging from 0 up to a transport-specific upper boundary which is guaranteed to be 14 | not less than 127. 15 | Nodes of a Cyphal network can communicate using the following communication methods: 16 | 17 | \begin{description} 18 | \item[Message publication] --- The primary method of data exchange with one-to-many publish/subscribe semantics. 19 | \item[Service invocation] --- The communication method for one-to-one request/response 20 | interactions\footnote{Like remote procedure call (RPC).}. 21 | \end{description} 22 | 23 | For each type of communication, a predefined set of data types is used, 24 | where each data type has a unique name. 25 | Additionally, every data type definition has a pair of major and minor version numbers, 26 | which enable data type definitions to evolve in arbitrary ways while ensuring a well-defined 27 | migration path if backward-incompatible changes are introduced. 28 | Some data types are standard and defined by the protocol specification (of which only a small 29 | subset are required); others may be specific to a particular application or vendor. 30 | 31 | \subsubsection{Subjects and services}\label{sec:basic_subjects_and_services} 32 | 33 | Message exchanges between nodes are grouped into \emph{subjects} by the semantic meaning of the message. 34 | Message exchanges belonging to the same subject pertain to the same function or process within the system. 35 | 36 | Request/response exchanges between nodes are grouped into \emph{services} by the semantic meaning 37 | of the request and response, like messages are grouped into subjects. 38 | Requests and their corresponding responses that belong to the same service pertain to 39 | the same function or process within the system. 40 | 41 | Each message subject is identified by a unique natural number -- a \emph{subject-ID}; 42 | likewise, each service is identified by a unique \emph{service-ID}. 43 | An umbrella term \emph{port-ID} is used to refer either to a subject-ID or to a service-ID 44 | (port identifiers have no direct manifestation in the construction of the protocol, 45 | but they are convenient for discussion). 46 | The sets of subject-ID and service-ID are orthogonal. 47 | 48 | Port identifiers are assigned to various functions, processes, or data streams within the network 49 | at the system definition time. 50 | Generally, a port identifier can be selected arbitrarily by a system integrator 51 | by changing relevant configuration parameters of connected nodes, 52 | in which case such port identifiers are called \emph{non-fixed port identifiers}. 53 | It is also possible to permanently associate any data type definition with a particular port identifier 54 | at a data type definition time, 55 | in which case such port identifiers are called \emph{fixed port identifiers}; 56 | their usage is governed by rules and regulations described in later sections. 57 | 58 | A port-ID used in a given Cyphal network shall not be shared between functions, processes, or data streams 59 | that have different semantic meaning. 60 | 61 | A data type of a given major version can be used simultaneously with 62 | an arbitrary number of non-fixed different port identifiers, 63 | but not more than one fixed port identifier. 64 | 65 | \subsection{Data types} 66 | 67 | \subsubsection{Data type definitions} 68 | 69 | Message and service types 70 | are defined using the \emph{data structure description language} (DSDL) (chapter~\ref{sec:dsdl}). 71 | A DSDL definition specifies the name, major version, minor version, attributes, 72 | and an optional fixed port-ID of the data type among other less important properties. 73 | Service types define two inner data types: one for request, and the other for response. 74 | 75 | \subsubsection{Regulation}\label{sec:basic_data_type_regulation} 76 | 77 | Data type definitions can be created by the Cyphal specification maintainers or by its users, 78 | such as equipment vendors or application designers. 79 | Irrespective of the origin, data types can be included into the set of data type definitions maintained 80 | and distributed by the Cyphal specification maintainers; 81 | definitions belonging to this set are termed \emph{regulated data type definitions}. 82 | The specification maintainers undertake to keep regulated definitions well-maintained and may occasionally 83 | amend them and release new versions, if such actions are believed to benefit the protocol. 84 | User-created (i.e., vendor-specific or application-specific) data type definitions that are 85 | not included into the aforementioned set are called \emph{unregulated data type definitions}. 86 | 87 | Unregulated definitions that are made available for reuse by others are called 88 | \emph{unregulated public data type definitions}; 89 | those that are kept closed-source for private use by their authors are called 90 | \emph{(unregulated) private data type definitions}\footnote{% 91 | The word ``unregulated'' is redundant because private data types cannot be regulated, by definition. 92 | Likewise, all regulated definitions are public, so the word ``public'' can be omitted. 93 | }. 94 | 95 | Data type definitions authored by the specification maintainers for the purpose of supporting and advancing 96 | this specification are called \emph{standard data type definitions}. 97 | All standard data type definitions are regulated. 98 | 99 | Fixed port identifiers can be used only with regulated data type definitions or with private definitions. 100 | Fixed port identifiers shall not be used with public unregulated data types, 101 | since that is likely to cause unresolvable port identifier collisions\footnote{% 102 | Any system that relies on data type definitions with fixed port identifiers provided by 103 | an external party (i.e., data types and the system in question are designed by different parties) 104 | runs the risk of encountering port identifier conflicts that cannot be resolved without resorting to help 105 | from said external party since the designers of the system do not have control over their fixed port identifiers. 106 | Because of this, the specification strongly discourages the use of fixed unregulated private port identifiers. 107 | If a data type definition is ever disclosed to any other party (i.e., a party that did not author it) 108 | or to the public at large it is important that the data type \emph{not} include a fixed port-identifier. 109 | }. 110 | This restriction shall be followed at all times by all compliant implementations and 111 | systems\footnote{% 112 | In general, private unregulated fixed port identifiers are collision-prone by their nature, so they should 113 | be avoided unless there are very strong reasons for their usage and the authors fully understand the risks. 114 | }. 115 | 116 | \begin{CyphalSimpleTable}{Data type taxonomy}{|l|X|X|} 117 | & Regulated & Unregulated \\ 118 | \bfseries{Public} 119 | & 120 | Standard and contributed (e.g., vendor-specific) definitions.\newline 121 | Fixed port identifiers are allowed; they are called \emph{regulated port-ID}. 122 | & 123 | Definitions distributed separately from the Cyphal specification.\newline 124 | Fixed port identifiers are \emph{not allowed}. 125 | \\ 126 | 127 | \bfseries{Private} 128 | & 129 | Nonexistent category. 130 | & 131 | Definitions that are not available to anyone except their authors.\newline 132 | Fixed port identifiers are permitted (although not recommended); 133 | they are called \emph{unregulated fixed port-ID}. 134 | \\ 135 | \end{CyphalSimpleTable} 136 | 137 | DSDL processing tools shall prohibit unregulated fixed port identifiers by default, 138 | unless they are explicitly configured otherwise. 139 | 140 | Each of the two sets of port identifiers (which are subject identifiers and service identifiers) are 141 | segregated into three categories: 142 | 143 | \begin{itemize} 144 | \item Application-specific port identifiers. 145 | These can be assigned by changing relevant configuration parameters of the connected nodes 146 | (in which case they are called \emph{non-fixed}), 147 | or at the data type definition time (in which case they are called \emph{fixed unregulated}, 148 | and they generally should be avoided due to the risks of collisions as explained earlier). 149 | 150 | \item Regulated non-standard fixed port identifiers. 151 | These are assigned by the specification maintainers for non-standard contributed 152 | vendor-specific public data types. 153 | 154 | \item Standard fixed port identifiers. These are assigned by the specification maintainers 155 | for standard regulated public data types. 156 | \end{itemize} 157 | 158 | Data type authors that want to release regulated data type definitions or contribute to the standard data 159 | type set should contact the Cyphal maintainers for coordination. 160 | The maintainers will choose unoccupied fixed port identifiers for use with the new definitions, if necessary. 161 | Since the set of regulated definitions is maintained in a highly centralized manner, 162 | it can be statically ensured that no identifier collisions will take place within it; 163 | also, since the identifier ranges used with regulated definitions are segregated, 164 | regulated port-IDs will not conflict with any other compliant Cyphal node or system\footnote{% 165 | The motivation for the prohibition of fixed port identifiers in unregulated public data types is 166 | derived directly from the above: since there is no central repository of unregulated definitions, 167 | collisions would be likely. 168 | }. 169 | 170 | \subsubsection{Serialization} 171 | 172 | A DSDL description can be used to automatically generate the serialization and deserialization code 173 | for every defined data type in a particular programming language. 174 | Alternatively, a DSDL description can be used to construct appropriate serialization code manually by a human. 175 | DSDL ensures that the memory footprint and computational complexity per data type 176 | are constant and easily predictable. 177 | 178 | Serialized message and service objects\footnote{% 179 | An \emph{object} means a value that is an instance of a well-defined type. 180 | } 181 | are exchanged by means of the transport layer (chapter~\ref{sec:transport}), 182 | which implements automatic decomposition of long transfers into several transport frames\footnote{% 183 | A \emph{transport frame} means a block of data that can be atomically exchanged over the transport layer network, 184 | e.g., a CAN frame. 185 | } and reassembly from these transport frames 186 | back into a single atomic data block, allowing nodes to exchange serialized objects of 187 | arbitrary size (DSDL guarantees, however, that the minimum and maximum size of the serialized representation 188 | of any object of any data type is always known statically). 189 | 190 | \subsection{High-level functions} 191 | 192 | On top of the standard data types, Cyphal defines a set of standard high-level functions including: 193 | node health monitoring, node discovery, time synchronization, firmware update, 194 | plug-and-play node support, and more (section~\ref{sec:application_functions}). 195 | 196 | \begin{figure}[hbt] 197 | \centering 198 | \begin{tabular}{|c|c|l|c|l|c|} 199 | \hline 200 | \multicolumn{6}{|c|}{Applications} \\ \hline 201 | 202 | \qquad{} & Required functions & 203 | \qquad{} & Standard functions & 204 | \qquad{} & Custom functions \\ 205 | \cline{2-2} \cline{4-4} \cline{6-6} 206 | 207 | \multicolumn{2}{|c|}{Required data types} & 208 | \multicolumn{2}{c|}{Standard data types} & 209 | \multicolumn{2}{c|}{Custom data types} \\ \hline 210 | 211 | \multicolumn{6}{|c|}{Serialization} \\ \hline 212 | 213 | \multicolumn{6}{|c|}{Transport} \\ \hline 214 | \end{tabular} 215 | \caption{Cyphal architectural diagram\label{fig:basic_architecture}} 216 | \end{figure} 217 | 218 | \section{Message publication} 219 | 220 | Message publication refers to the transmission of a serialized message object over the network to other nodes. 221 | This is the primary data exchange mechanism used in Cyphal; 222 | it is functionally similar to raw data exchange with minimal overhead, 223 | additional communication integrity guarantees, and automatic decomposition and reassembly of long payloads 224 | across multiple transport frames. 225 | Typical use cases may include transfer of the following kinds of data (either cyclically or on an ad-hoc basis): 226 | sensor measurements, actuator commands, equipment status information, and more. 227 | 228 | Information contained in a published message is summarized in table~\ref{table:basic_message}. 229 | 230 | \begin{CyphalSimpleTable}{Published message properties}{|l X|}\label{table:basic_message} 231 | Property & Description \\ 232 | Payload & The serialized message object. \\ 233 | Subject-ID & Numerical identifier that indicates how the payload should be interpreted. \\ 234 | Source node-ID & The node-ID of the transmitting node (excepting anonymous messages). \\ 235 | Transfer-ID & An integer value that is used for message sequence monitoring, 236 | multi-frame transfer reassembly, deduplication, automatic management of redundant transports, 237 | and other purposes (section~\ref{sec:transport_transfer_id}). \\ 238 | \end{CyphalSimpleTable} 239 | 240 | \subsection{Anonymous message publication} 241 | 242 | Nodes that don't have a unique node-ID can publish only \emph{anonymous messages}. 243 | An anonymous message is different from a regular message in that it doesn't contain a source node-ID. 244 | 245 | Cyphal nodes will not have an identifier initially until they are assigned one, 246 | either statically (which is generally the preferred option for applications where a high degree of 247 | determinism and high safety assurances are required) or automatically (i.e., plug-and-play). 248 | Anonymous messages are used to facilitate the plug-and-play function (section~\ref{sec:application_functions_pnp}). 249 | 250 | \section{Service invocation} 251 | 252 | Service invocation is a two-step data exchange operation between exactly two nodes: a client and a server. 253 | The steps are\footnote{% 254 | The request/response semantic is facilitated by means of hardware (if available) 255 | or software acceptance filtering and higher-layer logic. 256 | No additional support or non-standard transport layer features are required. 257 | }: 258 | 259 | \begin{enumerate} 260 | \item The client sends a service request to the server. 261 | \item The server takes appropriate actions and sends a response to the client. 262 | \end{enumerate} 263 | 264 | Typical use cases for this type of communication include: 265 | node configuration parameter update, firmware update, an ad-hoc action request, file transfer, 266 | and other functions of similar nature. 267 | 268 | Information contained in service requests and responses is summarized in table~\ref{table:basic_service}. 269 | Both the request and the response contain same values for all listed fields except payload, 270 | where the content is application-defined. 271 | 272 | \begin{CyphalSimpleTable}{Service request/response properties}{|l X|}\label{table:basic_service} 273 | Property & Description \\ 274 | Payload & The serialized request/response object. \\ 275 | Service-ID & Numerical identifier that indicates how the service should be handled. \\ 276 | Client node-ID & Source node-ID during request transfer, destination node-ID during response transfer. \\ 277 | Server node-ID & Destination node-ID during request transfer, source node-ID during response transfer. \\ 278 | Transfer-ID & An integer value that is used for request/response matching, 279 | multi-frame transfer reassembly, deduplication, automatic management of redundant transports, 280 | and other purposes (section~\ref{sec:transport_transfer_id}). \\ 281 | \end{CyphalSimpleTable} 282 | -------------------------------------------------------------------------------- /specification/cyphal_logo.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-3.0 2 | %%Creator: cairo 1.17.4 (https://cairographics.org) 3 | %%CreationDate: Mon Apr 11 23:51:10 2022 4 | %%Pages: 1 5 | %%DocumentData: Clean7Bit 6 | %%LanguageLevel: 2 7 | %%BoundingBox: 0 0 1189 383 8 | %%EndComments 9 | %%BeginProlog 10 | 50 dict begin 11 | /q { gsave } bind def 12 | /Q { grestore } bind def 13 | /cm { 6 array astore concat } bind def 14 | /w { setlinewidth } bind def 15 | /J { setlinecap } bind def 16 | /j { setlinejoin } bind def 17 | /M { setmiterlimit } bind def 18 | /d { setdash } bind def 19 | /m { moveto } bind def 20 | /l { lineto } bind def 21 | /c { curveto } bind def 22 | /h { closepath } bind def 23 | /re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto 24 | 0 exch rlineto 0 rlineto closepath } bind def 25 | /S { stroke } bind def 26 | /f { fill } bind def 27 | /f* { eofill } bind def 28 | /n { newpath } bind def 29 | /W { clip } bind def 30 | /W* { eoclip } bind def 31 | /BT { } bind def 32 | /ET { } bind def 33 | /BDC { mark 3 1 roll /BDC pdfmark } bind def 34 | /EMC { mark /EMC pdfmark } bind def 35 | /cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def 36 | /Tj { show currentpoint cairo_store_point } bind def 37 | /TJ { 38 | { 39 | dup 40 | type /stringtype eq 41 | { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse 42 | } forall 43 | currentpoint cairo_store_point 44 | } bind def 45 | /cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore 46 | cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def 47 | /Tf { pop /cairo_font exch def /cairo_font_matrix where 48 | { pop cairo_selectfont } if } bind def 49 | /Td { matrix translate cairo_font_matrix matrix concatmatrix dup 50 | /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point 51 | /cairo_font where { pop cairo_selectfont } if } bind def 52 | /Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def 53 | cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def 54 | /g { setgray } bind def 55 | /rg { setrgbcolor } bind def 56 | /d1 { setcachedevice } bind def 57 | /cairo_data_source { 58 | CairoDataIndex CairoData length lt 59 | { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } 60 | { () } ifelse 61 | } def 62 | /cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def 63 | /cairo_image { image cairo_flush_ascii85_file } def 64 | /cairo_imagemask { imagemask cairo_flush_ascii85_file } def 65 | %%EndProlog 66 | %%BeginSetup 67 | %%EndSetup 68 | %%Page: 1 1 69 | %%BeginPageSetup 70 | %%PageBoundingBox: 0 0 1189 383 71 | %%EndPageSetup 72 | q 0 0 1189 383 rectclip 73 | 1 0 0 -1 0 383 cm q 74 | 0.0901961 0.0352941 0.701961 rg 75 | 201.215 82.176 m 191.23 71.426 181.566 64.258 172.223 60.672 c 162.879 76 | 57.09 153.473 55.297 144 55.297 c 129.918 55.297 117.184 57.793 105.793 77 | 62.785 c 94.398 67.777 84.609 74.688 76.414 83.52 c 68.223 92.352 61.887 78 | 102.656 57.406 114.434 c 52.93 126.207 50.688 138.879 50.688 152.449 c 79 | 50.688 167.039 52.93 180.48 57.406 192.77 c 61.887 205.055 68.223 215.68 80 | 76.414 224.641 c 84.609 233.602 94.398 240.641 105.793 245.762 c 117.184 81 | 250.879 129.918 253.441 144 253.441 c 155.008 253.441 165.695 250.816 176.062 82 | 245.566 c 186.434 240.32 196.098 231.938 205.055 220.418 c 244.992 248.832 83 | l 232.703 265.727 217.727 278.016 200.062 285.695 c 182.398 293.375 163.586 84 | 297.215 143.617 297.215 c 122.625 297.215 103.359 293.824 85.824 287.039 85 | c 68.289 280.258 53.184 270.656 40.512 258.238 c 27.84 245.824 17.922 230.914 86 | 10.754 213.504 c 3.582 196.098 0 176.77 0 155.52 c 0 133.762 3.582 113.984 87 | 10.754 96.191 c 17.922 78.398 27.84 63.23 40.512 50.688 c 53.184 38.145 88 | 68.289 28.48 85.824 21.695 c 103.359 14.91 122.625 11.52 143.617 11.52 89 | c 162.047 11.52 179.137 14.785 194.879 21.312 c 210.625 27.84 225.281 38.91 90 | 238.848 54.527 c h 91 | 201.215 82.176 m f 92 | 248.449 105.984 m 299.137 105.984 l 350.594 233.855 l 351.359 233.855 l 93 | 397.441 105.984 l 445.441 105.984 l 358.273 329.855 l 354.945 338.559 351.297 94 | 346.176 347.328 352.703 c 343.359 359.23 338.688 364.734 333.312 369.215 95 | c 327.938 373.695 321.602 377.023 314.305 379.199 c 307.008 381.375 298.238 96 | 382.465 288 382.465 c 275.969 382.465 264.191 380.93 252.672 377.855 c 97 | 258.434 336.383 l 262.016 337.664 265.793 338.754 269.762 339.648 c 273.727 98 | 340.543 277.762 340.992 281.855 340.992 c 287.488 340.992 292.223 340.48 99 | 296.062 339.457 c 299.902 338.434 303.168 336.832 305.855 334.656 c 308.543 100 | 332.48 310.785 329.664 312.574 326.207 c 314.367 322.754 316.289 318.594 101 | 318.336 313.727 c 327.168 291.84 l h 102 | 248.449 105.984 m f 103 | 472.703 105.984 m 516.48 105.984 l 516.48 133.633 l 517.246 133.633 l 523.902 104 | 122.367 532.863 114.176 544.129 109.055 c 555.391 103.938 567.551 101.375 105 | 580.609 101.375 c 594.688 101.375 607.359 103.871 618.625 108.863 c 629.887 106 | 113.855 639.488 120.703 647.426 129.406 c 655.359 138.113 661.375 148.352 107 | 665.473 160.129 c 669.566 171.902 671.617 184.574 671.617 198.145 c 671.617 108 | 211.711 669.441 224.383 665.09 236.16 c 660.734 247.938 654.656 258.176 109 | 646.848 266.879 c 639.039 275.586 629.633 282.434 618.625 287.426 c 607.617 110 | 292.418 595.586 294.91 582.527 294.91 c 573.824 294.91 566.145 294.016 111 | 559.488 292.223 c 552.832 290.434 546.945 288.129 541.824 285.312 c 536.703 112 | 282.496 532.352 279.488 528.77 276.289 c 525.184 273.09 522.238 269.953 113 | 519.938 266.879 c 518.785 266.879 l 518.785 377.855 l 472.703 377.855 l 114 | h 115 | 625.535 198.145 m 625.535 190.977 624.32 184.062 621.887 177.406 c 619.457 116 | 170.754 615.871 164.863 611.137 159.742 c 606.398 154.625 600.703 150.527 117 | 594.047 147.457 c 587.391 144.383 579.84 142.848 571.391 142.848 c 562.945 118 | 142.848 555.391 144.383 548.734 147.457 c 542.078 150.527 536.383 154.625 119 | 531.648 159.742 c 526.91 164.863 523.328 170.754 520.895 177.406 c 518.465 120 | 184.062 517.246 190.977 517.246 198.145 c 517.246 205.312 518.465 212.223 121 | 520.895 218.879 c 523.328 225.535 526.91 231.426 531.648 236.543 c 536.383 122 | 241.664 542.078 245.762 548.734 248.832 c 555.391 251.902 562.945 253.441 123 | 571.391 253.441 c 579.84 253.441 587.391 251.902 594.047 248.832 c 600.703 124 | 245.762 606.398 241.664 611.137 236.543 c 615.871 231.426 619.457 225.535 125 | 621.887 218.879 c 624.32 212.223 625.535 205.312 625.535 198.145 c h 126 | 625.535 198.145 m f 127 | 760.703 131.711 m 761.473 131.711 l 765.055 124.031 771.391 117.055 780.48 128 | 110.785 c 789.566 104.512 801.281 101.375 815.617 101.375 c 827.902 101.375 129 | 838.336 103.426 846.91 107.52 c 855.488 111.617 862.465 116.992 867.84 130 | 123.648 c 873.215 130.305 877.055 137.984 879.359 146.688 c 881.664 155.391 131 | 882.816 164.48 882.816 173.953 c 882.816 290.305 l 836.734 290.305 l 836.734 132 | 196.992 l 836.734 191.871 836.48 186.176 835.969 179.902 c 835.457 173.633 133 | 834.113 167.742 831.938 162.238 c 829.762 156.734 826.367 152.129 821.762 134 | 148.418 c 817.152 144.703 810.879 142.848 802.945 142.848 c 795.266 142.848 135 | 788.801 144.129 783.551 146.688 c 778.305 149.246 773.953 152.703 770.496 136 | 157.055 c 767.039 161.406 764.543 166.398 763.008 172.031 c 761.473 177.664 137 | 760.703 183.551 760.703 189.695 c 760.703 290.305 l 714.625 290.305 l 714.625 138 | 0 l 760.703 0 l h 139 | 760.703 131.711 m f 140 | 1050.238 264.961 m 1049.09 264.961 l 1042.434 275.457 1033.984 283.07 1023.742 141 | 287.809 c 1013.504 292.543 1002.238 294.91 989.953 294.91 c 981.504 294.91 142 | 973.246 293.762 965.184 291.457 c 957.121 289.152 949.953 285.695 943.68 143 | 281.09 c 937.406 276.48 932.352 270.719 928.512 263.809 c 924.672 256.895 144 | 922.754 248.832 922.754 239.617 c 922.754 229.633 924.543 221.121 928.129 145 | 214.078 c 931.711 207.039 936.512 201.152 942.527 196.418 c 948.543 191.68 146 | 955.52 187.902 963.457 185.09 c 971.391 182.273 979.648 180.16 988.223 147 | 178.754 c 996.801 177.344 1005.441 176.449 1014.145 176.062 c 1022.848 175.68 148 | 1031.039 175.488 1038.719 175.488 c 1050.238 175.488 l 1050.238 170.496 149 | l 1050.238 158.977 1046.273 150.336 1038.336 144.574 c 1030.398 138.816 150 | 1020.289 135.938 1008 135.938 c 998.273 135.938 989.184 137.664 980.734 151 | 141.121 c 972.289 144.574 964.992 149.246 958.848 155.137 c 934.656 130.945 152 | l 944.895 120.449 956.863 112.895 970.559 108.289 c 984.258 103.68 998.398 153 | 101.375 1012.992 101.375 c 1026.047 101.375 1037.055 102.848 1046.016 105.793 154 | c 1054.977 108.734 1062.398 112.512 1068.289 117.121 c 1074.176 121.727 155 | 1078.719 127.039 1081.922 133.055 c 1085.121 139.07 1087.426 145.152 1088.832 156 | 151.297 c 1090.238 157.441 1091.07 163.391 1091.328 169.152 c 1091.582 157 | 174.91 1091.711 179.969 1091.711 184.32 c 1091.711 290.305 l 1050.238 290.305 158 | l h 159 | 1047.551 207.742 m 1037.953 207.742 l 1031.551 207.742 1024.383 208 1016.449 160 | 208.512 c 1008.512 209.023 1001.023 210.238 993.984 212.16 c 986.945 214.078 161 | 980.992 216.895 976.129 220.609 c 971.266 224.32 968.832 229.504 968.832 162 | 236.16 c 968.832 240.512 969.793 244.16 971.711 247.105 c 973.633 250.047 163 | 976.129 252.543 979.199 254.594 c 982.273 256.641 985.727 258.113 989.566 164 | 259.008 c 993.406 259.902 997.246 260.352 1001.09 260.352 c 1016.961 260.352 165 | 1028.672 256.574 1036.223 249.023 c 1043.777 241.473 1047.551 231.168 1047.551 166 | 218.113 c h 167 | 1047.551 207.742 m f 168 | 1142.016 0 46.082 290.305 re f 169 | Q Q 170 | showpage 171 | %%Trailer 172 | end 173 | %%EOF 174 | -------------------------------------------------------------------------------- /specification/cyphal_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 36 | 38 | 42 | 46 | 47 | 51 | 55 | 56 | 60 | 64 | 65 | 69 | 73 | 74 | 78 | 82 | 83 | 87 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /specification/cyphaldoc.cls: -------------------------------------------------------------------------------- 1 | % 2 | % Copyright (c) 2018-2019 OpenCyphal Development Team 3 | % 4 | % Author: Pavel Kirienko 5 | % 6 | 7 | \NeedsTeXFormat{LaTeX2e} 8 | 9 | \ProvidesClass{cyphaldoc}[2018/06/29 Cyphal document class] 10 | 11 | \LoadClass[a4paper,onecolumn,openany]{book} 12 | 13 | \author{OpenCyphal Development Team} 14 | 15 | \RequirePackage[pagestyles]{titlesec} 16 | \RequirePackage{titletoc} 17 | \RequirePackage[table,xcdraw]{xcolor} 18 | \RequirePackage{gensymb} 19 | \RequirePackage{graphicx} 20 | \RequirePackage{hyperref} 21 | \RequirePackage{enumitem} 22 | \RequirePackage{multicol} 23 | \RequirePackage{etoolbox} 24 | \RequirePackage{amstext} 25 | \RequirePackage[detect-all]{siunitx} 26 | \RequirePackage[font={bf},hypcap=false]{caption} 27 | \RequirePackage{threeparttablex} 28 | \RequirePackage{tabu} 29 | \RequirePackage{makecell} 30 | \RequirePackage{longtable} 31 | \RequirePackage{ifthen} 32 | \RequirePackage{calc} 33 | \RequirePackage{titling} 34 | \RequirePackage[yyyymmdd]{datetime} 35 | \RequirePackage{lastpage} 36 | \RequirePackage{minted} 37 | \RequirePackage{chngcntr} 38 | \RequirePackage{changepage} 39 | \RequirePackage{csquotes} 40 | \RequirePackage{xparse} 41 | \usepackage[most]{tcolorbox} 42 | 43 | % 44 | % Minor definitions. 45 | % 46 | % OpenCyphal color palette: #1700b3 (logo color), #0003ee, #00dac6, #007e87, #b00036 #fc6d09 47 | % Source: https://forum.opencyphal.org/t/cyphal-logo-palooza/1626/27?u=pavel.kirienko 48 | \definecolor{colorlogo}{HTML}{1700B3} % from the palette 49 | \definecolor{colorhyperlink}{HTML}{0003EE} % from the palette 50 | \definecolor{colorremarkbg}{HTML}{E6F2FF} 51 | \definecolor{colorremarkframe}{HTML}{6669FF} % lightened 0003ee 52 | 53 | \renewcommand{\dateseparator}{-} 54 | 55 | \sisetup{range-phrase = \text{--}} 56 | 57 | \newcommand\CyphalCopyright{\copyright{} 2015--\the\year{} \href{http://opencyphal.org}{\@author}} 58 | 59 | % Deferring configuration of the PDF metadata until the point where the document title (and author) are known. 60 | \preto\frontmatter{\hypersetup{ 61 | pdftitle={\@title{} -- \@author}, 62 | pdfauthor={\@author} 63 | }} 64 | 65 | % Source code listings highlighting 66 | \usemintedstyle{vs} 67 | \setminted{ 68 | frame=leftline, 69 | linenos, 70 | numberblanklines=false, 71 | fontsize=\footnotesize, 72 | xleftmargin=\dimexpr\leftskip-2.15mm\relax, 73 | framesep=2mm, 74 | baselinestretch=1, 75 | autogobble 76 | } 77 | % The Pygments library is just too smart. 78 | % We don't want it to highlight errors in our listings because our listings are obviously perfect. 79 | % https://github.com/gpoore/minted/issues/69 80 | \AtBeginEnvironment{minted}{\renewcommand{\fcolorbox}[4][]{#4}} 81 | \preto\inputminted{\renewcommand{\fcolorbox}[4][]{#4}} 82 | 83 | \renewcommand{\theFancyVerbLine}{\scriptsize \texttt \oldstylenums{\arabic{FancyVerbLine}}} 84 | 85 | % List styling 86 | \renewcommand{\labelitemi}{\textbullet} 87 | \renewcommand{\labelitemii}{\textbullet} 88 | \renewcommand{\labelitemiii}{\textbullet} 89 | \renewcommand{\labelitemiv}{\textbullet} 90 | 91 | \setlist[itemize,2]{leftmargin=2em} 92 | \setlist[itemize,3]{leftmargin=3em} 93 | \setlist[itemize,4]{leftmargin=4em} 94 | 95 | \setlist[description]{leftmargin=\leftskip,labelindent=\dimexpr\leftskip+\parindent\relax} 96 | \setlist[enumerate]{itemindent=0ex,leftmargin=\leftskip+1.4em,nosep} 97 | \setlist[itemize]{itemindent=0ex,leftmargin=\leftskip+1em,nosep} 98 | 99 | % Remark formatting. 100 | % Use with \begin{remark}[breakable] to make it breakable across multiple pages. 101 | % By default, the remark will be non-breakable. 102 | % 103 | % STYLE RULE: 104 | % SECTIONS THAT CONTAIN ONLY REMARKS ARE TO BE AVOIDED. 105 | % A remark is an optional part of the document. The text should make sense even if all remarks were to be 106 | % completely removed. For example, the following pattern should be avoided, because if we were to ignore 107 | % the remark, we'd end up with an empty section, which doesn't make sense: 108 | % 109 | % \section{My section} 110 | % \begin{remark} 111 | % This is a remark, meaning that this text is not very important. 112 | % \end{remark} 113 | % 114 | % Instead, try to reformulate things so that the section would still make sense without the remark: 115 | % 116 | % \section{My section} 117 | % Kill-o-Zap is to be a dangerous weapon. 118 | % \begin{remark} 119 | % Make it totally clear that this gun has a right end and a wrong end. 120 | % Make it totally clear to anyone standing at the wrong end that things are going badly for them. 121 | % This is not a gun for hanging over the fireplace or sticking in the umbrella stand, 122 | % it is a gun for going out and making people miserable with. 123 | % \end{remark} 124 | \newenvironment{remark}[1][unbreakable]{ 125 | % Disable overfull h-box warning 126 | % See https://tex.stackexchange.com/questions/13715/how-to-suppress-overfull-hbox-warnings-up-to-some-maximum 127 | \hfuzz=1em 128 | \begin{tcolorbox}[ 129 | size=normal, 130 | left=1mm, 131 | right=1mm, 132 | top=1mm, 133 | bottom=1mm, 134 | colback=colorremarkbg, 135 | colframe=colorremarkframe, 136 | boxrule=0.5pt, 137 | toprule at break=0pt, 138 | bottomrule at break=0pt, 139 | sharp corners, 140 | width=\textwidth-\leftskip, 141 | enlarge top initially by=-1mm, 142 | #1 143 | ] 144 | \setlength{\parskip}{\DefaultParskip} 145 | }{ 146 | \end{tcolorbox} 147 | \hfuzz=0em % Restore strict overflow warning 148 | } 149 | 150 | % Continuous footnote numbering 151 | \counterwithout{footnote}{chapter} 152 | 153 | % Discourage carrying a footnote to the next page 154 | \interfootnotelinepenalty=1000 155 | 156 | % We don't need to clear double page, ever. Shall the need arise, we'll have to implement a cleaner fix. 157 | \renewcommand{\cleardoublepage}{\clearpage} 158 | 159 | % 160 | % Font specification. 161 | % 162 | \RequirePackage[T1]{fontenc} 163 | \RequirePackage{fourier} % Main font: Utopia Regular (serif); the monospace is ugly, so we override it later 164 | \renewcommand*\ttdefault{txtt} % Overriding the monospace font 165 | 166 | % 167 | % Page layout (tricky). 168 | % 169 | \newcommand{\DefaultParskip}{0.6em} 170 | \raggedbottom 171 | \RequirePackage[a4paper]{geometry} 172 | \special{papersize=210mm,297mm} % https://en.wikibooks.org/wiki/LaTeX/Page_Layout 173 | \setlength\columnsep{6mm} % Multi-column envoronments only 174 | \setlength\headheight{17mm} 175 | \setlength{\parskip}{\DefaultParskip} 176 | \setlength{\abovecaptionskip}{0.2em} 177 | \parindent=0em 178 | \renewcommand{\baselinestretch}{1} 179 | \renewcommand{\arraystretch}{1.1} 180 | \leftskip=17mm 181 | \headsep=8mm 182 | \footskip=12mm 183 | \geometry{margin=17mm,top=20mm,bottom=20mm} 184 | 185 | % Removes the left margin for the next paragraph 186 | \newcommand{\NoLeftSkip}{\parindent=-\leftskip} 187 | 188 | % Allowing larger emergency stretch in order to avoid overfull boxes. More on the emergencystretch feature here: 189 | % https://tex.stackexchange.com/questions/241343/what-is-the-meaning-of-fussy-sloppy-emergencystretch-tolerance-hbadness 190 | \appto\fussy{\emergencystretch 5em} 191 | 192 | % 193 | % Section formatting 194 | % 195 | \setcounter{secnumdepth}{3} % Increase this to add deeper structures 196 | 197 | \titleformat{\part}[display]{}{\centering\Large Part \thepart}{1em}{\centering\huge\bfseries} 198 | \titleformat{\chapter}{\huge\bfseries}{}{0em}{\makebox[17mm][l]{\thechapter}\hangindent=\leftskip} 199 | \titleformat{\section}{\Large\bfseries}{}{0em}{\makebox[17mm][l]{\thesection}\hangindent=\leftskip} 200 | \titleformat{\subsection}{\bfseries}{}{0em}{\makebox[17mm][l]{\thesubsection}\hangindent=\leftskip} 201 | \titleformat{\subsubsection}{\itshape}{}{0em}{\makebox[17mm][l]{\thesubsubsection}\hangindent=\leftskip} 202 | 203 | % Starred sections 204 | \titleformat{name=\chapter,numberless}{\huge\bfseries}{}{0em}{} 205 | \titleformat{name=\section,numberless}{\Large\bfseries}{}{0em}{} 206 | 207 | % {left}{before}{after}[right] 208 | \titlespacing{\chapter}{0em}{0em}{0em} 209 | \titlespacing{\section}{0em}{0em}{0em} 210 | \titlespacing{\subsection}{0em}{0em}{0em} 211 | \titlespacing{\subsubsection}{0em}{0em}{0em} 212 | 213 | % 214 | % Hyperlinks. 215 | % 216 | \hypersetup{ 217 | colorlinks, 218 | citecolor=colorhyperlink, 219 | filecolor=colorhyperlink, 220 | linkcolor=colorhyperlink, 221 | urlcolor=colorhyperlink 222 | } 223 | 224 | % 225 | % Table of contents. 226 | % Note that the title margins are defined in absolute units because we're using different font sizes. 227 | % 228 | \renewcommand{\contentsname}{Table of contents} 229 | \renewcommand{\listfigurename}{List of figures} 230 | \renewcommand{\listtablename}{List of tables} 231 | \setcounter{tocdepth}{2} 232 | \titlecontents{part}[0em]{\centering\bfseries}{}{}{} 233 | \dottedcontents{chapter}[5mm]{\bfseries}{5mm}{1pc} 234 | \dottedcontents{section}[14mm]{}{9mm}{1pc} 235 | \dottedcontents{subsection}[25mm]{\footnotesize}{11mm}{1pc} 236 | 237 | \dottedcontents{table}[3em]{}{3em}{1pc} 238 | \dottedcontents{figure}[3em]{}{3em}{1pc} 239 | 240 | % Custom styling of TOC, LOF, LOT. 241 | % Using \sloppy in order to ensure that the maximum line length is not exceeded. 242 | % Exceeding the line limit in two-column environments breaks the table of contents and wreaks havoc in general. 243 | % More on this at https://kb.zubax.com/x/IYEh 244 | \renewcommand\tableofcontents{% 245 | \thispagestyle{plain}% 246 | \sloppy% 247 | \section*{\contentsname}% 248 | \@starttoc{toc}% 249 | \fussy% 250 | } 251 | \renewcommand\listoffigures{% 252 | \thispagestyle{plain}% 253 | \sloppy% 254 | \section*{\listfigurename}% 255 | \@starttoc{lof}% 256 | \fussy% 257 | } 258 | \renewcommand\listoftables{% 259 | \thispagestyle{plain}% 260 | \sloppy% 261 | \section*{\listtablename}% 262 | \@starttoc{lot}% 263 | \fussy% 264 | } 265 | 266 | % Make links black in the TOC, LOF, LOT. 267 | \preto\tableofcontents{\hypersetup{linkcolor=black} \setlength{\parskip}{0em}} 268 | \appto\tableofcontents{\hypersetup{linkcolor=colorhyperlink}\setlength{\parskip}{\DefaultParskip}} 269 | 270 | \preto\listoffigures{\hypersetup{linkcolor=black} \setlength{\parskip}{0em}} 271 | \appto\listoffigures{\hypersetup{linkcolor=colorhyperlink}\setlength{\parskip}{\DefaultParskip}} 272 | 273 | \preto\listoftables{\hypersetup{linkcolor=black} \setlength{\parskip}{0em}} 274 | \appto\listoftables{\hypersetup{linkcolor=colorhyperlink}\setlength{\parskip}{\DefaultParskip}} 275 | 276 | % Include section numbers in the pdf bookmark tree. 277 | \hypersetup{bookmarksnumbered} 278 | 279 | % 280 | % Table macros. 281 | % 282 | 283 | % Ensuring proper bottom spacing for multi-row cells. 284 | % This requires the makecell package 285 | % More at https://tex.stackexchange.com/a/378134/132781 286 | \setcellgapes{1pt} 287 | \makegapedcells 288 | 289 | % Use this wrapper environment to define tables in it. 290 | % This environment provides proper placement of the table within the page, and the properly positioned caption. 291 | \NewDocumentEnvironment{CyphalTableWrapper}{ o m }{% 292 | \ifthenelse{\equal{#1}{wide}}{ 293 | \NoLeftSkip 294 | \begin{minipage}{\textwidth} % Minipage is needed to prevent page breaks after the caption 295 | }{ 296 | \begin{minipage}{\textwidth-\leftskip} % Minipage is needed to prevent page breaks after the caption 297 | } 298 | \begin{ThreePartTable} 299 | }{ 300 | % https://tex.stackexchange.com/questions/3243/why-should-a-table-caption-be-placed-above-the-table 301 | \captionof{table}{#2} 302 | \end{ThreePartTable} 303 | \end{minipage} 304 | } 305 | 306 | \newenvironment{CyphalCompactTable}[1]{ 307 | \begin{tabu}{#1} 308 | \hline 309 | \everyrow{\hline} 310 | \rowfont{\bfseries} 311 | }{ 312 | \end{tabu} 313 | } 314 | 315 | % Use this environment to define a table within the wrapper environment defined above. 316 | \newenvironment{CyphalWrappedTable}[1]{ 317 | \begin{tabu} to \textwidth {#1} 318 | \hline 319 | \everyrow{\hline} 320 | \rowfont{\bfseries} 321 | }{ 322 | \end{tabu} 323 | } 324 | 325 | % This is a shortcut that places a table within the wrapper environment. 326 | % Use it in all cases unless you need to define table notes, or if you need to customize something. 327 | % Arguments: 328 | % {Table caption}{format} 329 | % Example: 330 | % \begin{CyphalSimpleTable}{Firmware status indication via RGB LED}{|l l|X|} 331 | \newenvironment{CyphalSimpleTable}[3][]{ 332 | \begin{CyphalTableWrapper}[#1]{#2} 333 | \begin{CyphalWrappedTable}{#3} 334 | }{ 335 | \end{CyphalWrappedTable} 336 | \end{CyphalTableWrapper} 337 | } 338 | 339 | % 340 | % Page styling. 341 | % 342 | \newcommand\ChapterTitleWithNumber{% 343 | \ifthenelse{\equal{\thechapter}{0}}% 344 | {}% 345 | {\thechapter.\ }% 346 | \ifdefempty{\chaptertitle}% 347 | {\sectiontitle}% 348 | {\chaptertitle}% 349 | } 350 | 351 | \newcommand\PageNumberWithTotal{\thepage\if@mainmatter/\pageref*{LastPage}\fi} 352 | 353 | \newcommand\CyphalLogo[1][15mm]{\includegraphics[width=#1]{cyphal_logo}} 354 | 355 | \newcommand\VerboseLinkToSupportForum{Support \& feedback: \href{http://opencyphal.org}{opencyphal.org}} 356 | 357 | \newcommand\TitleWithDateBefore{\begin{footnotesize}\today\quad\end{footnotesize}{\@title}} 358 | \newcommand\TitleWithDateAfter{{\@title}\begin{footnotesize}\quad\today\end{footnotesize}} 359 | 360 | \renewpagestyle{plain}{ 361 | \sethead% 362 | [\TitleWithDateAfter][][\CyphalLogo] % even 363 | {\CyphalLogo}{}{\TitleWithDateBefore} % odd 364 | 365 | \setfoot% 366 | [\PageNumberWithTotal][\small\VerboseLinkToSupportForum][\small\CyphalCopyright] 367 | {\small\CyphalCopyright}{\small\VerboseLinkToSupportForum}{\PageNumberWithTotal} 368 | 369 | \headrule 370 | \footrule 371 | } 372 | \newpagestyle{main}{ 373 | \sethead% 374 | [\TitleWithDateAfter][][\CyphalLogo] % even 375 | {\CyphalLogo}{}{\TitleWithDateBefore} % odd 376 | 377 | \setfoot% 378 | [\PageNumberWithTotal][][\small\ChapterTitleWithNumber] 379 | {\small\ChapterTitleWithNumber}{}{\PageNumberWithTotal} 380 | 381 | \headrule 382 | \footrule 383 | } 384 | \newpagestyle{titlepage}{ 385 | \setfoot{\CyphalCopyright}{}{\VerboseLinkToSupportForum} 386 | \footrule 387 | } 388 | 389 | % Use the same style on pages that open new chapters. 390 | \patchcmd{\chapter}{plain}{main}{}{} 391 | 392 | % The document will switch to the proper page style automatically. 393 | % We also take this opportunity to enforce \fussy in the main matter. 394 | \preto\frontmatter{\twocolumn\pagestyle{plain}} 395 | \preto\mainmatter{\onecolumn\pagestyle{main}\fussy} 396 | \preto\backmatter{\onecolumn\pagestyle{plain}} 397 | 398 | % 399 | % Title page environment. 400 | % Use "\BeginRightColumn" to switch to the right column. 401 | % 402 | \newcommand{\BeginRightColumn}{\vfill\eject} 403 | 404 | \newcommand{\RenderTitlePageHeader}{% 405 | \renewcommand{\baselinestretch}{1} 406 | \CyphalLogo[\textwidth]\hfill\vspace{10mm} 407 | \begin{flushleft}\begin{Huge}\@title\end{Huge}\end{flushleft} 408 | Revision \today\\[10mm] 409 | } 410 | 411 | \renewenvironment{titlepage}{% 412 | \leftskip=0mm\parindent=0mm 413 | \pagestyle{titlepage}\thispagestyle{titlepage} 414 | \twocolumn[% 415 | \begin{@twocolumnfalse} 416 | \RenderTitlePageHeader 417 | \end{@twocolumnfalse} 418 | ] 419 | % This is needed to allow LaTeX add more white spaces to avoid overflowing lines. 420 | % Extra white spaces in two-column environments are much less bad than overflowing lines. 421 | \emergencystretch 10em 422 | }{% 423 | \clearpage 424 | } 425 | 426 | \endinput 427 | -------------------------------------------------------------------------------- /specification/dsdl/architecture.tex: -------------------------------------------------------------------------------- 1 | \section{Architecture} 2 | 3 | \subsection{General principles} 4 | 5 | In accordance with the Cyphal architecture, DSDL allows users to define data types of two kinds: 6 | message types and service types. 7 | Message types are used to exchange data over publish-subscribe one-to-many message links identified by subject-ID, 8 | and service types are used to perform request-response one-to-one exchanges (like RPC) identified by service-ID. 9 | A service type is composed of exactly two inner data types: 10 | one of them is the request type (its instances are transferred from client to server), 11 | and the other is the response type (its instances are transferred from the server back to the client). 12 | 13 | Following the deterministic nature of Cyphal, the size of a serialized representation of any 14 | message or service object is bounded within statically known limits. 15 | Variable-size entities always have a fixed size limit defined by the data type designer. 16 | 17 | DSDL definitions are strongly statically typed. 18 | 19 | DSDL provides a well-defined means of data type versioning, which enables data type maintainers to introduce changes 20 | to released data types while ensuring backward compatibility with fielded systems. 21 | 22 | DSDL is designed to support extensive static analysis. Important properties of data type definitions such as 23 | backward binary compatibility and data field layouts can be checked and validated by automatic software tools 24 | before the systems utilizing them are fielded. 25 | 26 | DSDL definitions can be used to automatically generate serialization (and deserialization) source code 27 | for any data type in a target programming language. 28 | A tool that is capable of generating serialization code based on a DSDL definition is called a \emph{DSDL compiler}. 29 | More generically, a software tool designed for working with DSDL definitions is called a 30 | \emph{DSDL processing tool}. 31 | 32 | \subsection{Data types and namespaces} 33 | 34 | Every data type is located inside a \emph{namespace}. 35 | Namespaces may be included into higher-level namespaces, forming a tree hierarchy. 36 | 37 | A namespace that is at the root of the tree hierarchy (i.e., not nested within another one) 38 | is called a \emph{root namespace}. 39 | A namespace that is located inside another namespace is called a \emph{nested namespace}. 40 | 41 | A data type is uniquely identified by its namespaces and its \emph{short name}. 42 | The short name of a data type is the name of the type itself excluding the containing namespaces. 43 | 44 | A \emph{full name} of a data type consists of its short name and all of its namespace names. 45 | The short name and the namespace names included in a full name are called \emph{name components}. 46 | Name components are ordered: the root namespace is always the first component of the name, 47 | followed by the nested namespaces, if there are any, in the order of their nesting; 48 | the short name is always the last component of the full name. 49 | The full name is formed by joining its name components via the ASCII dot character ``\verb|.|'' (ASCII code 46). 50 | 51 | A \emph{full namespace} name is the full name without the short name and its component separator. 52 | 53 | A \emph{sub-root namespace} is a nested namespace that is located immediately under its root namespace. 54 | Data types that reside directly under their root namespace do not have a sub-root namespace. 55 | 56 | The name structure is illustrated in figure~\ref{fig:dsdl_data_type_name_structure}. 57 | 58 | \begin{figure}[H] 59 | $$ 60 | \overbrace{ 61 | \underbrace{ 62 | \underbrace{\texttt{\huge{uavcan}}}_{\substack{\text{root} \\ \text{namespace}}}% 63 | \texttt{\huge{.}}% 64 | \underbrace{\texttt{\huge{node}}}_{\substack{\text{nested, also} \\ \text{sub-root} \\ \text{namespace}}}% 65 | \texttt{\huge{.}}% 66 | \underbrace{\texttt{\huge{port}}}_{\substack{\text{nested} \\ \text{namespace}}}% 67 | }_{\text{full namespace}}% 68 | \texttt{\huge{.}}% 69 | \underbrace{\texttt{\huge{GetInfo}}}_{\text{short name}} 70 | }^{\text{full name}} 71 | $$ 72 | \caption{Data type name structure\label{fig:dsdl_data_type_name_structure}} 73 | \end{figure} 74 | 75 | A set of full namespace names and a set of full data type names shall not intersect\footnote{% 76 | For example, a namespace ``\texttt{vendor.example}'' and a data type ``\texttt{vendor.example.1.0}'' 77 | are mutually exclusive. 78 | Note the data type name shown in this example violates the naming conventions 79 | which are reviewed in a separate section. 80 | }. 81 | 82 | Data type names and namespace names are case-sensitive. 83 | However, names that differ only in letter case are not permitted\footnote{% 84 | Because that may cause problems with case-insensitive file systems. 85 | }. 86 | In other words, a pair of names which differ only in letter case is considered to constitute a name collision. 87 | 88 | A name component consists of alphanumeric ASCII characters (which are: \verb|A-Z|, \verb|a-z|, and \verb|0-9|) 89 | and underscore (``\verb|_|'', ASCII code 95). 90 | An empty string is not a valid name component. 91 | The first character of a name component shall not be a digit. 92 | A name component shall not match any of the reserved word patterns, 93 | which are listed in table~\ref{table:dsdl_reserved_word_patterns}. 94 | 95 | The length of a full data type name shall not exceed 255 96 | characters\footnote{This includes the name component separators, but not the version.}. 97 | 98 | Every data type definition is assigned a major and minor version number pair. 99 | In order to uniquely identify a data type definition, its version numbers shall be specified. 100 | In the following text, the term \emph{version} without a majority qualifier refers to 101 | a pair of major and minor version numbers. 102 | 103 | Valid data type version numbers range from 0 to 255, inclusively. 104 | A data type version where both major and minor components are zero is not allowed. 105 | 106 | \subsection{File hierarchy} 107 | 108 | DSDL data type definitions are contained in UTF-8 encoded text files with a file name extension \verb|.dsdl|. 109 | 110 | One file defines exactly one version of a data type, 111 | meaning that each combination of major and minor version numbers shall be unique per data type name. 112 | There may be an arbitrary number of versions of the same data type defined alongside each other, 113 | provided that each version is defined at most once. 114 | Version number sequences can be non-contiguous, 115 | meaning that it is allowed to skip version numbers or remove existing definitions that are neither oldest nor newest. 116 | 117 | A data type definition may have an optional fixed port-ID\footnote{Chapter~\ref{sec:basic}.} value specified. 118 | 119 | The name of a data type definition file is constructed from the following entities 120 | joined via the ASCII dot character ``\verb|.|'' (ASCII code 46), in the specified order: 121 | \begin{itemize} 122 | \item Fixed port-ID in decimal notation, unless a fixed port-ID is not provided for this definition. 123 | \item Short name of the data type (mandatory, always non-empty). 124 | \item Major version number in decimal notation (mandatory). 125 | \item Minor version number in decimal notation (mandatory). 126 | \item File name extension ``\verb|dsdl|'' (mandatory). 127 | \end{itemize} 128 | 129 | \begin{figure}[H] 130 | $$ 131 | \overbrace{% 132 | \underbrace{\texttt{\huge{432}}}_{\substack{\text{fixed} \\ \text{port-ID}}}% 133 | \texttt{\huge{.}}% 134 | }^{\text{optional}}% 135 | \overbrace{% 136 | \underbrace{\texttt{\huge{GetInfo}}}_{\substack{\text{short name}}}% 137 | \texttt{\huge{.}}% 138 | \underbrace{\texttt{\huge{1.0}}}_{\substack{\text{version} \\ \text{numbers}}}% 139 | \texttt{\huge{.}}% 140 | \underbrace{\texttt{\huge{dsdl}}}_{\text{file extension}}% 141 | }^{\text{mandatory}} 142 | $$ 143 | \caption{Data type definition file name structure\label{fig:dsdl_definition_file_name_structure}} 144 | \end{figure} 145 | 146 | DSDL namespaces are represented as directories, where one directory defines exactly one namespace\footnote{% 147 | While a single directory can define only one namespace, the inverse is not prohibited; namespaces can be 148 | defined as the union of the contents of multiple directories that share the same name and folder hierarchy (up to 149 | the root namespace folder). The rules for how distributed definitions such as these are resolved are specific to any 150 | tools that manage them. This specification applies only to the resulting union assuming it is equivalent to a single 151 | file tree. 152 | }, possibly nested. 153 | The name of the directory defines the name of its data type name component. 154 | One directory cannot define more than one level of 155 | nesting\footnote{% 156 | For example, ``\texttt{foo.bar}'' is not a valid directory name. 157 | The valid representation would be ``\texttt{bar}'' nested in ``\texttt{foo}''. 158 | }. 159 | 160 | \begin{remark} 161 | \begin{figure}[H] 162 | \begin{tabu}{|l|X|} \hline 163 | \rowfont{\bfseries} 164 | Directory tree & Entry description \\\hline 165 | 166 | \texttt{vendor\_x/} & 167 | Root namespace \texttt{vendor\_x}. \\\cline{2-2} 168 | 169 | \texttt{\qquad{}foo/} & 170 | Nested namespace (also sub-root) \texttt{vendor\_x.foo}. \\\cline{2-2} 171 | 172 | \texttt{\qquad{}\qquad{}100.Run.1.0.dsdl} & 173 | Data type definition v1.0 with fixed service-ID 100. \\\cline{2-2} 174 | 175 | \texttt{\qquad{}\qquad{}100.Status.1.0.dsdl} & 176 | Data type definition v1.0 with fixed subject-ID 100. \\\cline{2-2} 177 | 178 | \texttt{\qquad{}\qquad{}ID.1.0.dsdl} & 179 | Data type definition v1.0 without fixed port-ID. \\\cline{2-2} 180 | 181 | \texttt{\qquad{}\qquad{}ID.1.1.dsdl} & 182 | Data type definition v1.1 without fixed port-ID. \\\cline{2-2} 183 | 184 | \texttt{\qquad{}\qquad{}bar\_42/} & 185 | Nested namespace \texttt{vendor\_x.foo.bar\_42}. \\\cline{2-2} 186 | 187 | \texttt{\qquad{}\qquad{}\qquad{}101.List.1.0.dsdl} & 188 | Data type definition v1.0 with fixed service-ID 101. \\\cline{2-2} 189 | 190 | \texttt{\qquad{}\qquad{}\qquad{}102.List.2.0.dsdl} & 191 | Data type definition v2.0 with fixed service-ID 102. \\\cline{2-2} 192 | 193 | \texttt{\qquad{}\qquad{}\qquad{}ID.1.0.dsdl} & 194 | Data type definition v1.0 without fixed port-ID. \\\hline 195 | \end{tabu} 196 | \caption{DSDL directory structure example}\label{fig:dsdl_directory_structure_example} 197 | \end{figure} 198 | \end{remark} 199 | 200 | \subsection{Elements of data type definition}\label{sec:dsdl_elements_of_data_type_definition} 201 | 202 | A data type definition file contains an exhaustive description of a particular version of the said data type in the 203 | \emph{data structure description language} (DSDL). 204 | 205 | A data type definition contains an ordered, possibly empty collection of \emph{field attributes} and/or 206 | unordered, possibly empty collection of \emph{constant attributes}. 207 | 208 | A data type may describe either a \emph{structure object} or a \emph{tagged union object}. 209 | The value of a structure object is a function of the values of all of its field attributes. 210 | A tagged union object is formed from at least two field attributes, 211 | but it is capable of holding exactly one field attribute value at any given time. 212 | The value of a tagged union object is a function of which field attribute value 213 | it is holding at the moment and the value of said field attribute. 214 | 215 | A field attribute represents a named dynamically assigned value of a statically defined type 216 | that can be exchanged over the network as a member of its containing object. 217 | A padding field attribute is a special kind of field attribute which is used for data alignment purposes; 218 | such field attributes are not named. 219 | 220 | A constant attribute represents a named statically defined value of a statically defined type. 221 | Constants are never exchanged over the network, since they are assumed to be known to all involved nodes 222 | by virtue of them sharing compatible definitions of the data type. 223 | 224 | Constant values are defined via \emph{DSDL expressions}, 225 | which are evaluated at the time of DSDL definition processing. 226 | There is a special category of types called \emph{expression types}, 227 | instances of which are used only during expression evaluation 228 | and cannot be exchanged over the network. 229 | 230 | Data type definitions can also contain various auxiliary elements reviewed later, 231 | such as deprecation markers (notifying its users that the data type is no longer recommended for new designs) 232 | or assertions (special statements introduced by data type designers 233 | which are statically validated by DSDL processing tools). 234 | 235 | Service type definitions are a special case: 236 | they cannot be instantiated or serialized, they do not contain attributes, 237 | and they are composed of exactly two inner data type definitions\footnote{ 238 | A service type can be thought of as a specialized namespace that contains two types and 239 | has some of the properties of a type, such as name and version. 240 | }. 241 | These inner types are the service request type and the service response type, 242 | separated by the \emph{service response marker}. 243 | They are otherwise ordinary data types except that they are unutterable\footnote{% 244 | Cannot be referred to. Another commonly used term is ``Voldemort type''. 245 | } 246 | and they derive some of their properties\footnote{Like version numbers or deprecation status.} 247 | from their \emph{parent service type}. 248 | 249 | \subsection{Serialization} 250 | 251 | Every object that can be exchanged between Cyphal nodes has a well-defined \emph{serialized representation}. 252 | The value and meaning of an object can be unambiguously recovered from its serialized representation, 253 | provided that the type of the object is known. 254 | Such recovery process is called \emph{deserialization}. 255 | 256 | \label{sec:dsdl_bit_length_set} 257 | A serialized representation is a sequence of binary digits (bits); 258 | the number of bits in a serialized representation is called its \emph{bit length}. 259 | A \emph{bit length set} of a data type refers to the set of bit length values of all possible 260 | serialized representations of objects that are instances of the data type. 261 | 262 | A data type whose bit length set contains more than one element is said to be \emph{variable length}. 263 | The opposite case is referred to as \emph{fixed length}. 264 | 265 | The data type of a serialized message or service object exchanged over the network 266 | is recovered from its subject-ID or service-ID, respectively, 267 | which is attached to the serialized object, along with other metadata, in a manner dictated by the applicable 268 | transport layer specification (chapter~\ref{sec:transport}). 269 | For more information on port identifiers and data type mapping refer to section~\ref{sec:basic_subjects_and_services}. 270 | 271 | The bit length set is not defined on service types (only on their request and response types) 272 | because they cannot be instantiated. 273 | -------------------------------------------------------------------------------- /specification/dsdl/attributes.tex: -------------------------------------------------------------------------------- 1 | \section{Attributes}\label{sec:dsdl_attributes} 2 | 3 | An \emph{attribute} is a named (excepting padding fields) entity associated with a particular object or type. 4 | 5 | \subsection{Composite type attributes} 6 | 7 | A composite type attribute that has a value assigned at the data type definition time is called a 8 | \emph{constant attribute}; 9 | a composite type attribute that does not have a value assigned at the definition time is called a 10 | \emph{field attribute}. 11 | 12 | The name of a composite type attribute shall be unique within the data type definition that contains it, 13 | and it shall not match any of the reserved name patterns specified in the table 14 | \ref{table:dsdl_reserved_word_patterns}. 15 | This requirement does not apply to padding fields. 16 | 17 | \subsubsection{Field attributes} 18 | 19 | A field attribute represents a named dynamically assigned value of a statically defined type 20 | that can be exchanged over the network as a member of its containing object. 21 | The data type of a field attribute shall be of the serializable type category 22 | (section~\ref{sec:dsdl_serializable_types}), 23 | excepting the void type category, which is not allowed. 24 | 25 | Exception applies to the special kind of field attributes --- \emph{padding fields}. 26 | The type of a padding field attribute shall be of the void category. 27 | A padding field attribute may not have a name. 28 | 29 | A pair of field attributes is considered equal if, and only if, both field attributes are of the same type, 30 | and both share the same name or both are padding field attributes. 31 | 32 | \begin{remark} 33 | Example: 34 | \begin{minted}{python} 35 | uint8[<=10] regular_field # A field named "regular field" 36 | void16 # A padding field; no name is permitted 37 | \end{minted} 38 | \end{remark} 39 | 40 | \subsubsection{Constant attributes} 41 | 42 | A constant attribute represents a named statically assigned value of a statically defined type. 43 | Values of constant attributes are never exchanged over the network, 44 | since they are assumed to be known to all involved nodes 45 | by virtue of them sharing the same definition of the data type. 46 | 47 | The data type of a constant attribute shall be of the primitive type category 48 | (section~\ref{sec:dsdl_serializable_types}). 49 | 50 | The value of the constant attribute is determined at the DSDL definition processing time by evaluating its 51 | \emph{initialization expression}. 52 | The expression shall yield a compatible type upon its evaluation in order to initialize 53 | the value of its constant attribute. 54 | The set of compatible types depends on the type of the initialized constant attribute, 55 | as specified in table~\ref{table:dsdl_constant_init_pattern}. 56 | 57 | \begin{CyphalSimpleTable}[wide]{Permitted constant attribute value initialization patterns}{|l | X | X[2] | X[2]|} 58 | \diagbox[font=\footnotesize]{Constant\\type\\category}{Expression\\type} & 59 | \texttt{bool} & \texttt{rational} & \texttt{string} \\ 60 | 61 | \textbf{Boolean} & 62 | Allowed. & 63 | Not allowed. & 64 | Not allowed. \\ 65 | 66 | \textbf{Integer} & 67 | Not allowed. & 68 | Allowed if the denominator equals one and the numerator value is within the range of the constant type. & 69 | Allowed if the target type is \texttt{uint8} and the source string contains one symbol whose code point falls 70 | into the range $[0, 127]$. \\ 71 | 72 | \textbf{Floating point} & 73 | Not allowed. & 74 | Allowed if the source value does not exceed the finite range of the constant type. 75 | The final value is computed as the quotient of the numerator and the denominator 76 | with implementation-defined accuracy. & 77 | Not allowed. \label{table:dsdl_constant_init_pattern}\\ 78 | 79 | \end{CyphalSimpleTable} 80 | 81 | Due to the value of a constant attribute being defined at the data type definition time, 82 | the cast mode of primitive-typed constants has no observable effect. 83 | 84 | \begin{remark} 85 | A real literal \verb|1234.5678| is represented internally as 86 | $\frac{6172839}{5000}$, which can be used to initialize a \verb|float16| value, 87 | resulting in $1235.0$. 88 | 89 | The specification states that the value of a floating-point constant should be computed 90 | with an implementation-defined accuracy. Cyphal avoids strict accuracy requirements in order to 91 | ensure compatibility with implementations that rely on non-standard floating point formats. 92 | Such laxity in the specification is considered acceptable since the uncertainty is always 93 | confined to a single division expression per constant; all preceding computations, if any, 94 | are always performed by the DSDL compiler using exact rational arithmetic. 95 | \end{remark} 96 | 97 | \subsection{Local attributes}\label{sec:dsdl_local_attributes} 98 | 99 | Local attributes are available at the DSDL definition processing time. 100 | 101 | As defined in section~\ref{sec:dsdl_grammar}, 102 | a DSDL definition is an ordered collection of statements; 103 | a statement may contain DSDL expressions. 104 | An expression contained in a statement number $E$ may refer to a 105 | composite type attribute introduced in a statement number $A$ by its name, 106 | where $A < E$ and both statements belong to the same data type definition\footnote{ 107 | Per \ref{sec:dsdl_elements_of_data_type_definition}, 108 | in case of services, this applies only to their request and response types. 109 | }. 110 | The representation of the referred attribute in the context of the referring DSDL expression 111 | is specified in table~\ref{table:dsdl_local_attribute_representation}. 112 | 113 | \begin{CyphalSimpleTable}{Local attribute representation}{|l X X|}\label{table:dsdl_local_attribute_representation}% 114 | Attribute category & Value type & Value \\ 115 | 116 | Constant attribute & 117 | Type of the constant attribute & 118 | Value of the constant attribute \\ 119 | 120 | % Field attribute & 121 | % \texttt{metaserializable} & 122 | % Type of the field attribute \\ 123 | Field attribute & 124 | Illegal & 125 | Illegal \\ 126 | 127 | \end{CyphalSimpleTable} 128 | 129 | \begin{remark} 130 | \begin{minted}{python} 131 | uint8 FOO = 123 132 | uint16 BAR = FOO ** 2 133 | @assert BAR == 15129 134 | --- # The request type ends here; its attributes are no longer accessible. 135 | #uint16 BAZ = BAR # Would fail - BAR is not accessible here. 136 | float64 FOO = 3.14 137 | @assert FOO == 3.14 138 | \end{minted} 139 | \end{remark} 140 | 141 | \subsection{Intrinsic attributes} 142 | 143 | Intrinsic attributes are available in any expression. 144 | Their values are constructed by the DSDL processing tool depending on the context, 145 | as specified in this section. 146 | 147 | \subsubsection{Offset attribute} 148 | 149 | The offset attribute is referred to by its identifier ``\verb|_offset_|''. 150 | Its value is of type $\texttt{set}_\texttt{}$. 151 | 152 | In the following text, the term \emph{referring statement} denotes a statement 153 | containing an expression which refers to the offset attribute. 154 | The term \emph{bit length set} is defined in section~\ref{sec:dsdl_bit_length_set}. 155 | 156 | The value of the attribute is a function of the field attribute declarations preceding the referring statement 157 | and the category of the containing definition. 158 | 159 | If the current definition belongs to the tagged union category, 160 | the referring statement shall be located after the last field attribute definition. 161 | A field attribute definition following the referring statement renders the current definition invalid. 162 | For tagged unions, the value of the offset attribute is defined as the 163 | cumulative bit length set\footnote{Section \ref{sec:dsdl_composite_alignment_cumulative_bls}.} 164 | of the union's fields, where each element of the set is incremented by the bit length of the implicit union tag field 165 | (section \ref{sec:dsdl_serialization_composite}). 166 | 167 | If the current data definition does not belong to the tagged union category, 168 | the referring statement may be located anywhere within the current definition. 169 | The value of the offset attribute is defined as the 170 | cumulative bit length set\footnote{Section \ref{sec:dsdl_composite_alignment_cumulative_bls}.} 171 | of the fields defined in statements preceding the referring statement 172 | (see section~\ref{sec:dsdl_grammar} on statement ordering). 173 | 174 | \begin{remark} 175 | \begin{minted}{python} 176 | @union 177 | uint8 a 178 | #@print _offset_ # Would fail: it's a tagged union, _offset_ is undefined until after the last field 179 | uint16 b 180 | @assert _offset_ == {8 + 8, 8 + 16} 181 | --- 182 | @assert _offset_ == {0} 183 | float16 a 184 | @assert _offset_ == {16} 185 | void4 186 | @assert _offset_ == {20} 187 | int4 b 188 | @assert _offset_ == {24} 189 | uint8[<4] c 190 | @assert _offset_ == 8 + {24, 32, 40, 48} 191 | @assert _offset_ % 8 == {0} 192 | # One of the main usages for _offset_ is statically proving that the following field is byte-aligned 193 | # for all possible valid serialized representations of the preceding fields. It is done by computing 194 | # a remainder as shown above. If the field is aligned, the remainder set will equal {0}. If the 195 | # remainder set contains other elements, the field may be misaligned under some circumstances. 196 | # If the remainder set does not contain zero, the field is never aligned. 197 | uint8 well_aligned # Proven to be byte-aligned. 198 | \end{minted} 199 | \end{remark} 200 | -------------------------------------------------------------------------------- /specification/dsdl/conventions.tex: -------------------------------------------------------------------------------- 1 | \section{Conventions and recommendations} 2 | 3 | This section is dedicated to conventions and recommendations 4 | intended to help data type designers maintain a consistent style across the ecosystem 5 | and avoid some common pitfalls. 6 | All of the conventions and recommendations provided in this section are optional (not mandatory to follow). 7 | 8 | \subsection{Naming recommendations} 9 | 10 | The DSDL naming recommendations follow those that are widely accepted in the general software development industry. 11 | 12 | \begin{itemize} 13 | \item Namespaces and field attributes should be named in the \verb|snake_case|. 14 | \item Constant attributes should be named in the \verb|SCREAMING_SNAKE_CASE|. 15 | \item Data types (excluding their namespaces) should be named in the \verb|PascalCase|. 16 | \item Names of message types should form a declarative phrase or a noun. For example, 17 | \verb|BatteryStatus| or \verb|OutgoingPacket|. 18 | \item Names of service types should form an imperative phrase or a verb. For example, 19 | \verb|GetInfo| or \verb|HandleIncomingPacket|. 20 | \item Short names, unnecessary abbreviations, and uncommon acronyms should be avoided. 21 | \end{itemize} 22 | 23 | \subsection{Comments} 24 | 25 | Every data type definition file should begin with a header comment that provides an exhaustive description 26 | of the data type, its purpose, semantics, usage patterns, any related data exchange patterns, 27 | assumptions, constraints, and all other information that may be necessary or generally useful for the usage of the 28 | data type definition. 29 | 30 | Every attribute of the data type definition, and especially every field attribute of it, 31 | should have an associated comment explaining the purpose of the attribute, its semantics, usage patterns, 32 | assumptions, constraints, and any other pertinent information. 33 | Exception applies to attributes supplied with sufficiently descriptive and unambiguous names. 34 | 35 | A comment should be placed after the entity it is intended to describe; 36 | either on the same line (in which case it should be separated from the preceding text with at least two spaces) 37 | or on the next line (without blank lines in between). 38 | This recommendation does not apply to the file header comment. 39 | 40 | % Field comment placement https://forum.opencyphal.org/t/dsdl-documentation-comments/407 41 | 42 | \subsection{Optional value representation} 43 | 44 | Data structures may include optional field attributes that are not always populated. 45 | 46 | The recommended approach for representing optional field attributes 47 | is to use variable-length arrays with the capacity of one element. 48 | 49 | Alternatively, such one-element variable-length arrays can be replaced with two-field unions, 50 | where the first field is empty and the second field contains the desired optional value. 51 | The described layout is semantically compatible with the one-element array described above, 52 | provided that the field attributes are not swapped. 53 | 54 | Floating-point-typed field attributes may be assigned the value of not-a-number (NaN) per IEEE 754 55 | to indicate that the value is not specified; 56 | however, this pattern is discouraged because the value would still have to be transferred over the bus 57 | even if not populated, and special case values undermine type safety. 58 | 59 | \begin{remark}[breakable] 60 | Array-based optional field: 61 | 62 | \begin{minted}{python} 63 | MyType[<=1] optional_field 64 | \end{minted} 65 | 66 | Union-based optional field: 67 | 68 | \begin{minted}{python} 69 | @sealed # Sic! 70 | @union # The implicit tag is one byte long. 71 | uavcan.primitive.Empty none # Represents lack of value, unpopulated field. 72 | MyType some # The field of interest; field ordering is important. 73 | \end{minted} 74 | 75 | The defined above union can be used as follows (suppose it is named \verb|MaybeMyType|): 76 | 77 | \begin{minted}{python} 78 | MaybeMyType optional_field 79 | \end{minted} 80 | 81 | The shown approaches are semantically compatible. 82 | \end{remark} 83 | 84 | \begin{remark}[breakable] 85 | The implicit truncation and the implicit zero extension rules allow one to freely add such optional fields 86 | at the end of a definition while retaining semantic compatibility. 87 | The implicit truncation rule will render them invisible to nodes that utilize older data type definitions 88 | which do not contain them, whereas nodes that utilize newer definitions will be able to correctly process 89 | objects serialized using older definitions because the implicit zero extension rule guarantees 90 | that the optional fields will appear unpopulated. 91 | 92 | For example, let the following be the old message definition: 93 | 94 | \begin{minted}{python} 95 | float64 foo 96 | float32 bar 97 | \end{minted} 98 | 99 | The new message definition with the new field is as follows: 100 | 101 | \begin{minted}{python} 102 | float64 foo 103 | float32 bar 104 | MyType[<=1] my_new_field 105 | \end{minted} 106 | 107 | Suppose that one node is publishing a message using the old definition, 108 | and another node is receiving it using the new definition. 109 | The implicit zero extension rule guarantees that the optional field array will 110 | appear empty to the receiving node because the implicit length field will be read as zero. 111 | Same is true if the message was nested inside another one, thanks to the delimiter header. 112 | \end{remark} 113 | 114 | \subsection{Bit flag representation} 115 | 116 | The recommended approach to defining a set of bit flags is to dedicate a \verb|bool|-typed field attribute for each. 117 | Representations based on an integer sum of powers of two\footnote{Which are popular in programming.} 118 | are discouraged due to their obscurity and failure to express the intent clearly. 119 | 120 | \begin{remark} 121 | Recommended approach: 122 | 123 | \begin{minted}{python} 124 | void5 125 | bool flag_foo 126 | bool flag_bar 127 | bool flag_baz 128 | \end{minted} 129 | 130 | Not recommended: 131 | 132 | \begin{minted}{python} 133 | uint8 flags # Not recommended 134 | uint8 FLAG_BAZ = 1 135 | uint8 FLAG_BAR = 2 136 | uint8 FLAG_FOO = 4 137 | \end{minted} 138 | \end{remark} 139 | -------------------------------------------------------------------------------- /specification/dsdl/directives.tex: -------------------------------------------------------------------------------- 1 | \section{Directives}\label{sec:dsdl_directives} 2 | 3 | Per the DSDL grammar specification (section~\ref{sec:dsdl_grammar}), 4 | a directive may or may not have an associated expression. 5 | In this section, it is assumed that a directive does not expect an expression unless explicitly stated otherwise. 6 | 7 | If the expectation of an associated directive expression or lack thereof is violated, 8 | the containing DSDL definition is malformed. 9 | 10 | The effect of a directive is confined to the data type definition that contains it. 11 | That means that for service types, unless specifically stated otherwise, 12 | a directive placed in the request (response) type affects only the request (response) type. 13 | 14 | \subsection{Tagged union marker} 15 | 16 | The identifier of the tagged union marker directive is ``\verb|union|''. 17 | Presence of this directive in a data type definition indicates that the 18 | data type definition containing this directive belongs to the tagged union category 19 | (section~\ref{sec:dsdl_composite_tagged_unions}). 20 | 21 | Usage of this directive is subject to the following constraints: 22 | \begin{itemize} 23 | \item The directive shall not be used more than once per data type definition. 24 | \item The directive shall be placed before the first composite type attribute definition in the current definition. 25 | \end{itemize} 26 | 27 | \begin{remark} 28 | \begin{minted}{python} 29 | uint8[<64] name # Request is not a union 30 | --- 31 | @union # Response is a union 32 | uint64 natural 33 | #@union # Would fail - @union is not allowed after the first attribute definition 34 | float64 real 35 | \end{minted} 36 | \end{remark} 37 | 38 | \subsection{Extent specifier}\label{sec:dsdl_directive_extent} 39 | 40 | The identifier of the extent specification directive is ``\verb|extent|''. 41 | This directive declares the current data type definition to be delimited (non-sealed) 42 | and specifies its extent (section \ref{sec:dsdl_composite_extent_and_sealing}). 43 | The extent value is obtained by evaluating the provided expression. 44 | The expression shall be present and it shall yield a non-negative integer value of type 45 | ``\verb|rational|'' (section~\ref{sec:dsdl_primitive_types}) upon its evaluation. 46 | 47 | Usage of this directive is subject to the following constraints (otherwise, the definition is malformed): 48 | \begin{itemize} 49 | \item The directive shall not be used more than once per data type definition. 50 | \item The directive shall be placed after the last attribute definition in the current data type\footnote{% 51 | This constraint is to help avoid issues where the extent is defined as a function of the offset past 52 | the last field of the type, and a new field is mistakenly added after the extent directive. 53 | }. 54 | \item The value shall satisfy the constraints given in section \ref{sec:dsdl_composite_extent_and_sealing}. 55 | \item The data type shall not be sealed. 56 | \end{itemize} 57 | 58 | \begin{remark} 59 | \begin{minted}{python} 60 | uint64 foo 61 | @extent 256 * 8 # Make the extent 256 bytes large 62 | #@sealed # Would fail -- mutually exclusive directives 63 | \end{minted} 64 | 65 | \begin{minted}{python} 66 | uint64[<=64] bar 67 | @extent _offset_.max * 2 68 | #float32 baz # Would fail (protects against incorrectly computing 69 | # the extent when it is a function of _offset_) 70 | \end{minted} 71 | \end{remark} 72 | 73 | \subsection{Sealing marker}\label{sec:dsdl_directive_sealed} 74 | 75 | The identifier of the sealing marker directive is ``\verb|sealed|''. 76 | This directive marks the current data type sealed (section \ref{sec:dsdl_composite_extent_and_sealing}). 77 | 78 | Usage of this directive is subject to the following constraints (otherwise, the definition is malformed): 79 | \begin{itemize} 80 | \item The directive shall not be used more than once per data type definition. 81 | \item The extent directive shall not be used in this data type definition. 82 | \end{itemize} 83 | 84 | \begin{remark} 85 | \begin{minted}{python} 86 | uint64 foo 87 | @sealed # The request type is sealed. 88 | #@extent 128 # Would fail -- cannot specify extent for sealed type 89 | --- 90 | float64 bar # The response type is not sealed. 91 | @extent 4000 * 8 92 | \end{minted} 93 | \end{remark} 94 | 95 | \subsection{Deprecation marker} 96 | 97 | The identifier of the deprecation marker directive is ``\verb|deprecated|''. 98 | Presence of this directive in a data type definition indicates that the current version of the data type definition 99 | is nearing the end of its life cycle and may be removed soon. 100 | The data type versioning principles are explained in section~\ref{sec:dsdl_versioning}. 101 | 102 | Code generation tools should use this directive to reflect the impending removal of the current data type version 103 | in the generated code. 104 | 105 | Usage of this directive is subject to the following constraints: 106 | \begin{itemize} 107 | \item The directive shall not be used more than once per data type definition. 108 | \item The directive shall be placed before the first composite type attribute definition in the definition. 109 | \item In case of service types, this directive may only be placed in the request type, 110 | and it affects the response type as well. 111 | \end{itemize} 112 | 113 | \begin{remark} 114 | \begin{minted}{python} 115 | @deprecated # Applies to the entire definition 116 | uint8 FOO = 123 117 | #@deprecated # Would fail - shall be placed before the first attribute definition 118 | --- 119 | #@deprecated # Would fail - shall be placed in the request type 120 | \end{minted} 121 | 122 | A C++ class generated from the above definition could be annotated with the \verb|[[deprecated]]| attribute. 123 | 124 | A Rust structure generated from the above definition could be annotated with the \verb|#[deprecated]| attribute. 125 | 126 | A Python class generated from the above definition could raise \verb|DeprecationWarning| upon usage. 127 | \end{remark} 128 | 129 | \subsection{Assertion check} 130 | 131 | The identifier of the assertion check directive is ``\verb|assert|''. 132 | The assertion check directive expects an expression which shall yield a value of type 133 | ``\verb|bool|'' (section~\ref{sec:dsdl_primitive_types}) upon its evaluation. 134 | 135 | If the expression yields truth, the assertion check directive has no effect. 136 | 137 | If the expression yields falsity, a value of type other than ``\verb|bool|'', or fails to evaluate, 138 | the containing DSDL definition is malformed. 139 | 140 | \begin{remark} 141 | \begin{minted}{python} 142 | float64 real 143 | @assert _offset_ == {32} # Would fail: {64} != {32} 144 | \end{minted} 145 | \end{remark} 146 | 147 | \subsection{Print} 148 | 149 | The identifier of the print directive is ``\verb|print|''. 150 | The print directive may or may not be provided with an associated expression. 151 | 152 | If the expression is not provided, the behavior is implementation-defined. 153 | 154 | If the expression is provided, it is evaluated and its result is displayed by the DSDL processing tool in 155 | a human-readable implementation-defined form. 156 | Implementations should strive to produce textual representations that form valid DSDL expressions themselves, 157 | so that they would produce the same value if evaluated by a DSDL processing tool. 158 | 159 | If the expression is provided but cannot be evaluated, the containing DSDL definition is malformed. 160 | 161 | \begin{remark} 162 | \begin{minted}{python} 163 | float64 real 164 | @print _offset_ / 6 # Possible output: {32/3} 165 | @print uavcan.node.Heartbeat.1.0 # Possible output: uavcan.node.Heartbeat.1.0 166 | @print bool[<4] # Possible output: saturated bool[<=3] 167 | @print float64 # Possible output: saturated float64 168 | @print {123 == 123, false} # Possible output: {true, false} 169 | @print 'we all float64 down here\n' # Possible output: 'we all float64 down here\n' 170 | \end{minted} 171 | \end{remark} 172 | -------------------------------------------------------------------------------- /specification/dsdl/dsdl.tex: -------------------------------------------------------------------------------- 1 | \chapter{Data structure description language}\label{sec:dsdl} 2 | 3 | The data structure description language, or \emph{DSDL}, is a simple domain-specific language designed for 4 | defining composite data types. 5 | The defined data types are used for exchanging data between Cyphal nodes via one of the standard Cyphal 6 | transport protocols\footnote{The standard transport protocols are documented in chapter~\ref{sec:transport}. 7 | Cyphal doesn't prohibit users from defining their own application-specific transports as well, 8 | although users doing that are likely to encounter compatibility issues and possibly a suboptimal 9 | performance of the protocol.}. 10 | 11 | \input{dsdl/architecture.tex} 12 | \input{dsdl/grammar.tex} 13 | \input{dsdl/expression_types.tex} 14 | \input{dsdl/serializable_types.tex} 15 | \input{dsdl/attributes.tex} 16 | \input{dsdl/directives.tex} 17 | \input{dsdl/serialization.tex} 18 | \input{dsdl/compatibility.tex} 19 | \input{dsdl/conventions.tex} 20 | -------------------------------------------------------------------------------- /specification/dsdl/expression_types.tex: -------------------------------------------------------------------------------- 1 | \section{Expression types}\label{sec:dsdl_expression_types} 2 | 3 | Expression types are a special category of data types whose instances can only exist and be operated upon 4 | at the time of DSDL definition processing. 5 | As such, expression types cannot be used to define attributes, 6 | and their instances cannot be exchanged between nodes. 7 | 8 | Expression types are used to represent values of constant expressions which are evaluated 9 | when a DSDL definition is processed. 10 | Results of such expressions can be used to define various constant properties, 11 | such as array length boundaries or values of constant attributes. 12 | 13 | Expression types are specified in this section. 14 | Each expression type has a formal DSDL name for completeness; 15 | even if such types can't be used to define attributes, 16 | a well-defined formal name allows DSDL processing tools to emit well-formed 17 | and understandable diagnostic messages. 18 | 19 | \subsection{Rational number}\label{sec:dsdl_rational} 20 | 21 | At the time of DSDL definition processing, integer and real numbers are represented internally as rational numbers 22 | where the range of numerator and denominator is unlimited\footnote{% 23 | Technically, the range may only be limited by the memory resources available to the DSDL processing tool. 24 | }. 25 | DSDL processing tools are not permitted to introduce any implicit rational number transformations that 26 | may result in a loss of information. 27 | 28 | The DSDL name of the rational number type is ``\verb|rational|''. 29 | 30 | Rational numbers are assumed to be stored in a normalized form, where the denominator is positive 31 | and the greatest common divisor of the numerator and the denominator is one. 32 | 33 | A rational number can be used in a context where an integer value is expected only if its denominator equals one. 34 | 35 | Implicit conversions between boolean-valued entities and rational numbers are not allowed. 36 | 37 | \begin{CyphalSimpleTable}{Operators defined on instances of rational numbers}{|l l X X|} 38 | Op & Type & Constraints & Description 39 | \label{table:dsdl_operators_rational} \\ 40 | 41 | \texttt{\textbf{+}} & $(\texttt{rational}) \rightarrow \texttt{rational}$ & & 42 | No effect. \\ 43 | \texttt{\textbf{-}} & $(\texttt{rational}) \rightarrow \texttt{rational}$ & & 44 | Negation. \\ 45 | 46 | \texttt{\textbf{**}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & 47 | Power denominator equals one & 48 | Exact exponentiation. \\ 49 | 50 | \texttt{\textbf{**}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & 51 | Power denominator greater than one & 52 | Exponentiation with imp\-lem\-en\-ta\-ti\-on-de\-fin\-ed accuracy. \\ 53 | 54 | \texttt{\textbf{*}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & & 55 | Exact multiplication. \\ 56 | 57 | \texttt{\textbf{/}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & 58 | Non-zero divisor & 59 | Exact division. \\ 60 | 61 | \texttt{\textbf{\%}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & 62 | Non-zero divisor & 63 | Exact modulo. \\ 64 | 65 | \texttt{\textbf{+}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & & 66 | Exact addition. \\ 67 | 68 | \texttt{\textbf{-}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & & 69 | Exact subtraction. \\ 70 | 71 | \texttt{\textbf{|}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & 72 | Denominators equal one & 73 | Bitwise or. \\ 74 | 75 | \texttt{\textbf{\textasciicircum{}}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & 76 | Denominators equal one & 77 | Bitwise xor. \\ 78 | 79 | \texttt{\textbf{\&}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{rational}$ & 80 | Denominators equal one & 81 | Bitwise and. \\ 82 | 83 | \texttt{\textbf{!=}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{bool}$ & & Exact inequality. \\ 84 | \texttt{\textbf{==}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{bool}$ & & Exact equality. \\ 85 | \texttt{\textbf{<=}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{bool}$ & & Less or equal. \\ 86 | \texttt{\textbf{>=}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{bool}$ & & Greater or equal. \\ 87 | \texttt{\textbf{<}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{bool}$ & & Strictly less. \\ 88 | \texttt{\textbf{>}} & $(\texttt{rational}, \texttt{rational}) \rightarrow \texttt{bool}$ & & Strictly greater. \\ 89 | 90 | \end{CyphalSimpleTable} 91 | 92 | \subsection{Unicode string}\label{sec:dsdl_string} 93 | 94 | This type contains a sequence of Unicode characters. 95 | It is used to represent string literals internally. 96 | 97 | The DSDL name of the Unicode string type is ``\verb|string|''. 98 | 99 | A Unicode string containing one symbol whose code point is within $[0, 127]$ 100 | (i.e., an ASCII character) is implicitly convertible into a \verb|uint8|-typed constant attribute value, 101 | where the value of the constant is to be equal the code point of the symbol. 102 | 103 | \begin{CyphalSimpleTable}{Operators defined on instances of Unicode strings}{|l l X|} 104 | Op & Type & Description 105 | \label{table:dsdl_operators_string} \\ 106 | 107 | \texttt{\textbf{+}} & $(\texttt{string}, \texttt{string}) \rightarrow \texttt{string}$ & 108 | Concatenation. \\ 109 | 110 | \texttt{\textbf{!=}} & $(\texttt{string}, \texttt{string}) \rightarrow \texttt{bool}$ & 111 | Inequality of Unicode NFC normalized forms. 112 | NFC stands for \emph{Normalization Form Canonical Composition} -- 113 | one of standard Unicode normalization forms where characters are recomposed by canonical equivalence. \\ 114 | 115 | \texttt{\textbf{==}} & $(\texttt{string}, \texttt{string}) \rightarrow \texttt{bool}$ & 116 | Equality of Unicode NFC normalized forms. \\ 117 | 118 | \end{CyphalSimpleTable} 119 | 120 | The set of operations and conversions defined for Unicode strings is to be extended in future versions of 121 | the specification. 122 | 123 | \subsection{Set}\label{sec:dsdl_set} 124 | 125 | A set type represents an unordered collection of unique objects. 126 | All objects shall be of the same type. 127 | Uniqueness of elements is determined by application of the equality operator ``\verb|==|''. 128 | 129 | The DSDL name of the set type is ``\verb|set|''. 130 | 131 | A set can be constructed from a set literal, in which case such set shall contain at least one element. 132 | 133 | The attributes and operators defined on set instances are listed in the tables~\ref{table:dsdl_set_attributes} 134 | and~\ref{table:dsdl_set_operators}, where $E$ represents the set element type. 135 | 136 | \begin{CyphalSimpleTable}{Attributes defined on instances of sets}{|l l X X|} 137 | Name & Type & Constraints & Description 138 | \label{table:dsdl_set_attributes} \\ 139 | 140 | \texttt{min} & $E$ & 141 | Operator ``\texttt{<}'' is defined \mbox{$(E, E) \rightarrow \texttt{bool}$} & 142 | Smallest element in the set determined by sequential application of the operator ``\texttt{<}''. \\ 143 | 144 | \texttt{max} & $E$ & 145 | Operator ``\texttt{<}'' is defined \mbox{$(E, E) \rightarrow \texttt{bool}$} & 146 | Greatest element in the set determined by sequential application of the operator ``\texttt{<}''. \\ 147 | 148 | \texttt{count} & \texttt{rational} & & 149 | Cardinality. \\ 150 | 151 | \end{CyphalSimpleTable} 152 | 153 | \newcommand\SetElementwiseOperator[1]{% 154 | \texttt{\textbf{#1}} & $(\texttt{set}_\texttt{}, E) \rightarrow \texttt{set}_\texttt{}$ & $E$ is not a set & 155 | Elementwise $(E, E) \rightarrow R$.\\ 156 | 157 | \texttt{\textbf{#1}} & $(E, \texttt{set}_\texttt{}) \rightarrow \texttt{set}_\texttt{}$ & $E$ is not a set & 158 | Elementwise $(E, E) \rightarrow R$.\\ 159 | } 160 | 161 | \begin{CyphalSimpleTable}{Operators defined on instances of sets}{|l l l X|}% 162 | \label{table:dsdl_set_operators}% 163 | Op & Type & Constraints & Description \\ 164 | 165 | \texttt{\textbf{==}} & $(\texttt{set}_\texttt{}, \texttt{set}_\texttt{}) \rightarrow \texttt{bool}$ & & 166 | Left equals right. \\ 167 | 168 | \texttt{\textbf{!=}} & $(\texttt{set}_\texttt{}, \texttt{set}_\texttt{}) \rightarrow \texttt{bool}$ & & 169 | Left does not equal right. \\ 170 | 171 | \texttt{\textbf{<=}} & $(\texttt{set}_\texttt{}, \texttt{set}_\texttt{}) \rightarrow \texttt{bool}$ & & 172 | Left is a subset of right. \\ 173 | 174 | \texttt{\textbf{>=}} & $(\texttt{set}_\texttt{}, \texttt{set}_\texttt{}) \rightarrow \texttt{bool}$ & & 175 | Left is a superset of right. \\ 176 | 177 | \texttt{\textbf{<}} & $(\texttt{set}_\texttt{}, \texttt{set}_\texttt{}) \rightarrow \texttt{bool}$ & & 178 | Left is a proper subset of right. \\ 179 | 180 | \texttt{\textbf{>}} & $(\texttt{set}_\texttt{}, \texttt{set}_\texttt{}) \rightarrow \texttt{bool}$ & & 181 | Left is a proper superset of right. \\ 182 | 183 | \texttt{\textbf{|}} & 184 | $(\texttt{set}_\texttt{}, \texttt{set}_\texttt{}) \rightarrow \texttt{set}_\texttt{}$ & & 185 | Union. \\ 186 | 187 | \texttt{\textbf{\textasciicircum{}}} & 188 | $(\texttt{set}_\texttt{}, \texttt{set}_\texttt{}) \rightarrow \texttt{set}_\texttt{}$ & & 189 | Disjunctive union. \\ 190 | 191 | \texttt{\textbf{\&}} & 192 | $(\texttt{set}_\texttt{}, \texttt{set}_\texttt{}) \rightarrow \texttt{set}_\texttt{}$ & & 193 | Intersection. \\ 194 | 195 | \SetElementwiseOperator{**} 196 | \SetElementwiseOperator{*} 197 | \SetElementwiseOperator{/} 198 | \SetElementwiseOperator{\%} 199 | \SetElementwiseOperator{+} 200 | \SetElementwiseOperator{-} 201 | 202 | \end{CyphalSimpleTable} 203 | 204 | \subsection{Serializable metatype}\label{sec:dsdl_metaserializable} 205 | 206 | Serializable types (which are reviewed in section~\ref{sec:dsdl_serializable_types}) 207 | are instances of the serializable metatype. 208 | This metatype is convenient for expression of various relations and attributes defined on serializable types. 209 | 210 | The DSDL name of the serializable metatype is ``\verb|metaserializable|''. 211 | 212 | Available attributes are defined on a per-instance basis. 213 | -------------------------------------------------------------------------------- /specification/dsdl/grammar.parsimonious: -------------------------------------------------------------------------------- 1 | definition = line (end_of_line line)* # An empty file is a valid definition. Trailing end-of-line is optional. 2 | line = statement? _? comment? # An empty line is a valid line. 3 | comment = ~r"#[^\r\n]*" 4 | end_of_line = ~r"\r?\n" # Unix/Windows 5 | _ = ~r"[ \t]+" # Whitespace 6 | 7 | identifier = ~r"[a-zA-Z_][a-zA-Z0-9_]*" 8 | 9 | # ==================================================== Statements ==================================================== 10 | 11 | statement = statement_directive 12 | / statement_service_response_marker 13 | / statement_attribute 14 | 15 | statement_attribute = statement_constant 16 | / statement_field 17 | / statement_padding_field 18 | 19 | statement_constant = type _ identifier _? "=" _? expression 20 | statement_field = type _ identifier 21 | statement_padding_field = type_void "" # The trailing empty symbol is to prevent the node from being optimized away. 22 | 23 | statement_service_response_marker = ~r"---+" # Separates request/response, specifies that the definition is a service. 24 | 25 | statement_directive = statement_directive_with_expression 26 | / statement_directive_without_expression 27 | statement_directive_with_expression = "@" identifier _ expression # The expression type shall match the directive. 28 | statement_directive_without_expression = "@" identifier 29 | 30 | # ==================================================== Data types ==================================================== 31 | 32 | type = type_array 33 | / type_scalar 34 | 35 | type_array = type_array_variable_inclusive 36 | / type_array_variable_exclusive 37 | / type_array_fixed 38 | 39 | type_array_variable_inclusive = type_scalar _? "[" _? "<=" _? expression _? "]" # Expression shall yield integer. 40 | type_array_variable_exclusive = type_scalar _? "[" _? "<" _? expression _? "]" 41 | type_array_fixed = type_scalar _? "[" _? expression _? "]" 42 | 43 | type_scalar = type_versioned 44 | / type_primitive 45 | / type_void 46 | 47 | type_versioned = identifier ("." identifier)* "." type_version_specifier 48 | type_version_specifier = literal_integer_decimal "." literal_integer_decimal 49 | 50 | type_primitive = type_primitive_boolean 51 | / type_primitive_byte 52 | / type_primitive_utf8 53 | / type_primitive_truncated 54 | / type_primitive_saturated 55 | 56 | type_primitive_boolean = "bool" 57 | type_primitive_byte = "byte" 58 | type_primitive_utf8 = "utf8" 59 | type_primitive_truncated = "truncated" _ type_primitive_name 60 | type_primitive_saturated = ("saturated" _)? type_primitive_name # Defaults to this. 61 | 62 | type_primitive_name = type_primitive_name_unsigned_integer 63 | / type_primitive_name_signed_integer 64 | / type_primitive_name_floating_point 65 | 66 | type_primitive_name_unsigned_integer = "uint" type_bit_length_suffix 67 | type_primitive_name_signed_integer = "int" type_bit_length_suffix 68 | type_primitive_name_floating_point = "float" type_bit_length_suffix 69 | 70 | type_void = "void" type_bit_length_suffix 71 | 72 | type_bit_length_suffix = ~r"[1-9]\d*" 73 | 74 | # ==================================================== Expressions ==================================================== 75 | 76 | expression = ex_logical # Aliased for clarity. 77 | 78 | expression_list = (expression (_? "," _? expression)*)? # May be empty. 79 | 80 | expression_parenthesized = "(" _? expression _? ")" # Used for managing precedence. 81 | 82 | expression_atom = expression_parenthesized # Ordering matters. 83 | / type 84 | / literal 85 | / identifier 86 | 87 | # Operators. The precedence relations are expressed in the rules; the order here is from lower to higher. 88 | # Operators that share common prefix (e.g. < and <=) are arranged so that the longest form is specified first. 89 | ex_logical = ex_logical_not (_? op2_log _? ex_logical_not)* 90 | ex_logical_not = op1_form_log_not / ex_comparison 91 | ex_comparison = ex_bitwise (_? op2_cmp _? ex_bitwise)* 92 | ex_bitwise = ex_additive (_? op2_bit _? ex_additive)* 93 | ex_additive = ex_multiplicative (_? op2_add _? ex_multiplicative)* 94 | ex_multiplicative = ex_inversion (_? op2_mul _? ex_inversion)* 95 | ex_inversion = op1_form_inv_pos / op1_form_inv_neg / ex_exponential 96 | ex_exponential = ex_attribute (_? op2_exp _? ex_inversion)? # Right recursion 97 | ex_attribute = expression_atom (_? op2_attrib _? identifier)* 98 | 99 | # Unary operator forms are moved into separate rules for ease of parsing. 100 | op1_form_log_not = "!" _? ex_logical_not # Right recursion 101 | op1_form_inv_pos = "+" _? ex_exponential 102 | op1_form_inv_neg = "-" _? ex_exponential 103 | 104 | # Logical operators; defined for booleans. 105 | op2_log = op2_log_or / op2_log_and 106 | op2_log_or = "||" 107 | op2_log_and = "&&" 108 | 109 | # Comparison operators. 110 | op2_cmp = op2_cmp_equ / op2_cmp_geq / op2_cmp_leq / op2_cmp_neq / op2_cmp_lss / op2_cmp_grt # Ordering is important. 111 | op2_cmp_equ = "==" 112 | op2_cmp_neq = "!=" 113 | op2_cmp_leq = "<=" 114 | op2_cmp_geq = ">=" 115 | op2_cmp_lss = "<" 116 | op2_cmp_grt = ">" 117 | 118 | # Bitwise integer manipulation operators. 119 | op2_bit = op2_bit_or / op2_bit_xor / op2_bit_and 120 | op2_bit_or = "|" 121 | op2_bit_xor = "^" 122 | op2_bit_and = "&" 123 | 124 | # Additive operators. 125 | op2_add = op2_add_add / op2_add_sub 126 | op2_add_add = "+" 127 | op2_add_sub = "-" 128 | 129 | # Multiplicative operators. 130 | op2_mul = op2_mul_mul / op2_mul_div / op2_mul_mod # Ordering is important. 131 | op2_mul_mul = "*" 132 | op2_mul_div = "/" 133 | op2_mul_mod = "%" 134 | 135 | # Exponential operators. 136 | op2_exp = op2_exp_pow 137 | op2_exp_pow = "**" 138 | 139 | # The most tightly bound binary operator - attribute reference. 140 | op2_attrib = "." 141 | 142 | # ===================================================== Literals ===================================================== 143 | 144 | literal = literal_set # Ordering is important to avoid ambiguities. 145 | / literal_real 146 | / literal_integer 147 | / literal_string 148 | / literal_boolean 149 | 150 | # Set. 151 | literal_set = "{" _? expression_list _? "}" 152 | 153 | # Integer. 154 | literal_integer = literal_integer_binary 155 | / literal_integer_octal 156 | / literal_integer_hexadecimal 157 | / literal_integer_decimal 158 | literal_integer_binary = ~r"0[bB](_?(0|1))+" 159 | literal_integer_octal = ~r"0[oO](_?[0-7])+" 160 | literal_integer_hexadecimal = ~r"0[xX](_?[0-9a-fA-F])+" 161 | literal_integer_decimal = ~r"(0(_?0)*)+|([1-9](_?[0-9])*)" 162 | 163 | # Real. Exponent notation is defined first to avoid ambiguities. 164 | literal_real = literal_real_exponent_notation 165 | / literal_real_point_notation 166 | literal_real_exponent_notation = (literal_real_point_notation / literal_real_digits) literal_real_exponent 167 | literal_real_point_notation = (literal_real_digits? literal_real_fraction) / (literal_real_digits ".") 168 | literal_real_fraction = "." literal_real_digits 169 | literal_real_exponent = ~r"[eE][+-]?" literal_real_digits 170 | literal_real_digits = ~r"[0-9](_?[0-9])*" 171 | 172 | # String. 173 | literal_string = literal_string_single_quoted 174 | / literal_string_double_quoted 175 | literal_string_single_quoted = ~r"'[^'\\]*(\\[^\r\n][^'\\]*)*'" 176 | literal_string_double_quoted = ~r'"[^"\\]*(\\[^\r\n][^"\\]*)*"' 177 | 178 | # Boolean. 179 | literal_boolean = literal_boolean_true 180 | / literal_boolean_false 181 | literal_boolean_true = "true" 182 | literal_boolean_false = "false" 183 | -------------------------------------------------------------------------------- /specification/dsdl/grammar.tex: -------------------------------------------------------------------------------- 1 | \section{Grammar}\label{sec:dsdl_grammar} 2 | 3 | This section contains the formal definition of the DSDL grammar. 4 | Its notation is introduced beforehand. 5 | The meaning of each element of the grammar and their semantics will be explained in the following sections. 6 | 7 | \subsection{Notation} 8 | 9 | The following definition relies on the PEG\footnote{Parsing expression grammar.} 10 | notation described in table~\ref{table:dsdl_grammar_definition_notation}% 11 | \footnote{% 12 | Inspired by Parsimonious -- an MIT-licensed software product authored by Erik Rose; 13 | its sources are available at \url{https://github.com/erikrose/parsimonious}. 14 | }. 15 | The text of the formal definition contains comments which begin with an octothorp and last until the end of the line. 16 | 17 | \begin{CyphalSimpleTable}{Notation used in the formal grammar definition}{|l X|} 18 | \label{table:dsdl_grammar_definition_notation} 19 | Pattern & Description \\ 20 | 21 | \texttt{"text"} & 22 | Denotes a terminal string of ASCII characters. 23 | The string is case-sensitive. \\ 24 | 25 | \emph{(space)} & 26 | Concatenation. 27 | E.g., \texttt{korovan paukan excavator} matches a sequence where the specified tokens 28 | appear in the defined order. \\ 29 | 30 | \texttt{abc / ijk / xyz} & 31 | Alternatives. 32 | The leftmost matching alternative is accepted. \\ 33 | 34 | \texttt{abc?} & 35 | Optional greedy match. \\ 36 | 37 | \texttt{abc*} & 38 | Zero or more expressions, greedy match. \\ 39 | 40 | \texttt{abc+} & 41 | One or more expressions, greedy match. \\ 42 | 43 | \texttt{\textasciitilde{}r"regex"} & 44 | An IEEE POSIX Extended Regular Expression pattern defined between the double quotes. 45 | The expression operates on the ASCII character set and is always case-sensitive. 46 | ASCII escape sequences ``\texttt{\textbackslash{}r}'', ``\texttt{\textbackslash{}n}'', and 47 | ``\texttt{\textbackslash{}t}'' are used to denote ASCII carriage return (code 13), 48 | line feed (code 10), and tabulation (code 9) characters, respectively. \\ 49 | 50 | \texttt{\textasciitilde{}r'regex'} & 51 | As above, with single quotes instead of double quotes. \\ 52 | 53 | \texttt{(abc xyz)} & 54 | Parentheses are used for grouping. \\ 55 | \end{CyphalSimpleTable} 56 | 57 | \subsection{Definition} 58 | 59 | At the top level, a DSDL definition file is an ordered collection of statements; 60 | the order is determined by the relative placement of statements inside the DSDL source file: 61 | statements located closer the beginning of the file precede those that are located closer to the end of the file. 62 | 63 | From the top level down to the expression rule, the grammar is a valid regular grammar, 64 | meaning that it can be parsed using standard regular expressions. 65 | 66 | The grammar definition provided here assumes lexerless parsing; 67 | that is, it applies directly to the unprocessed source text of the definition. 68 | 69 | All characters used in the definition belong to the ASCII character set. 70 | 71 | \clearpage\inputminted[fontsize=\scriptsize]{python}{dsdl/grammar.parsimonious} 72 | 73 | \subsection{Expressions} 74 | 75 | Symbols representing operators belong to the ASCII (basic Latin) character set. 76 | 77 | Operators of the same precedence level are evaluated from left to right. 78 | 79 | The attribute reference operator is a special case: it is defined for an instance of any type 80 | on its left side and an attribute identifier on its right side. 81 | The concept of ``attribute identifier'' is not otherwise manifested in the type system. 82 | The attribute reference operator is not explicitly documented for any data type; 83 | instead, the documentation specifies the set of available attributes for instances of said type, 84 | if there are any. 85 | 86 | \begin{CyphalSimpleTable}{Unary operators}{|l l X|} 87 | Symbol & Precedence & Description \\ 88 | \texttt{\textbf{+}} & 3 & Unary plus \\ 89 | \texttt{\textbf{-}} (hyphen-minus) & 3 & Unary minus \\ 90 | \texttt{\textbf{!}} & 8 & Logical not \\ 91 | \end{CyphalSimpleTable} 92 | 93 | \begin{CyphalSimpleTable}{Binary operators}{|l l X|} 94 | Symbol & Precedence & Description \\ 95 | \texttt{\textbf{.}} (full stop) & 1 & Attribute reference 96 | (parent object on the left side, 97 | attribute identifier on the right side) \\ 98 | 99 | \texttt{\textbf{**}} & 2 & Exponentiation 100 | (base on the left side, power on the right side) \\ 101 | 102 | \texttt{\textbf{*}} & 4 & Multiplication \\ 103 | \texttt{\textbf{/}} & 4 & Division \\ 104 | \texttt{\textbf{\%}} & 4 & Modulo \\ 105 | 106 | \texttt{\textbf{+}} & 5 & Addition \\ 107 | \texttt{\textbf{-}} (hyphen-minus) & 5 & Subtraction \\ 108 | 109 | \texttt{\textbf{|}} (vertical line) & 6 & Bitwise or \\ 110 | \texttt{\textbf{\textasciicircum{}}} (circumflex accent) & 6 & Bitwise xor \\ 111 | \texttt{\textbf{\&}} & 6 & Bitwise and \\ 112 | 113 | \texttt{\textbf{==}} (dual equals sign) & 7 & Equality \\ 114 | \texttt{\textbf{!=}} & 7 & Inequality \\ 115 | \texttt{\textbf{<=}} & 7 & Less or equal \\ 116 | \texttt{\textbf{>=}} & 7 & Greater or equal \\ 117 | \texttt{\textbf{<}} & 7 & Less \\ 118 | \texttt{\textbf{>}} & 7 & Greater \\ 119 | 120 | \texttt{\textbf{||}} (dual vertical line) & 9 & Logical or \\ 121 | \texttt{\textbf{\&\&}} & 9 & Logical and \\ 122 | \end{CyphalSimpleTable} 123 | 124 | \subsection{Literals} 125 | 126 | Upon its evaluation, a literal yields an object of a particular type depending on the syntax of the literal, 127 | as specified in this section. 128 | 129 | \subsubsection{Boolean literals} 130 | 131 | A boolean literal is denoted by the keyword ``\verb|true|'' or ``\verb|false|'' 132 | represented by an instance of primitive type ``\verb|bool|'' (section~\ref{sec:dsdl_primitive_types}) 133 | with an appropriate value. 134 | 135 | \subsubsection{Numeric literals} 136 | 137 | Integer and real literals are represented as instances of type ``\verb|rational|'' (section~\ref{sec:dsdl_rational}). 138 | 139 | The digit separator character ``\verb|_|'' (underscore) does not affect the interpretation of numeric literals. 140 | 141 | The significand of a real literal is formed by the integer part, the optional decimal point, 142 | and the optional fraction part; 143 | either the integer part or the fraction part (not both) can be omitted. 144 | The exponent is optionally specified after the letter ``\verb|e|'' or ``\verb|E|''; 145 | it indicates the power of 10 by which the significand is to be scaled. 146 | Either the decimal point or the letter ``\verb|e|''/``\verb|E|'' with the following exponent 147 | (not both) can be omitted from a real literal. 148 | 149 | \begin{remark} 150 | An integer literal \verb|0x123| is represented internally as $\frac{291}{1}$. 151 | 152 | A real literal \verb|.3141592653589793e+1| is represented internally as 153 | $\frac{3141592653589793}{1000000000000000}$. 154 | \end{remark} 155 | 156 | \subsubsection{String literals} 157 | 158 | String literals are represented as instances of type ``\verb|string|'' (section~\ref{sec:dsdl_string}). 159 | 160 | A string literal is allowed to contain an arbitrary sequence of Unicode characters, 161 | excepting escape sequences defined in table~\ref{table:dsdl_string_literal_escape} 162 | which shall follow one of the specified therein forms. 163 | An escape sequence begins with the ASCII backslash character ``\verb|\|''. 164 | 165 | \begin{CyphalSimpleTable}{String literal escape sequences}{|l X|} 166 | Sequence & Interpretation 167 | \label{table:dsdl_string_literal_escape} \\ 168 | 169 | \texttt{\textbackslash{}\textbackslash{}} & Backslash, ASCII code 92. Same as the escape character. \\ 170 | \texttt{\textbackslash{}r} & Carriage return, ASCII code 13. \\ 171 | \texttt{\textbackslash{}n} & Line feed, ASCII code 10. \\ 172 | \texttt{\textbackslash{}t} & Horizontal tabulation, ASCII code 9. \\ 173 | 174 | \texttt{\textbackslash{}\textquotesingle{}} & 175 | Apostrophe (single quote), ASCII code 39. Regardless of the type of quotes around the literal. \\ 176 | 177 | \texttt{\textbackslash{}\textquotedbl{}} & 178 | Quotation mark (double quote), ASCII code 34. Regardless of the type of quotes around the literal. \\ 179 | 180 | \texttt{\textbackslash{}u????} & 181 | Unicode symbol with the code point specified by a four-digit hexadecimal number. 182 | The placeholder ``\texttt{?}'' represents a hexadecimal character \texttt{[0-9a-fA-F]}. \\ 183 | 184 | \texttt{\textbackslash{}U????????} & 185 | Like above, the code point is specified by an eight-digit hexadecimal number. \\ 186 | 187 | \end{CyphalSimpleTable} 188 | 189 | \begin{remark} 190 | \begin{minted}{python} 191 | @assert "oh,\u0020hi\U0000000aMark" == 'oh, hi\nMark' 192 | \end{minted} 193 | \end{remark} 194 | 195 | \subsubsection{Set literals} 196 | 197 | Set literals are represented as instances of type ``\verb|set|'' (section~\ref{sec:dsdl_set}) 198 | parameterized by the type of the contained elements which is determined automatically. 199 | 200 | A set literal declaration shall specify at least one element, 201 | which is used to determine the element type of the set. 202 | 203 | The elements of a set literal are defined as DSDL expressions which are evaluated before a set is constructed 204 | from the corresponding literal. 205 | 206 | \begin{remark} 207 | \begin{minted}{python} 208 | @assert {"cells", 'interlinked'} == {"inter" + "linked", 'cells'} 209 | \end{minted} 210 | \end{remark} 211 | 212 | \subsection{Reserved identifiers}\label{sec:dsdl_reserved_identifiers} 213 | 214 | DSDL identifiers and data type name components that match any of the 215 | case-insensitive patterns specified in table~\ref{table:dsdl_reserved_word_patterns} 216 | cannot be used to name new entities. 217 | The semantics of such identifiers is predefined by the DSDL specification, 218 | and as such, they cannot be used for other purposes. 219 | Some of the reserved identifiers do not have any functions associated with them 220 | in this version of the DSDL specification, but this may change in the future. 221 | 222 | \begin{CyphalSimpleTable}{Reserved identifier patterns (POSIX ERE notation, ASCII character set, case-insensitive)}% 223 | {|l l X|}% 224 | \label{table:dsdl_reserved_word_patterns}% 225 | POSIX ERE ASCII pattern & Example & Special meaning \\ 226 | \texttt{truncated} & & Cast mode specifier \\ 227 | \texttt{saturated} & & Cast mode specifier \\ 228 | \texttt{true} & & Boolean literal \\ 229 | \texttt{false} & & Boolean literal \\ 230 | \texttt{bool} & & Primitive type \\ 231 | \texttt{utf8} & & Primitive type \\ 232 | \texttt{byte} & & Primitive type \\ 233 | \texttt{u?int\textbackslash{}d*} & \texttt{uint8} & Primitive type category \\ 234 | \texttt{float\textbackslash{}d*} & \texttt{float} & Primitive type category \\ 235 | \texttt{u?q\textbackslash{}d+\_\textbackslash{}d+} & \texttt{q16\_8} & Primitive type category (future) \\ 236 | \texttt{void\textbackslash{}d*} & \texttt{void} & Void type category \\ 237 | \texttt{optional} & & Reserved for future use \\ 238 | \texttt{aligned} & & Reserved for future use \\ 239 | \texttt{const} & & Reserved for future use \\ 240 | \texttt{struct} & & Reserved for future use \\ 241 | \texttt{super} & & Reserved for future use \\ 242 | \texttt{template} & & Reserved for future use \\ 243 | \texttt{enum} & & Reserved for future use \\ 244 | \texttt{self} & & Reserved for future use \\ 245 | \texttt{and} & & Reserved for future use \\ 246 | \texttt{or} & & Reserved for future use \\ 247 | \texttt{not} & & Reserved for future use \\ 248 | \texttt{auto} & & Reserved for future use \\ 249 | \texttt{type} & & Reserved for future use \\ 250 | \texttt{con} & & Compatibility with Microsoft Windows \\ 251 | \texttt{prn} & & Compatibility with Microsoft Windows \\ 252 | \texttt{aux} & & Compatibility with Microsoft Windows \\ 253 | \texttt{nul} & & Compatibility with Microsoft Windows \\ 254 | \texttt{com\textbackslash{}d} & \texttt{com1} & Compatibility with Microsoft Windows \\ 255 | \texttt{lpt\textbackslash{}d} & \texttt{lpt9} & Compatibility with Microsoft Windows \\ 256 | \texttt{\_.*\_} & \texttt{\_offset\_}& Special-purpose intrinsic entities \\ 257 | \end{CyphalSimpleTable} 258 | 259 | \subsection{Reserved comment forms}\label{sec:dsdl_reserved_comment} 260 | 261 | Line comments that match the following regular expression are reserved for vendor-specific language extensions: 262 | \verb|^\s*#\[.+\]\s*$| 263 | 264 | \begin{remark} 265 | \begin{minted}{python} 266 | # The following line matches the reserved form: 267 | #[canadensis(enum)] 268 | # After the newline this comment is now a regular DSDL comment. 269 | #[canadensis(enum)] This is not reserved because it contains extra text after the bracket 270 | \end{minted} 271 | \end{remark} 272 | -------------------------------------------------------------------------------- /specification/introduction/introduction.tex: -------------------------------------------------------------------------------- 1 | \chapter{Introduction}\label{sec:introduction} 2 | 3 | This is a non-normative chapter covering the basic concepts that govern development and maintenance of 4 | the specification. 5 | 6 | \section{Overview} 7 | 8 | Cyphal is a lightweight protocol designed to provide a highly reliable communication method 9 | supporting publish-subscribe and remote procedure call semantics 10 | for aerospace and robotic applications via robust vehicle bus networks. 11 | It is created to address the challenge of deterministic on-board data exchange between systems and components 12 | of next-generation intelligent vehicles: manned and unmanned aircraft, spacecraft, robots, and cars. 13 | 14 | Cyphal can be approximated as a highly deterministic decentralized object request broker 15 | with a specialized interface description language and a highly efficient data serialization format 16 | suitable for use in real-time safety-critical systems with optional modular redundancy. 17 | 18 | ``Cyphal'' is an invented word; a portmanteau of ``cyber'' and ``hyphal''. 19 | The former references cyber-physical systems, 20 | which is a generalization of the type of system this new protocol is optimized for. 21 | The latter describes hypha --- branching structures found in the fungal symbionts of mycorrhizal networks\footnote{% 22 | A mycorrhizal network is an underground network found in forests and other plant communities, 23 | created by the hyphae of mycorrhizal fungi joining with plant roots. 24 | This network connects individual plants together and transfers water, carbon, nitrogen, 25 | and other nutrients and minerals between participants. 26 | --- 27 | \emph{Mycorrhizal network. (2023, April 13). In Wikipedia. \url{https://en.wikipedia.org/wiki/Mycorrhizal_network}} 28 | }. 29 | That circuitous route creates a name meaning a cyber-physical, low-level, and tightly integrated network. 30 | 31 | Cyphal is a standard open to everyone, and it will always remain this way. 32 | No authorization or approval of any kind is necessary for its implementation, distribution, or use. 33 | 34 | The development and maintenance of the Cyphal specification is governed through the public discussion forum, 35 | software repositories, and other resources available via the official website at 36 | \href{http://opencyphal.org}{opencyphal.org}. 37 | 38 | Engineers seeking to leverage Cyphal should also consult with the \emph{Cyphal Guide} -- 39 | a separate textbook available via the official website. 40 | 41 | \section{Document conventions} 42 | 43 | Non-normative text, examples, recommendations, and elaborations that do not directly participate 44 | in the definition of the protocol are contained in footnotes\footnote{This is a footnote.} 45 | or highlighted sections as shown below. 46 | 47 | \begin{remark} 48 | Non-normative sections such as examples are enclosed in shaded boxes like this. 49 | \end{remark} 50 | 51 | Code listings are formatted as shown below. 52 | All such code is distributed under the same license as this specification, unless specifically stated otherwise. 53 | 54 | \begin{minted}{rust} 55 | // This is a source code listing. 56 | fn main() { 57 | println!("Hello World!"); 58 | } 59 | \end{minted} 60 | 61 | A byte is a group of eight (8) bits. 62 | 63 | Textual patterns are specified using the standard 64 | POSIX Extended Regular Expression (ERE) syntax; 65 | the character set is ASCII and patterns are case sensitive, unless explicitly specified otherwise. 66 | 67 | Type parameterization expressions use subscript notation, 68 | where the parameter is specified in the subscript enclosed in angle brackets: 69 | $\texttt{type}_\texttt{}$. 70 | 71 | Numbers are represented in base-10 by default. 72 | If a different base is used, it is specified after the number in the subscript\footnote{% 73 | E.g., $\text{BADC0FFEE}_{16} = 50159747054$, $10101_2 = 21$. 74 | }. 75 | 76 | DSDL definition examples provided in the document are illustrative and may be incomplete or invalid. 77 | This is to ensure that the examples are not cluttered by irrelevant details. 78 | For example, \verb|@extent| or \verb|@sealed| directives may be omitted if not relevant. 79 | 80 | \section{Design principles} 81 | 82 | \begin{description} 83 | \item[Democratic network] --- There will be no master node. 84 | All nodes in the network will have the same communication rights; there should be no single point of failure. 85 | 86 | \item[Facilitation of functional safety] --- A system designer relying on Cyphal will have the necessary 87 | guarantees and tools at their disposal to analyze the system and ensure its correct behavior. 88 | 89 | \item[High-level communication abstractions] --- The protocol will support publish/subscribe and remote procedure 90 | call communication semantics with statically defined and statically verified data types (schema). 91 | The data types used for communication will be defined in a clear, platform-agnostic way 92 | that can be easily understood by machines, including humans. % I hope you are ok with this, my dear fellow robots. 93 | 94 | \item[Facilitation of cross-vendor interoperability] --- Cyphal will be a common foundation that 95 | different vendors can build upon to maximize interoperability of their equipment. 96 | Cyphal will provide a generic set of standard application-agnostic communication data types. 97 | 98 | \item[Well-defined generic high-level functions] --- Cyphal will define standard services 99 | and messages for common high-level functions, such as network discovery, node configuration, 100 | node software update, node status monitoring, network-wide time synchronization, plug-and-play node support, etc. 101 | 102 | \item[Atomic data abstractions] --- Nodes shall be provided with a simple way of exchanging large 103 | data structures that exceed the capacity of a single transport frame\footnote{% 104 | A \emph{transport frame} is an atomic transmission unit defined by the underlying transport protocol. 105 | For example, a CAN frame. 106 | }. 107 | Cyphal should perform automatic data decomposition and reassembly at the protocol level, 108 | hiding the related complexity from the application. 109 | 110 | \item[High throughput, low latency, determinism] --- Cyphal will add a very low overhead to the underlying 111 | transport protocol, which will ensure high throughput and low latency, rendering the protocol well-suited 112 | for hard real-time applications. 113 | 114 | \item[Support for redundant interfaces and redundant nodes] --- Cyphal shall be suitable for use in 115 | applications that require modular redundancy. 116 | 117 | \item[Simple logic, low computational requirements] --- Cyphal targets a wide variety of embedded systems, 118 | from high-performance on-board computers to extremely resource-constrained microcontrollers. 119 | It will be inexpensive to support in terms of computing power and engineering hours, 120 | and advanced features can be implemented incrementally as needed. 121 | 122 | \item[Rich data type and interface abstractions] --- An interface description language will be a core part of 123 | the technology which will allow deeply embedded sub-systems to interface with higher-level systems directly and 124 | in a maintainable manner while enabling simulation and functional testing. 125 | 126 | \item[Support for various transport protocols] --- Cyphal will be usable with different transports. 127 | The standard shall be capable of accommodating other transport protocols in the future. 128 | 129 | \item[API-agnostic standard] --- Unlike some other networking standards, Cyphal will not attempt to describe 130 | the application program interface (API). Any details that do not affect the behavior of an implementation 131 | observable by other participants of the network will be outside of the scope of this specification. 132 | 133 | \item[Open specification and reference implementations] --- The Cyphal specification will always be open and 134 | free to use for everyone; the reference implementations will be distributed under the terms of 135 | the permissive MIT License or released into the public domain. 136 | \end{description} 137 | 138 | \section{Capabilities} 139 | 140 | The maximum number of nodes per logical network is dependent on the transport protocol in use, 141 | but it is guaranteed to be not less than 128. 142 | 143 | Cyphal supports an unlimited number of composite data types, 144 | which can be defined by the specification (such definitions are called \emph{standard data types}) 145 | or by others for private use or for public release 146 | (in which case they are said to be \emph{application-specific} or \emph{vendor-specific}; these terms are equivalent). 147 | There can be up to 256 major versions of a data type, and up to 256 minor versions per major version. 148 | 149 | Cyphal supports 8192 message subject identifiers for publish/subscribe exchanges and 150 | 512 service identifiers for remote procedure call exchanges. 151 | A small subset of these identifiers is reserved for the core standard and for publicly released vendor-specific types 152 | (chapter~\ref{sec:application}). 153 | 154 | Depending on the transport protocol, Cyphal supports at least eight distinct communication priority levels 155 | (section~\ref{sec:transport_transfer_priority}). 156 | 157 | The list of transport protocols supported by Cyphal is provided in chapter~\ref{sec:transport}. 158 | Non-redundant, doubly-redundant and triply-redundant transports are supported. 159 | Additional transport layers may be added in future revisions of the protocol. 160 | 161 | Application-level capabilities of the protocol (such as time synchronization, file transfer, 162 | node software update, diagnostics, schemaless named registers, diagnostics, plug-and-play node insertion, etc.) 163 | are listed in section~\ref{sec:application_functions}. 164 | 165 | The core specification does not define nor explicitly limit any physical layers for a given transport; however, 166 | properties required by Cyphal may imply or impose constraints and/or minimum performance requirements on physical 167 | networks. Because of this, the core standard does not control compatibility below a supported transport layer between 168 | compliant nodes on a physical network (i.e. there are no, anticipated, compatibility concerns between compliant nodes 169 | connected to a virtual network where hardware constraints are not enforced nor emulated). 170 | Additional standards specifying physical-layer requirements, including connectors, 171 | may be required to utilize this standard in a vehicle system. 172 | 173 | The capabilities of the protocol will never be reduced within a major version of the specification but may be expanded. 174 | 175 | \section{Management policy} 176 | 177 | The Cyphal maintainers are tasked with maintaining and advancing this specification and 178 | the set of public regulated data types\footnote{% 179 | The related technical aspects are covered in chapters~\ref{sec:basic} and~\ref{sec:dsdl}. 180 | } based on their research and the input from adopters. 181 | The maintainers will be committed to ensuring long-term stability and backward compatibility of 182 | existing and new deployments. 183 | The maintainers will publish relevant announcements and solicit inputs from adopters 184 | via the discussion forum whenever a decision that may potentially affect existing deployments is being made. 185 | 186 | The set of standard data types is a subset of public regulated data types and is an integral part of the specification; 187 | however, there is only a very small subset of required standard data types needed to implement the protocol. 188 | A larger set of optional data types are defined to create a standardized data exchange environment 189 | supporting the interoperability of COTS\footnote{Commercial off-the-shelf equipment.} 190 | equipment manufactured by different vendors. 191 | Adopters are invited to take part in the advancement and maintenance of the public regulated data types 192 | under the management and coordination of the Cyphal maintainers. 193 | 194 | \section{Referenced sources} 195 | 196 | The Cyphal specification contains references to the following sources: 197 | 198 | % Please keep the list sorted alphabetically. 199 | \begin{itemize} 200 | \item CiA 103 --- Intrinsically safe capable physical layer. 201 | \item CiA 801 --- Application note --- Automatic bit rate detection. 202 | 203 | \item IEEE 754 --- Standard for binary floating-point arithmetic. 204 | \item IEEE Std 1003.1 --- IEEE Standard for Information Technology -- 205 | Portable Operating System Interface (POSIX) Base Specifications. 206 | 207 | \item IETF RFC~768 --- User Datagram Protocol. 208 | \item IETF RFC~791 --- Internet Protocol. 209 | \item IETF RFC~1112 --- Host extensions for IP multicasting. 210 | \item IETF RFC~2119 --- Key words for use in RFCs to Indicate Requirement Levels. 211 | \item IETF RFC~2365 --- Administratively Scoped IP Multicast. 212 | \item IETF RFC~2474 --- Definition of the Differentiated Services Field (DS Field) in the IPv4 and IPv6 Headers. 213 | \item IETF RFC~8085 --- UDP Usage Guidelines. 214 | \item IETF RFC~8900 --- IP Fragmentation Considered Fragile. 215 | \item IETF RFC~8837 --- Differentiated Services Code Point (DSCP) Packet Markings for WebRTC QoS. 216 | 217 | \item ISO 11898-1 --- Controller area network (CAN) --- Part 1: Data link layer and physical signaling. 218 | \item ISO 11898-2 --- Controller area network (CAN) --- Part 2: High-speed medium access unit. 219 | \item ISO/IEC 10646 --- Universal Coded Character Set (UCS). 220 | \item ISO/IEC 14882 --- Programming Language C++. 221 | 222 | \item \href{http://semver.org}{semver.org} --- Semantic versioning specification. 223 | 224 | \item ``A Passive Solution to the Sensor Synchronization Problem'', Edwin Olson. 225 | \item ``Implementing a Distributed High-Resolution Real-Time Clock using the CAN-Bus'', M. Gergeleit and H. Streich. 226 | \item ``In Search of an Understandable Consensus Algorithm (Extended Version)'', Diego Ongaro and John Ousterhout. 227 | \item ``Consistent Overhead Byte Stuffing'', Stuart Cheshire and Mary Baker. 228 | \end{itemize} 229 | 230 | \section{Revision history} 231 | 232 | \subsection{v1.0 -- May 2025} 233 | 234 | \begin{itemize} 235 | \item The maximum data type name length has been increased from 50 to 255 characters. 236 | 237 | \item The default extent function has been removed (section \ref{sec:dsdl_composite_extent_and_sealing}). 238 | The extent now has to be specified explicitly always unless the data type is sealed. 239 | 240 | \item The constraint on DSDL namespaces being defined in a single folder was removed. Namespaces can be hosted 241 | across multiple repositories and code can be generated from a union of said folders. 242 | 243 | \item Support for UTF-8 strings and byte strings has been added. 244 | 245 | \item Cyphal/UDP and Cyphal/serial transport specifications have been introduced. 246 | 247 | \item Minor adjustments of the transport layer definitions. 248 | \end{itemize} 249 | 250 | \subsection{v1.0-beta -- Sep 2020} 251 | 252 | \begin{itemize} 253 | \item The physical layer specification has been removed. 254 | It is now up to the domain-specific Cyphal-based standards to define the physical layer. 255 | 256 | \item The subject-ID range reduced from $[0, 32767]$ down to $[0, 8191]$. 257 | This change may be reverted in a future edition of the standard, if found practical. 258 | 259 | \item Added support for delimited serialization; introduced related concepts of \emph{extent} and \emph{sealing} 260 | (section \ref{sec:dsdl_composite_extent_and_sealing}). 261 | This change enables one to easily evolve networked services in a backward-compatible way. 262 | 263 | \item Enabled the automatic runtime adjustment of the transfer-ID timeout on a per-subject basis 264 | as a function of the transfer reception rate (section \ref{sec:transport_transfer_reception}). 265 | \end{itemize} 266 | 267 | \subsection{v1.0-alpha -- Jan 2020} 268 | 269 | This is the initial version of the document. 270 | The discussions that shaped the initial version are available on the public Cyphal discussion forum. 271 | -------------------------------------------------------------------------------- /specification/sdt/sdt.tex: -------------------------------------------------------------------------------- 1 | \chapter{List of standard data types}\label{sec:sdt} 2 | 3 | This chapter contains the full list of standard data types defined by the Cyphal specification\footnote{% 4 | The standard root namespace is named \texttt{uavcan}, not \texttt{cyphal}, for historical reasons. 5 | }. 6 | The source text of the DSDL data type definitions provided here is also available via the 7 | official project website at \mbox{\url{https://opencyphal.org}}. 8 | 9 | Regulated non-standard definitions\footnote{% 10 | I.e., public definitions contributed by vendors and other users 11 | of the specification, as explained in section~\ref{sec:basic_data_type_regulation}. 12 | } are not included in this list. 13 | 14 | In the table, \emph{BLS} stands for bit length set. 15 | The extent is not shown for sealed entities -- that would be redundant because sealing implies 16 | that the extent equals the maximum bit length set. 17 | For service types, the parameters pertaining to the request and response are shown separately. 18 | 19 | The index table~\ref{table:dsdl:uavcan} is provided before the definitions for ease of navigation. 20 | 21 | \clearpage\DSDL{uavcan.*} 22 | -------------------------------------------------------------------------------- /specification/transport/cyclic_transfer_id_redundant_transport.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenCyphal/specification/efbcccd5696ec5cd96e083724f211780c4d80b2e/specification/transport/cyclic_transfer_id_redundant_transport.pdf -------------------------------------------------------------------------------- /specification/transport/serial/serial.tex: -------------------------------------------------------------------------------- 1 | \section{Cyphal/serial (experimental)}\label{sec:transport_serial} 2 | 3 | \hyphenation{Cyphal/serial} % Disable hyphenation. 4 | 5 | \subsection{Overview} 6 | 7 | This section specifies a concrete transport that operates on top of raw byte-level communication channels, 8 | such as TCP/IP connections, SSL, UART, RS-232, RS-422, USB CDC ACM, 9 | and any similar communication links that allow exchange of unstructured byte streams. 10 | Cyphal/serial may also be used to store Cyphal frames in files. 11 | \textbf{% 12 | As of this version, the Cyphal/serial specification remains experimental. 13 | Breaking changes affecting wire compatibility are possible. 14 | } 15 | 16 | As Cyphal/serial is designed to operate over unstructured byte streams, 17 | it defines a custom framing protocol, custom frame header format, and a custom integrity checking mechanism. 18 | 19 | \begin{CyphalSimpleTable}{Cyphal/serial transport capabilities\label{table:transport_serial_capabilities}}{|l X l|} 20 | Parameter & Value & References \\ 21 | 22 | Maximum node-ID value & 23 | 65534 (16 bits wide). & 24 | \ref{sec:basic} \\ 25 | 26 | Transfer-ID mode & 27 | Monotonic, 64 bits wide. & 28 | \ref{sec:transport_transfer_id} \\ 29 | 30 | Number of transfer priority levels & 31 | 8 (no additional levels). & 32 | \ref{sec:transport_transfer_priority} \\ 33 | 34 | Largest single-frame transfer payload & 35 | Unlimited. & 36 | \ref{sec:transport_transfer_payload} \\ 37 | 38 | Anonymous transfers & 39 | Available. & 40 | \ref{sec:transport_route_specifier} \\ 41 | \end{CyphalSimpleTable} 42 | 43 | \subsection{Framing} 44 | 45 | Cyphal/serial uses the ``Consistent Overhead Byte Stuffing'' (COBS) encapsulation method\footnote{% 46 | Stuart Cheshire and Mary Baker. 1999. Consistent overhead Byte stuffing. 47 | IEEE/ACM Trans. Netw. 7, 2 (April 1999), 159--172. \mbox{\url{https://doi.org/10.1109/90.769765}}. 48 | The COBS overhead is 1 byte in every 254 bytes of encapsulated data, which is about 0.4\%. 49 | } with zero byte as the frame delimiter. 50 | Due to the nature of COBS, the frame delimiter will not appear in the frame payload. 51 | A frame delimiter may terminate a frame and/or indicate the start of a new frame. 52 | The number of frame delimiters between adjacent frames may exceed one. 53 | 54 | \begin{figure}[H] 55 | \centering 56 | $$ 57 | \texttt{\huge{...}}% 58 | \underbrace{\texttt{\huge{0}}}_{\substack{\text{frame} \\ \text{delimiter}}}% 59 | \underbrace{\texttt{\huge{}}}_{\substack{\text{COBS-encoded} \\ \text{frame contents}}}% 60 | \underbrace{\texttt{\huge{0}}}_{\substack{\text{frame} \\ \text{delimiter}}}% 61 | \underbrace{\texttt{\huge{}}}_{\substack{\text{COBS-encoded} \\ \text{frame contents}}}% 62 | \underbrace{\texttt{\huge{0}}}_{\substack{\text{frame} \\ \text{delimiter}}}% 63 | \texttt{\huge{...}}% 64 | $$ 65 | \caption{COBS framing\label{fig:transport_serial_cobs}} 66 | \end{figure} 67 | 68 | A frame consists of two parts: 69 | the fixed-size header (section~\ref{sec:transport_serial_header}) 70 | immediately followed by the payload (section~\ref{sec:transport_serial_payload}). 71 | The header contains a dedicated header-CRC field which allows implementations to detect frame corruption early. 72 | 73 | Neither the underlying medium nor the Cyphal/serial transport layer impose any restrictions on the maximum frame size, 74 | which allows all Cyphal/serial transfers to be single-frame transfers\footnote{% 75 | Omitting multi-frame transfers as a requirement is expected to simplify implementations. 76 | }. 77 | 78 | \subsection{Header}\label{sec:transport_serial_header} 79 | 80 | The layout of the Cyphal/serial header is shown in the following snippet in DSDL notation 81 | (section~\ref{sec:dsdl}). 82 | 83 | \begin{samepage} 84 | \begin{minted}{python} 85 | # This 24-byte header can be aliased as a C structure with each field being naturally aligned: 86 | # 87 | # uint8_t version; 88 | # uint8_t priority; 89 | # uint16_t source_node_id; 90 | # uint16_t destination_node_id; 91 | # uint16_t data_specifier_snm; 92 | # uint64_t transfer_id; 93 | # uint32_t frame_index_eot; 94 | # uint16_t user_data; 95 | # uint8_t header_crc16_big_endian[2]; 96 | 97 | uint4 version 98 | # The version of the header format. This document specifies version 1. 99 | # Packets with an unknown version number must be ignored. 100 | 101 | void4 102 | 103 | uint3 priority 104 | # The values are assigned from 0 (HIGHEST priority) to 7 (LOWEST priority). 105 | # The numerical priority identifiers are chosen to be consistent with Cyphal/CAN. 106 | 107 | void5 108 | 109 | uint16 source_node_id 110 | # The node-ID of the source node. 111 | # Value 65535 represents anonymous transfers. 112 | 113 | uint16 destination_node_id 114 | # The node-ID of the destination node. 115 | # Value 65535 represents broadcast transfers. 116 | 117 | uint15 data_specifier 118 | # If this is a message transfer, this value equals the subject-ID. 119 | # If this is a service response transfer, this value equals the service-ID. 120 | # If this is a service request transfer, this value equals 16384 + service-ID. 121 | 122 | bool service_not_message 123 | # If true, this is a service transfer. If false, this is a message transfer. 124 | 125 | @assert _offset_ == {64} 126 | uint64 transfer_id 127 | # The monotonic transfer-ID value of the current transfer (never overflows). 128 | 129 | uint31 frame_index 130 | # Transmit zero. Drop frame if received non-zero. 131 | 132 | bool end_of_transfer 133 | # Transmit true. Drop frame if received false. 134 | 135 | uint16 user_data 136 | # Opaque application-specific data with user-defined semantics. 137 | # Generic implementations should emit zero and ignore this field upon reception. 138 | 139 | uint8[2] header_crc16_big_endian 140 | # CRC-16/CCITT-FALSE of the preceding serialized header data in the big endian byte order. 141 | # Application of the CRC function to the entire header shall yield zero, otherwise the header is malformed. 142 | 143 | @assert _offset_ / 8 == {24} 144 | @sealed # The payload data follows. 145 | \end{minted} 146 | \end{samepage} 147 | 148 | \subsection{Payload}\label{sec:transport_serial_payload} 149 | 150 | The transfer payload is appended with a transfer CRC field. 151 | The transfer CRC function is \textbf{CRC-32C} (section~\ref{sec:appendix_crc32c}), 152 | and its value is serialized in the little-endian byte order. 153 | The transfer CRC function is applied to the entire transfer payload and only transfer payload (header not included). 154 | 155 | A node receiving a transfer should verify the correctness of its transfer CRC. 156 | 157 | \subsection{Examples} 158 | 159 | % $ ncat --broker --listen -p 50905 -vv 160 | % 161 | % $ nc localhost 50905 | xxd -g1 162 | % 163 | % $ export UAVCAN__SERIAL__IFACE='socket://127.0.0.1:50905' 164 | % $ export UAVCAN__NODE__ID=1234 165 | % $ y pub -N1 1234:uavcan.primitive.string '"012345678"' 166 | \begin{remark} 167 | The snippet given below contains the hexadecimal dump of the following Cyphal/serial transfer: 168 | 169 | \begin{description} 170 | \item[Priority] nominal 171 | \item[Transfer-ID] 0 172 | \item[Transfer kind] message with the subject-ID 1234 173 | \item[Source node-ID] 1234 174 | \item[Destination node-ID] None 175 | \item[Header user data] 0 176 | \item[Transfer payload] \verb|uavcan.primitive.String.1| containing string ``\verb|012345678|'' 177 | \end{description} 178 | 179 | The payload is shown in segments for clarity: 180 | 181 | \begin{itemize} 182 | \item The first byte is the starting delimiter of the first frame. 183 | \item The second byte is a COBS overhead byte (one for the entire transfer). 184 | \item The following block of 24 bytes is the COBS-encoded header. 185 | \item The third-to-last block is the COBS-encoded transfer payload, 186 | containing the two bytes of the array length prefix followed by the string data. 187 | \item The second-to-last block of four bytes is the COBS-encoded transfer-CRC. 188 | \item The last byte is the ending frame delimiter. 189 | \end{itemize} 190 | 191 | \begin{verbatim} 192 | 00 193 | 09 194 | 01 04 d2 04 ff ff d2 04 01 01 01 01 01 01 01 01 01 01 02 80 01 04 08 12 195 | 09 0e 30 31 32 33 34 35 36 37 38 196 | 84 a2 2d e2 197 | 00 198 | \end{verbatim} 199 | \end{remark} 200 | 201 | \begin{remark} 202 | The snippet given below contains the hexadecimal dump of the following Cyphal/serial transfer: 203 | 204 | \begin{description} 205 | \item[Priority] nominal 206 | \item[Transfer-ID] 0 207 | \item[Transfer kind] message with the subject-ID 1234 208 | \item[Source node-ID] 4321 209 | \item[Destination node-ID] None 210 | \item[Header user data] 0 211 | \item[Transfer payload] \verb|uavcan.primitive.Empty.1| 212 | \end{description} 213 | 214 | The payload is shown in segments for clarity: 215 | 216 | \begin{itemize} 217 | \item The first byte is the starting delimiter of the first frame. 218 | \item The second byte is a COBS overhead byte (one for the entire transfer). 219 | \item The following block of 24 bytes is the COBS-encoded header. 220 | \item The second-to-last block of four bytes is the COBS-encoded transfer-CRC, 221 | which is zero as the payload is empty. 222 | \item The last byte is the ending frame delimiter. 223 | \end{itemize} 224 | 225 | \begin{verbatim} 226 | 00 227 | 09 228 | 01 04 e1 10 ff ff d2 04 01 01 01 01 01 01 01 01 01 01 02 80 01 03 93 70 229 | 01 01 01 01 230 | 00 231 | \end{verbatim} 232 | \end{remark} 233 | -------------------------------------------------------------------------------- /specification/transport/transport.tex: -------------------------------------------------------------------------------- 1 | \chapter{Transport layer}\label{sec:transport} 2 | 3 | This chapter defines the transport layer of Cyphal. 4 | First, the core abstract concepts are introduced. 5 | Afterwards, they are concretized for each supported underlying transport protocol (e.g., CAN bus); 6 | such concretizations are referred to as \emph{concrete transports}. 7 | 8 | When referring to a concrete transport, the notation ``Cyphal/X'' is used, 9 | where \emph{X} is the name of the underlying transport protocol. 10 | For example, ``Cyphal/CAN'' refers to CAN bus. 11 | 12 | As the specification is extended to add support for new concrete transports, 13 | some of the generic aspects may be pushed to the concrete sections 14 | if they are found to map poorly onto the newly supported protocols. 15 | Such changes are guaranteed to preserve full backward compatibility of the existing concrete transports. 16 | 17 | This chapter defines first-class transports only. 18 | For matters related to tunneling transport frames over other transports, 19 | refer to section~\ref{sec:application_functions_metatransport}. 20 | 21 | % Please keep \clearpage in front of every section to enforce clear separation! 22 | \clearpage\input{transport/abstract.tex} 23 | \clearpage\input{transport/can/can.tex} 24 | \clearpage\input{transport/udp/udp.tex} 25 | \clearpage\input{transport/serial/serial.tex} 26 | --------------------------------------------------------------------------------