diff --git a/docs/manual/_static/python_images/cyclonedds-help.svg b/docs/manual/_static/python_images/cyclonedds-help.svg new file mode 100644 index 0000000000..ea0cb530c9 --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-help.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ cyclonedds --help + +Usage: cyclonedds [OPTIONSCOMMAND [ARGS]... + +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +--help-h    Show this message and exit.                                                                             +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭─ DDS entities ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ +ls      Scan and display DDS entities in your network                                                                +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭─ DDS applications ───────────────────────────────────────────────────────────────────────────────────────────────────╮ +ps     Scan and display DDS applications in your network                                                             +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭─ Data ───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +subscribe                   Subscribe to an arbitrary topic                                                          +publish                     Publish to an arbitrary topic                                                            +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭─ Utilities ──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +typeof              Fetch and display reconstructed IDL of a type over XTypes                                        +performance         Run CycloneDDS performance tests on your system.                                                 +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-ls-demo.svg b/docs/manual/_static/python_images/cyclonedds-ls-demo.svg new file mode 100644 index 0000000000..af9cc5f2f3 --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-ls-demo.svg @@ -0,0 +1,470 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cyclonedds ls --suppress-progress-bar --force-color-mode + + + + + + + + + + +╭─────────────── Participant Srumailikos (01101efb-392e-c1ec-a7fc-a44d000001c1) ───────────────╮ +│                                                                                              │ +│ ╭──────────────────────────────────────────  QoS ──────────────────────────────────────────╮ │ +│ Liveliness.Automatic(lease_duration='10 seconds') │ +│ Property(key='__Hostname'value='bitcrusher') │ +│ Property(key='__NetworkAddresses'value='udp/239.255.0.1:7400@3udp/172.17.0.1:52992@3') │ +│ Property(key='__Pid'value='16435') │ +│ Property(key='__ProcessName'value='python3') │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ │ +│                                                                                              │ +│ ╭─────────────────────────────────────── Vehicle ────────────────────────────────────────╮   │ +│ │ ╭──────────────────────────────────── Common QoS ────────────────────────────────────╮ │   │ +│ │ DataRepresentation(use_cdrv0_representation=Trueuse_xcdrv2_representation=False) │   │ +│ │ Deadline(deadline='10 microseconds') │   │ +│ │ DestinationOrder.ByReceptionTimestamp │   │ +│ │ Durability.Transient │   │ +│ │ DurabilityService( │   │ +│ │ cleanup_delay=0,                                                                │   │ +│ │ history=History.KeepLast(depth=1),                                              │   │ +│ │ max_samples=-1,                                                                 │   │ +│ │ max_instances=-1,                                                               │   │ +│ │ max_samples_per_instance=-1 │   │ +│ │ ) │   │ +│ │ History.KeepLast(depth=10) │   │ +│ │ IgnoreLocal.Nothing │   │ +│ │ LatencyBudget(budget='zero') │   │ +│ │ Lifespan(lifespan='infinity') │   │ +│ │ Liveliness.Automatic(lease_duration='infinity') │   │ +│ │ Ownership.Shared │   │ +│ │ OwnershipStrength(strength=0) │   │ +│ │ PresentationAccessScope.Instance(coherent_access=Falseordered_access=False) │   │ +│ │ Reliability.BestEffort │   │ +│ │ ResourceLimits(max_samples=-1max_instances=-1max_samples_per_instance=-1) │   │ +│ │ TransportPriority(priority=0) │   │ +│ │ WriterDataLifecycle(autodispose=True) │   │ +│ │ ╰────────────────────────────────────────────────────────────────────────────────────╯ │   │ +│ │ ┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓                             │   │ +│ │ ┃ Typename       ┃                     vehicles::Vehicle ┃                             │   │ +│ │ │ XTypes Type ID │ COMPLETE 571647DF3994A28B63465C537B3E │                             │   │ +│ │ └────────────────┴───────────────────────────────────────┘                             │   │ +│ │                      Publications                                                      │   │ +│ │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓                                │   │ +│ │ ┃GUID                                               ┃                                │   │ +│ │ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩                                │   │ +│ │ │ Sruzoigaufab (01101efb-392e-c1ec-a7fc-a44d00000203) │                                │   │ +│ │ └─────────────────────────────────────────────────────┘                                │   │ +│ ╰────────────────────────────────────────────────────────────────────────────────────────╯   │ +╰──────────────────────────────────────────────────────────────────────────────────────────────╯ + +╭─────────────── Participant Knonefecac (0110c056-c5fc-ad05-bd6c-fd26000001c1) ────────────────╮ +│                                                                                              │ +│ ╭──────────────────────────────────────────  QoS ──────────────────────────────────────────╮ │ +│ Liveliness.Automatic(lease_duration='10 seconds') │ +│ Property(key='__Hostname'value='bitcrusher') │ +│ Property(key='__NetworkAddresses'value='udp/239.255.0.1:7400@3udp/172.17.0.1:49665@3') │ +│ Property(key='__Pid'value='16455') │ +│ Property(key='__ProcessName'value='python3') │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ │ +│                                                                                              │ +│ ╭─────────────────────────────────────── Vehicle ────────────────────────────────────────╮   │ +│ │ ╭──────────────────────────────────── Common QoS ────────────────────────────────────╮ │   │ +│ │ DataRepresentation(use_cdrv0_representation=Trueuse_xcdrv2_representation=False) │   │ +│ │ Deadline(deadline='10 microseconds') │   │ +│ │ DestinationOrder.ByReceptionTimestamp │   │ +│ │ Durability.Transient │   │ +│ │ History.KeepLast(depth=10) │   │ +│ │ IgnoreLocal.Nothing │   │ +│ │ LatencyBudget(budget='zero') │   │ +│ │ Liveliness.Automatic(lease_duration='infinity') │   │ +│ │ Ownership.Shared │   │ +│ │ PresentationAccessScope.Instance(coherent_access=Falseordered_access=False) │   │ +│ │ ReaderDataLifecycle( │   │ +│ │ autopurge_nowriter_samples_delay='infinity',                                    │   │ +│ │ autopurge_disposed_samples_delay='infinity' │   │ +│ │ ) │   │ +│ │ Reliability.BestEffort │   │ +│ │ ResourceLimits(max_samples=-1max_instances=-1max_samples_per_instance=-1) │   │ +│ │ TimeBasedFilter(filter_time='zero') │   │ +│ │ TransportPriority(priority=0) │   │ +│ │ TypeConsistency.AllowTypeCoercion( │   │ +│ │ ignore_sequence_bounds=True,                                                    │   │ +│ │ ignore_string_bounds=True,                                                      │   │ +│ │ ignore_member_names=False,                                                      │   │ +│ │ prevent_type_widening=False,                                                    │   │ +│ │ force_type_validation=False │   │ +│ │ ) │   │ +│ │ ╰────────────────────────────────────────────────────────────────────────────────────╯ │   │ +│ │ ┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓                             │   │ +│ │ ┃ Typename       ┃                     vehicles::Vehicle ┃                             │   │ +│ │ │ XTypes Type ID │ COMPLETE 571647DF3994A28B63465C537B3E │                             │   │ +│ │ └────────────────┴───────────────────────────────────────┘                             │   │ +│ │                      Subscriptions                                                     │   │ +│ │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓                                │   │ +│ │ ┃GUID                                               ┃                                │   │ +│ │ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩                                │   │ +│ │ │ Knoboesoelim (0110c056-c5fc-ad05-bd6c-fd2600000204) │                                │   │ +│ │ └─────────────────────────────────────────────────────┘                                │   │ +│ ╰────────────────────────────────────────────────────────────────────────────────────────╯   │ +╰──────────────────────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-ls-help.svg b/docs/manual/_static/python_images/cyclonedds-ls-help.svg new file mode 100644 index 0000000000..6c67e06556 --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-ls-help.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ cyclonedds ls --help + +Usage: cyclonedds ls [OPTIONS] + + Scan and display DDS entities in your network.                                                                          + +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +--id,--domain-id-iINTEGER                                   DDS Domain to inspect.                       +--runtime-rTIMEDELTA                                   Duration of discovery scan.                  +--topic-tTEXT                                        Filter which entity types to display by      +                                                                          topic name (supports regex)                  +--show-self  Show the tools own participant and           +                                                                          subscriptions.                               +--suppress-progress-bar  Suppress the output of the progress bar      +--color[auto|standard|256|truecolor|windows|none]  Force the command to output with/without     +                                                                          terminal colors. By default output colours   +                                                                          if the terminal supports it." See the Rich  +documentation for more info on what the      +                                                                          options mean.                                +--qos-q  Show the QoS settings of all entities.       +--help-h  Show this message and exit.                  +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-performance-help.svg b/docs/manual/_static/python_images/cyclonedds-performance-help.svg new file mode 100644 index 0000000000..bb807fa2a2 --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-performance-help.svg @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ cyclonedds performance --help + +Usage: cyclonedds performance [OPTIONSCOMMAND [ARGS]... + + Run CycloneDDS performance tests on your system.                                                                        +Examples +cyclonedds performance publish--size1000cyclonedds performance subscribe +-   basic throughput test with 1024-byte samples +cyclonedds performance ping cyclonedds performance pong +-   basic latency test + +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +--topic-T[KS|K32|K256|OU|UK16|UK1024|S16|S256|S4k|S32  Topic (KS is default). Print topic             +k]  information with cyclonedds performance  +topics +--num-keys-nINTEGER                                       Number of key values to use for data (only     +                                                                        for topics with a key value)                   +--unreliable-u  Use best-effort instead of reliable            +--keep-k<all,n>  Keep-all or keep-last-N for data (ping/pong    +                                                                        is always keep-last-1)                         +--cpu-c  Subscribe to CPU stats from peers and show     +                                                                        them                                           +--device-load-d<device:bandwidth>  Report network load for device DEV with        +                                                                        nominal bandwidth BW in bits/s (e.g.,          +                                                                        eth0:1e9)                                      +--duration-DTIMEDELTA                                     Set max duration, integer number of seconds    +                                                                        or timestring like '1h23m11s'                  +--local-matching-L  Allow matching with endpoints in the same      +                                                                        process to get throughput/latency in the same  +                                                                        ddsperf process                                +--success-criterion-QTEXT                                          Set success criteria rss:X% max allowed        +                                                                        increase in RSS, in %, rss:X max allowed       +                                                                        increase in RSS, in MBsamples:N min          +                                                                        received messages by "sub", roundtrips:N min   +                                                                        roundtrips for "pong", minmatch:N require >=   +N matching participants, initwait:DUR wait     +                                                                        for those participants before starting, abort  +                                                                        if not within DUR seconds, maxwait:DUR +                                                                        require those participants to match within     +DUR seconds,                                   +--reference-time-R<TREF>  Show timestamps in the output relative to      +TREF instead of process start                  +--wait-match-max-WTIMEDELTA                                     Maximum waittime for the minimum required      +                                                                        number of matching participants (set by        +-Qminmatch:N) to show up before starting       +                                                                        reading/writing data, terminate with an error  +                                                                        otherwise. This differs from -Qmaxwait:DUR +                                                                        because that doesn't delay starting and        +                                                                        doesn't terminate the process before doing     +                                                                        anything                                       +--domain-id-i<ID>  Use domain ID instead of the default domain    +--color[auto|standard|256|truecolor|windows|none]  Force the command to output with/without       +                                                                        terminal colors. By default output colours if  +                                                                        the terminal supports it." See the Rich  +documentation for more info on what the        +                                                                        options mean.                                  +--help-h  Show this message and exit.                    +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭─ Commands ───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +ping               Send pings                                                                                        +pong               Send pongs                                                                                        +publish            Publish data                                                                                      +subscribe          Subscribe to data                                                                                 +topics             Show information about the performance topic types.                                               +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-performance-subscribe-demo.svg b/docs/manual/_static/python_images/cyclonedds-performance-subscribe-demo.svg new file mode 100644 index 0000000000..92d5d5182d --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-performance-subscribe-demo.svg @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cyclonedds performance --duration 21s --render-output-once-on-exit --force-color-mode subscribe --triggering-mode waitset + + + + + + + + + + ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +ddsperf -1 -X -T KS -D 21.0 sub waitset +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +     ⏨⁵╭────────────────────────────────────╴Samplerate(S/s)╶────────────────────────────────────╮         ╭────────────────╴Samplerate histogram╶─────────────────╮  ╭──────────── Peers ─────────────╮ +    2.7┤                                                                                    │     1.00┤                                 │  │ ╶── Self ──╴                   │ +       │                                                                                    │         │                                 │  │ bitcrusher:28766               │ +    2.7┤                                                                                   │     0.91┤                                 │  │                                │ +       │                                                                                   │         │                                 │  │ ╶── Others ──╴                 │ +    2.6┤                                     │     0.82┤                                 │  │ bitcrusher:28243               │ +       │         │         │                                 │  │                                │ +    2.6┤ │     0.73┤                                 │  │                                │ +       │   │         │                                 │  │                                │ +    2.5┤  │     0.64┤                                 │  │                                │ +       │  │         │                                 │  │                                │ +    2.5┤   │     0.55┤                                 │  │                                │ +       │   │         ││  │                                │ +    2.4┤             │     0.45┤│  │                                │ +       │                                │         ││  │                                │ +    2.4┤                                                        │     0.36┤│  │                                │ +       │                                                            │         ││  │                                │ +    2.4┤                                                                                  │     0.27┤│  │                                │ +       │                                                                                   │         ││  │                                │ +    2.3┤                                                                                   │     0.18┤│  │                                │ +       │                                                                                    │         ││  │                                │ +    2.3┤                                                                                    │     0.09┤│  │                                │ +       │                                                                                    │         ││  │                                │ +    2.2┤                                                                                    │     0.00┤│  │                                │ +       ╰┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬╯         ╰┬──────┬─────┬──────┬──────┬──────┬──────┬─────┬──────┬╯  │                                │ +      0.0        2.4        4.8        7.1        9.5        11.9       14.2       16.6       19.0      ⏨⁵ 2.2    2.3   2.3    2.4    2.5    2.5    2.6   2.6    2.7  ╰────────────────────────────────╯ +       ╭────────────────────╴CPU(%thread)╶─────────────────────╮                                         ⏨⁵╭───────╴MaxRSS╶───────╮         ╭───────╴Rexmit╶───────╮         ╭──────╴Tthrottle╶──────╮   +    100┤                                                       │  tev user/tev system                  72.0┤│     1.00┤                      │     1.00┤                       │   +       │                                                       │  recvUC user/recvUC system                │                      │         │                      │         │                       │   +     91┤                                                       │  sub user/sub system                  71.2┤                      │     0.75┤                      │     0.75┤                       │   +       │                                                       │  ddsperf user/ddsperf system              │                      │         │                      │         │                       │   +     82┤                                                       │                                       70.5┤                      │     0.50┤                      │     0.50┤                       │   +       │                                                       │  Context switches                         │                      │         │                      │         │                       │   +     73┤                                                       │  Voluntary: 362084                    69.8┤                      │     0.25┤                      │     0.25┤                       │   +       │            │  Involuntary: 6                           │                      │         │                      │         │                       │   +     64┤       │                                       69.0┤                      │     0.00┤│     0.00┤│   +       │             │                                           ╰┬─────────┬──────────┬╯         ╰┬─────────┬──────────┬╯         ╰┬──────────┬──────────┬╯   +     55┤                 │                                           0.0       4.5        9.0         0.0       4.5        9.0         0.0        4.5        9.0   +       │                                           │                                                                                                                                         +     45┤                                                 │                                           ╭───╴Discarded msg╶────╮         ╭──────╴TRexmit╶───────╮         ╭──────╴Nthrottle╶──────╮   +       │            │                                       16.0┤ │     1.00┤                      │     1.00┤                       │   +     36┤│                                           │ │         │                      │         │                       │   +       ││                                       12.8┤ │     0.80┤                      │     0.80┤                       │   +     27┤ │                                           │ │         │                      │         │                       │   +       │           │                                        9.6┤ │     0.60┤                      │     0.60┤                       │   +     18┤             │                                           ││         │                      │         │                       │   +       │                                                       │                                        6.4┤ │     0.40┤                      │     0.40┤                       │   +      9┤                                                       │                                           │ │         │                      │         │                       │   +       │                                                       │                                        3.2┤ │     0.20┤                      │     0.20┤                       │   +      0┤│                                           │ │         │                      │         │                       │   +       ╰┬──────┬──────┬─────┬──────┬──────┬─────┬──────┬──────┬╯                                        0.0┤ │     0.00┤│     0.00┤│   +       0.0    1.2    2.3   3.5    4.7    5.9   7.0    8.2    9.4                                           ╰┬─────────┬──────────┬╯         ╰┬─────────┬──────────┬╯         ╰┬──────────┬──────────┬╯   +                                                                                                           0.0       4.5        9.0         0.0       4.5        9.0         0.0        4.5        9.0   + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-ps-demo.svg b/docs/manual/_static/python_images/cyclonedds-ps-demo.svg new file mode 100644 index 0000000000..94188b57b9 --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-ps-demo.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cyclonedds ps --suppress-progress-bar --force-color-mode + + + + + + + + + + +┏━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓ +Host      ApplicationPid  Participants                                      Topics  +┡━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩ +│ bitcrusher │ python3     │ 16435 │ Srumailikos (01101efb-392e-c1ec-a7fc-a44d000001c1) │ Vehicle │ +│ bitcrusher │ python3     │ 16455 │ Knonefecac (0110c056-c5fc-ad05-bd6c-fd26000001c1)  │ Vehicle │ +└────────────┴─────────────┴───────┴────────────────────────────────────────────────────┴─────────┘ + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-ps-help.svg b/docs/manual/_static/python_images/cyclonedds-ps-help.svg new file mode 100644 index 0000000000..13e1d167bb --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-ps-help.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ cyclonedds ps --help + +Usage: cyclonedds ps [OPTIONS] + + Scan and display DDS applications in your network                                                                       + +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +--id,--domain-id-iINTEGER                                   DDS Domain to inspect.                       +--runtime-rTIMEDELTA                                   Duration of discovery scan.                  +--topic-tTEXT                                        Filter which entity types to display by      +                                                                          topic name (supports regex)                  +--show-self  Show the tools own application.              +--suppress-progress-bar  Suppress the output of the progress bar      +--color[auto|standard|256|truecolor|windows|none]  Force the command to output with/without     +                                                                          terminal colors. By default output colours   +                                                                          if the terminal supports it." See the Rich  +documentation for more info on what the      +                                                                          options mean.                                +--help-h  Show this message and exit.                  +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-publish-help.svg b/docs/manual/_static/python_images/cyclonedds-publish-help.svg new file mode 100644 index 0000000000..927352679d --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-publish-help.svg @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ cyclonedds publish --help + +Usage: cyclonedds publish [OPTIONSTOPIC + + Publish to an arbitrary topic                                                                                           + +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +*TOPICTEXT                                    [required] +--id,--domain-id-iINTEGER                                 DDS Domain to inspect.                      +--runtime-rTIMEDELTA                                 Duration of discovery scan.                 +--suppress-progress-bar  Suppress the output of the progress bar     +--color[auto|standard|256|truecolor|windows|non  Force the command to output with/without    +e]  terminal colors. By default output colours  +                                                                           if the terminal supports it." See the Rich +documentation for more info on what the     +                                                                           options mean.                               +--qos[scan|scan-random|dds-default|json]  Method to determine the QoS settings of     +                                                                           the writer. With "scan" the network is      +                                                                           scanned for existing QoS used.              +                                                                           "scan-random" functions the same way but    +                                                                           does not prompt for input, but simply       +                                                                           picks a random QoS in case of conflicts.    +                                                                           With "dds-default" the default QoS from     +                                                                           the DDS specification is used and with      +                                                                           "json" your first line of input should be   +                                                                           a json string with the QoS settings,        +                                                                           defined by the output of                    +                                                                           `cyclonedds.qos.Qos.asdict()`.              +--type[scan|scan-random]  Method to determine the datatype of the     +                                                                           writer. With "scan" the network is scanned  +                                                                           for existing types using XTypes.            +                                                                           "scan-random" functions the same way but    +                                                                           does not prompt for input, but simply       +                                                                           picks a random datatype in case of          +                                                                           conflicts.                                  +--help-h  Show this message and exit.                 +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-subscribe-demo.svg b/docs/manual/_static/python_images/cyclonedds-subscribe-demo.svg new file mode 100644 index 0000000000..2d26f21014 --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-subscribe-demo.svg @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + timeout -s INT 10s cyclonedds subscribe Vehicle --suppress-progress-bar --force-color-mode + + + + + + + + + + + Subscribing, CTRL-C to quit + +Vehicle(name='Dallara IL-15'x=208y=230) +Vehicle(name='Dallara IL-15'x=207y=229) +Vehicle(name='Dallara IL-15'x=208y=228) +Vehicle(name='Dallara IL-15'x=209y=228) +Vehicle(name='Dallara IL-15'x=209y=227) +Vehicle(name='Dallara IL-15'x=209y=226) +Vehicle(name='Dallara IL-15'x=208y=225) +Vehicle(name='Dallara IL-15'x=207y=224) +Vehicle(name='Dallara IL-15'x=208y=224) +Vehicle(name='Dallara IL-15'x=209y=224) +Vehicle(name='Dallara IL-15'x=208y=223) +Vehicle(name='Dallara IL-15'x=207y=222) +Vehicle(name='Dallara IL-15'x=208y=222) +Vehicle(name='Dallara IL-15'x=207y=223) +Vehicle(name='Dallara IL-15'x=208y=222) +Vehicle(name='Dallara IL-15'x=209y=223) +Vehicle(name='Dallara IL-15'x=209y=222) +Vehicle(name='Dallara IL-15'x=210y=221) +Vehicle(name='Dallara IL-15'x=211y=220) + + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-subscribe-help.svg b/docs/manual/_static/python_images/cyclonedds-subscribe-help.svg new file mode 100644 index 0000000000..42ce9cd543 --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-subscribe-help.svg @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ cyclonedds subscribe --help + +Usage: cyclonedds subscribe [OPTIONSTOPIC + + Subscribe to an arbitrary topic                                                                                         + +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +*TOPICTEXT                                    [required] +--id,--domain-id-iINTEGER                                 DDS Domain to inspect.                      +--runtime-rTIMEDELTA                                 Duration of discovery scan.                 +--suppress-progress-bar  Suppress the output of the progress bar     +--color[auto|standard|256|truecolor|windows|non  Force the command to output with/without    +e]  terminal colors. By default output colours  +                                                                           if the terminal supports it." See the Rich +documentation for more info on what the     +                                                                           options mean.                               +--qos[scan|scan-random|dds-default|json]  Method to determine the QoS settings of     +                                                                           the reader. With "scan" the network is      +                                                                           scanned for existing QoS used.              +                                                                           "scan-random" functions the same way but    +                                                                           does not prompt for input, but simply       +                                                                           picks a random QoS in case of conflicts.    +                                                                           With "dds-default" the default QoS from     +                                                                           the DDS specification is used and with      +                                                                           "json" your first line of input should be   +                                                                           a json string with the QoS settings,        +                                                                           defined by the output of                    +                                                                           `cyclonedds.qos.Qos.asdict()`.              +--type[scan|scan-random]  Method to determine the datatype of the     +                                                                           reader. With "scan" the network is scanned  +                                                                           for existing types using XTypes.            +                                                                           "scan-random" functions the same way but    +                                                                           does not prompt for input, but simply       +                                                                           picks a random datatype in case of          +                                                                           conflicts.                                  +--help-h  Show this message and exit.                 +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-typeof-demo.svg b/docs/manual/_static/python_images/cyclonedds-typeof-demo.svg new file mode 100644 index 0000000000..ff5ccaca42 --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-typeof-demo.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cyclonedds typeof Vehicle --suppress-progress-bar --force-color-mode + + + + + + + + + + +As defined in participant(s)01101efb-392e-c1ec-a7fc-a44d000001c1 +0110c056-c5fc-ad05-bd6c-fd26000001c1 +modulevehicles{ +@final +structVehicle{ +stringname; +longlongx; +longlongy; +}; +}; + + + + + diff --git a/docs/manual/_static/python_images/cyclonedds-typeof-help.svg b/docs/manual/_static/python_images/cyclonedds-typeof-help.svg new file mode 100644 index 0000000000..f994605083 --- /dev/null +++ b/docs/manual/_static/python_images/cyclonedds-typeof-help.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ cyclonedds typeof --help + +Usage: cyclonedds typeof [OPTIONSTOPIC + + Fetch and display reconstructed IDL of a type over XTypes                                                               + +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +*TOPICTEXT                                    [required] +--id,--domain-id-iINTEGER                                 DDS Domain to inspect.                      +--runtime-rTIMEDELTA                                 Duration of discovery scan.                 +--suppress-progress-bar  Suppress the output of the progress bar     +--color[auto|standard|256|truecolor|windows|non  Force the command to output with/without    +e]  terminal colors. By default output colours  +                                                                           if the terminal supports it." See the Rich +documentation for more info on what the     +                                                                           options mean.                               +--help-h  Show this message and exit.                 +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/manual/about_dds/contributing.rst b/docs/manual/about_dds/contributing.rst new file mode 100644 index 0000000000..3c2aff8998 --- /dev/null +++ b/docs/manual/about_dds/contributing.rst @@ -0,0 +1,100 @@ +.. include:: ../external-links.part.rst + +.. index:: Contributing + +.. _contributing_to_dds: + +Contributing to |var-project| +============================= + +We welcome all contributions to the project, including questions, +examples, bug fixes, enhancements or improvements to the documentation, +etc. + + +.. tip:: + + Contributing to |var-project| means donating your code to the Eclipse foundation. It requires that you + sign the |url::eclipse_link| using |url::eclipse-form_link|. In summary, this means that your contribution is + yours to give away, and that you allow others to use and distribute it. However, don't take legal advice + from this getting started guide, read the terms linked above. + +To contribute code, it may be helpful to know that build configurations for Azure DevOps Pipelines +are present in the repositories. +There is a test suite using CTest and |url::cunit_link| that can be built locally. + +.. tabs:: + + .. group-tab:: Linux + + Set the CMake variable ``BUILD_TESTING`` to ``ON`` when configuring, e.g.: + + .. code-block:: bash + + cd build + cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON .. + cmake --build . + ctest + + This build requires |url::cunit_link|. You can + install this yourself, or you can choose to instead rely on the + |url::conan_link| packaging system that the CI build + infrastructure also uses. In that case, install Conan in the build + directory before running CMake: + + .. code-block:: bash + + conan install .. --build missing + + .. group-tab:: macOS + + Set the CMake variable ``BUILD_TESTING`` to ``ON`` when configuring, e.g.: + + .. code-block:: bash + + cd build + cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON .. + cmake --build . + ctest + + This build requires |url::cunit_link|. You can + install this yourself, or you can choose to instead rely on the + |url::conan_link| packaging system that the CI build + infrastructure also uses. In that case, install Conan in the build + directory before running CMake: + + .. code-block:: bash + + conan install .. --build missing + + .. group-tab:: Windows + + Set the CMake variable ``BUILD_TESTING`` to ``ON`` when configuring, e.g.: + + .. code-block:: bash + + cd build + cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON .. + cmake --build . + ctest + + This build requires |url::cunit_link|. You can + install this yourself, or you can choose to instead rely on the + |url::conan_link| packaging system that the CI build + infrastructure also uses. In that case, install Conan in the build + directory before running CMake: + + .. code-block:: bash + + conan install .. --build missing + + This automatically downloads and builds CUnit (and currently OpenSSL for transport security). + + .. note:: + + Depending on the generator, you may also need to add switches to select the architecture and build type, e.g.: + + .. code-block:: bash + + conan install -s arch=x86_64 -s build_type=Debug .. + diff --git a/docs/manual/about_dds/data_centric_architecture.rst b/docs/manual/about_dds/data_centric_architecture.rst index 03d3924279..84fa3d80ee 100644 --- a/docs/manual/about_dds/data_centric_architecture.rst +++ b/docs/manual/about_dds/data_centric_architecture.rst @@ -1,5 +1,7 @@ .. index:: Data-centric architecture +.. _data_centric_architecture: + Data-centric architecture ------------------------- @@ -31,7 +33,7 @@ the same data topic. Time-decoupling derives from the fact that, fundamentally, the nature of communication is asynchronous. Data producers and consumers, -known as ``DataWriter``\s and ``DataReader``\s, are not forced to +known as :ref:`datawriters_bm` and :ref:`datareaders_bm`, are not forced to be active and connected simultaneously to share data. In this scenario, the |var-project-short| middleware can handle and manage data on behalf of late joining ``DataReader`` applications and deliver it to them when they @@ -40,5 +42,5 @@ join the system. Time and space decoupling gives applications the freedom to be plugged or unplugged from the system at any time, from anywhere, in any order. This keeps the complexity and administration of a data-centric -architecture relatively low when adding more and more ``DataReader`` and -``DataWriter`` applications. \ No newline at end of file +architecture relatively low when adding more and more DataReader and +DataWriter applications. \ No newline at end of file diff --git a/docs/manual/about_dds/datareaders.rst b/docs/manual/about_dds/datareaders.rst new file mode 100644 index 0000000000..b0d4afcc55 --- /dev/null +++ b/docs/manual/about_dds/datareaders.rst @@ -0,0 +1,134 @@ +.. index:: DataReaders + +.. _datareaders_bm: + +=========== +DataReaders +=========== + +DataReaders enable the user access to the data received by a :ref:`subscriber ` +on a :ref:`topic `, and takes as a template parameter the data type being +exchanged. The settings for the reader are either inherited from the subscriber, or +explicitly set in its own QoS policies and listener: + +Inherited from the subscriber: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::sub::DataReader reader(sub, topic); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +Explicitly set in its own QoS policies and listener: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::sub::NoOpAnyDataReaderListener listener; /*you need to create your own class that derives from this listener, and implement your own callback functions*/ + /*the listener implementation should implement the on_data_available virtual function as we will rely on it later*/ + dds::sub::qos::DataReaderQos rqos; + dds::sub::DataReader reader(sub, topic, rqos, &listener, dds::core::status::StatusMask::data_available()); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +The data is accessed by either `reading` or `taking` the samples from the reader. +Both return a container of ``dds::sub::Sample``s, which have: + +- The received sample of the exchanged datatype accessed through `data()`. +- The metadata for the received sample accessed through `info()`. + +The metadata contains such information as: + +- Sample timestamp (time of writing). +- Data validity (whether the call to `data()` will return anything that should be processed). +- Sample state (READ/NOT_READ/...). + +The difference between these two different access methods is the state of the reader +after the access is finished. + +The `take` operation only returns samples that have not yet been returned in a `take` operation, + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + :emphasize-lines: 1 + + auto samples = reader.take(); + for (const auto & sample:samples) { + if (!sample.valid()) + continue; + const auto &data = sample.data(); + /*print the data?*/ + } + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +The `read` operation returns all samples currently stored by the reader. + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + :emphasize-lines: 1 + + auto samples = reader.read(); + for (const auto & sample:samples) { + if (!sample.valid() || + sample.state() != dds::sub::status::SampleState::not_read()) + continue; + const auto &data = sample.data(); + /*print the data?*/ + } + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + diff --git a/docs/manual/about_dds/datawriters.rst b/docs/manual/about_dds/datawriters.rst new file mode 100644 index 0000000000..aec430b865 --- /dev/null +++ b/docs/manual/about_dds/datawriters.rst @@ -0,0 +1,132 @@ +.. index:: DataWriters + +.. _datawriters_bm: + +=========== +DataWriters +=========== + +DataWriters write data to a :ref:`topic ` using a +:ref:`publisher `, and take as a template parameter the data type being +exchanged. The settings for the writer are either inherited from the publisher, or +explicitly set in its own :ref:`Qos ` policies and listener. + +Inherited from the publisher: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::pub::DataWriter writer(pub, topic); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +Explicitly set in its own QoS policies and listener: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::pub::NoOpAnyDataWriterListener listener; /*you need to create your own class that derives from this listener, and implement your own callback functions*/ + /*the listener implementation should implement the on_publication_matched virtual function as we will rely on it later*/ + dds::pub::qos::DataWriterQos wqos; + dds::pub::DataWriter writer(pub, topic, wqos, &listener, dds::core::status::StatusMask::publication_matched()); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +A writer can write a sample: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + DataType sample; + writer.write(sample); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +A sample with a specific timestamp: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + DataType sample; + dds::core::Time timestamp(123 /*seconds*/, 456 /*nanoseconds*/); + writer.write(sample, timestamp); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +A range of samples: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + std::vector samples; + writer.write(samples.begin(), samples.end()); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +.. tbd:: + Or update existing instances through handles, which we will not go into here. \ No newline at end of file diff --git a/docs/manual/config/ddsi-transient_behavoir.rst b/docs/manual/about_dds/ddsi-transient_behavior.rst similarity index 100% rename from docs/manual/config/ddsi-transient_behavoir.rst rename to docs/manual/about_dds/ddsi-transient_behavior.rst diff --git a/docs/manual/config/ddsi_concepts.rst b/docs/manual/about_dds/ddsi_concepts.rst similarity index 96% rename from docs/manual/config/ddsi_concepts.rst rename to docs/manual/about_dds/ddsi_concepts.rst index b67a7b30d7..0b3fef941b 100644 --- a/docs/manual/config/ddsi_concepts.rst +++ b/docs/manual/about_dds/ddsi_concepts.rst @@ -22,5 +22,5 @@ implementation. mapping_domains mapping_entities reliable_communication - ddsi-transient_behavoir + ddsi-transient_behavior discovery_participants \ No newline at end of file diff --git a/docs/manual/getting_started/disclaimer.part.rst b/docs/manual/about_dds/disclaimer.part.rst similarity index 96% rename from docs/manual/getting_started/disclaimer.part.rst rename to docs/manual/about_dds/disclaimer.part.rst index 15eaef4999..c7a06212da 100644 --- a/docs/manual/getting_started/disclaimer.part.rst +++ b/docs/manual/about_dds/disclaimer.part.rst @@ -1,4 +1,4 @@ -Disclaimer -========== - -"Eclipse Cyclone DDS" and "Cyclone DDS" are trademarks of the Eclipse Foundation. +Disclaimer +========== + +"Eclipse Cyclone DDS" and "Cyclone DDS" are trademarks of the Eclipse Foundation. diff --git a/docs/manual/config/discovery_participants.rst b/docs/manual/about_dds/discovery_participants.rst similarity index 86% rename from docs/manual/config/discovery_participants.rst rename to docs/manual/about_dds/discovery_participants.rst index 03176ac9cf..dace8c46f5 100644 --- a/docs/manual/config/discovery_participants.rst +++ b/docs/manual/about_dds/discovery_participants.rst @@ -1,9 +1,14 @@ +.. index:: + single: Discovery; DDSI Participants and endpoints + single: Endpoints; DDSI discovery + single: Participants; DDSI discovery + single: DDSI; Discovery of participants and endpoints -.. _`Discovery of participants and endpoints`: +.. _discovery_participants_endpoints: -*************************************** -Discovery of participants and andpoints -*************************************** +******************************************** +Discovery of DDSI participants and endpoints +******************************************** DDSI participants discover each other using the *Simple Participant Discovery Protocol* (SPDP). This protocol periodically sends a message containing the specifics diff --git a/docs/manual/about_dds/domainparticipants.rst b/docs/manual/about_dds/domainparticipants.rst new file mode 100644 index 0000000000..bed30da66e --- /dev/null +++ b/docs/manual/about_dds/domainparticipants.rst @@ -0,0 +1,68 @@ +.. index:: DomainParticipants + +.. _domainparticipants_bm: + +================== +DomainParticipants +================== + +A Domain is a specific subsection of the DDS shared-dataspace and identified by its +domain ID, which is a 32-bit unsigned integer. + +Data exchanges are limited to the domain they are made on. For example, data exchanged +on domain 456 is not visible on domain 789. + +To exchange data you must create a DomainParticipant, which is an entrypoint for the +program on the shared dataspace's domain. + +To specify the default domain ID: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::domain::DomainParticipant participant(domain::default_id()); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +To specify your own ID: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::domain::DomainParticipant participant(123456); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +.. important:: + You must have the same ID on both the reading side and the writing side, otherwise, + they can not see each other. + +.. tbd:: + ???Explain more about setting QoSes??? + diff --git a/docs/manual/about_dds/eclipse_cyclone_dds.rst b/docs/manual/about_dds/eclipse_cyclone_dds.rst index b9adcdf43a..d1003b9825 100644 --- a/docs/manual/about_dds/eclipse_cyclone_dds.rst +++ b/docs/manual/about_dds/eclipse_cyclone_dds.rst @@ -14,14 +14,27 @@ :maxdepth: 1 :hidden: - performance data_centric_architecture + domainparticipants + topics + publishers + subscribers + datareaders + datawriters + qos + listener + waitset + status + performance + idl + ddsi_concepts + contributing |var-project| is a performant and robust OMG-compliant **Data Distribution Service** (DDS) implementation (see |url::dds_spec|). |var-project-short| is developed completely in the open as an Eclipse IoT project (see |url::cyclone_dds-link|) with a -growing list of |url::cyclone_adopters| (if you're one of them, please add your -|url::cyclone_git_logo|. It is a tier-1 middleware for the Robot Operating System |url::ros2|. +growing list of |url::cyclone_adopters|. It is a tier-1 middleware for the Robot +Operating System |url::ros2|. The core of |var-project-short| is implemented in C and provides C-APIs to applications. Through its C++ package, the |url::omg.org| 2003 language binding is also supported. @@ -84,7 +97,7 @@ but our |url::python-link2| allows you to define data types on the fly: sleep(rng.exponential()) Today DDS is also popular in robotics and autonomous vehicles because those really -depend on high-throuhgput, low-latency control systems without introducing a single +depend on high-throughput, low-latency control systems without introducing a single point of failure by having a message broker in the middle. Indeed, it is by far the most used and the default middleware choice in ROS 2. It is used to transfer commands, sensor data and even video and point clouds between components. @@ -125,4 +138,6 @@ With references to the individual OMG specifications, the following is available The network stack in Cyclone DDS has been around for over a decade in one form or another and has proven itself in many systems, including large, high-availability -ones and systems where interoperation with other implementations was needed. \ No newline at end of file +ones and systems where inter-operation with other implementations was needed. + +.. include:: disclaimer.part.rst \ No newline at end of file diff --git a/docs/manual/about_dds/idl.rst b/docs/manual/about_dds/idl.rst new file mode 100644 index 0000000000..6d12a3d87b --- /dev/null +++ b/docs/manual/about_dds/idl.rst @@ -0,0 +1,77 @@ +.. index:: IDL + +.. _idl_bm: + +=== +IDL +=== + +.. toctree:: + :maxdepth: 1 + :hidden: + + idl_compilers + +IDL is a language to defined data types and interfaces that are platform and language +agnostic. There are tools that have been developed to then consume that IDL and emit +code and infrastructure that allows you target a specific platform or language. + +All IDL type support is contained within the subpackage `cyclonedds.idl`, which +enables you to use it even in contexts where you do not need the full +|var-project| ecosystem. + +For example, the following IDL code: + +.. code-block:: shell + + module HelloWorldData + { + struct Msg + { + @key + long userID; + string message; + }; + }; + +``idlc`` (the :ref:`idl_compiler`) converts this to: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code-block:: C + + typedef struct HelloWorldData_Msg + { + int32_t userID; + char * message; + } HelloWorldData_Msg; + + .. group-tab:: C++ + + .. code-block:: C++ + + namespace HelloWorldData + { + class Msg OSPL_DDS_FINAL + { + public: + int32_t userID_; + std::string message_; + /** SNIP THE REST OF THE METHODS **/ + } + } + + .. group-tab:: Python + + .. code-block:: python + + @dataclass + class HelloWorld(IdlStruct, typename="HelloWorld.Msg"): + usedID: int32 + message: str + + For further information, refer to :ref:`py_idl`. + +See also: :ref:`helloworld_idl`. \ No newline at end of file diff --git a/docs/manual/about_dds/idl_compilers.rst b/docs/manual/about_dds/idl_compilers.rst new file mode 100644 index 0000000000..6871b78267 --- /dev/null +++ b/docs/manual/about_dds/idl_compilers.rst @@ -0,0 +1,32 @@ +.. index:: + single: IDL; Compilers + single: Compilers; IDL + +.. _idl_compiler: + +IDL compiler +============ + +The |var-project-short| IDL compiler translates module names into namespaces +and structure names into classes. + +It also generates code for public accessor functions for all fields mentioned in +the IDL struct, separate public constructors, and a destructor: + +- A default (empty) constructor that recursively invokes the constructors of + all fields. +- A copy-constructor that performs a deep copy from the existing class. +- A move-constructor that moves all arguments to its members. + +The destructor recursively releases all fields. It also generates code for +assignment operators that recursively construct all fields based on the +parameter class (copy and move versions). + +.. note:: + + When translated into a different programming language, the data has another + representation specific to the target language. This highlights the advantage + of using a neutral language such as IDL to describe the data model. It can be + translated into different languages that can be shared between different + applications written in other programming languages. + diff --git a/docs/manual/about_dds/listener.rst b/docs/manual/about_dds/listener.rst new file mode 100644 index 0000000000..d4d5d4ba76 --- /dev/null +++ b/docs/manual/about_dds/listener.rst @@ -0,0 +1,154 @@ +.. + Copyright(c) 2022 ZettaScale Technology and others + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0 which is available at + http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + v. 1.0 which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +.. index:: ! Listeners + +.. _listeners_bm: + +Listeners +========= + +Listeners enable the code to react to changes in state of DDS entities such as +readers, writers, and so on. |var-project| implements different listeners for +different entities. Some types' listeners inherit from other types' listeners, +allowing the listener of one type to react to changes in state on subordinate entities. +For example, by implementing the required callback functions for :ref:`topics ` +and :ref:`subscribers ` in a ``DomainParticipantListener``, this listener +only needs to be set once in the :ref:`DomainParticipant `, and +the topic and subscriber propagates the events to this Listener. + +.. table:: CycloneDDS Entities and associated listeners + + +-----------------------+---------------------------+-----------------------+-------------------------------+----------------------------+--------------------------------+ + | CDDS-CXX Entity Type | Listener Type | Inherits From | Associated Unique Callbacks | Associated StatusMask | Passed Status Entity | + +=======================+===========================+=======================+===============================+============================+================================+ + | DomainParticipant | DomainParticipantListener | PublisherListener | | | | + | | | SubscriberListener | | | | + | | | AnyTopicListener | | | | + +-----------------------+---------------------------+-----------------------+-------------------------------+----------------------------+--------------------------------+ + | Topic | TopicListener | | on_inconsistent_topic | inconsistent_topic | InconsistentTopicStatus | + +-----------------------+---------------------------+-----------------------+-------------------------------+----------------------------+--------------------------------+ + | Publisher | PublisherListener | DataWriterListener | | | | + +-----------------------+---------------------------+-----------------------+-------------------------------+----------------------------+--------------------------------+ + | DataWriter | DataWriterListener | | on_offered_deadline_missed | offered_deadline_missed | OfferedDeadlineMissedStatus | + | | | +-------------------------------+----------------------------+--------------------------------+ + | | | | on_offered_incompatible_qos | offered_incompatible_qos | OfferedIncompatibleQosStatus | + | | | +-------------------------------+----------------------------+--------------------------------+ + | | | | on_liveliness_lost | liveliness_lost | LivelinessLostStatus | + | | | +-------------------------------+----------------------------+--------------------------------+ + | | | | on_publication_matched | publication_matched | PublicationMatchedStatus | + +-----------------------+---------------------------+-----------------------+-------------------------------+----------------------------+--------------------------------+ + | Subscriber | SubscriberListener | DataReaderListener | | | | + +-----------------------+---------------------------+-----------------------+-------------------------------+----------------------------+--------------------------------+ + | DataReader | DataReaderListener | | on_requested_deadline_missed | requested_deadline_missed | RequestedDeadlineMissedStatus | + | | | +-------------------------------+----------------------------+--------------------------------+ + | | | | on_requested_incompatible_qos | requested_incompatible_qos | RequestedIncompatibleQosStatus | + | | | +-------------------------------+----------------------------+--------------------------------+ + | | | | on_sample_rejected | sample_rejected | SampleRejectedStatus | + | | | +-------------------------------+----------------------------+--------------------------------+ + | | | | on_liveliness_changed | liveliness_changed | LivelinessChangedStatus | + | | | +-------------------------------+----------------------------+--------------------------------+ + | | | | on_data_available | data_available | | + | | | +-------------------------------+----------------------------+--------------------------------+ + | | | | on_subscription_matched | subscription_matched | SubscriptionMatchedStatus | + | | | +-------------------------------+----------------------------+--------------------------------+ + | | | | on_sample_lost | sample_lost | SampleLostStatus | + +-----------------------+---------------------------+-----------------------+-------------------------------+----------------------------+--------------------------------+ + +A Listener is implemented as a virtual base class that defines a number of functions that correspond to status transitions in the underlying entity. +For example, the DataReaderListener has an unimplemented virtual on_data_available function, which will be called each time data is inserted into the associated DataReader's history. +DDS entities can be passed to a listener during creation, together with a StatusMask that describes which status changes to pass to the listener. + +To make use of the listener functionality, create a class deriving from the type of listener necessary and implement the virtual functions. +To simplify the use of listeners, there are also NoOp listeners that implements all virtual functions with empty contents, which enables you to implement the functions you are interested in. + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + template + ExampleListener: public dds::sub::NoOpDataReaderListener { + public: + void on_data_available(dds::sub::DataReader& reader) { + /* you also get a reference to the reader the callback originated from */ + auto samples = reader.take(); + std::cout << "I have " << samples.length() << " new samples available." << std::endl; + int invsamples = 0; + for (const auto & sample:samples) { + if (!sample.info().valid()) + invsamples++; + } + std::cout << "Of which " << invsamples << " were invalid samples." << std::endl; + } + }; + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + + +By passing this listener to a reader and setting the correct status mask, the message "I have $N new samples available.", and then "Of which $I were invalid samples.", where $N is the number of new samples and $I the number of invalid samples, appears each time the associated reader receives data: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + dds::sub::qos::DataReaderQos drqos; + ExampleListener listener; + dds::sub::DataReader reader(subscriber, topic, drqos, &listener, dds::core::status::StatusMask::data_available()); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +Some listeners' callback functions pass references to the entities that the callback originated from and/or status objects and contain information relevant to the status change. +For example, the listener for DataWriters has the following callback function that is triggered when the Deadline QoS Policy is not complied with: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + void offered_deadline_missed(dds::pub::AnyDataWriter& writer, const dds::core::status::OfferedDeadlineMissedStatus& status); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + diff --git a/docs/manual/config/mapping_domains.rst b/docs/manual/about_dds/mapping_domains.rst similarity index 50% rename from docs/manual/config/mapping_domains.rst rename to docs/manual/about_dds/mapping_domains.rst index 33b3c3fdf2..9db2217d40 100644 --- a/docs/manual/config/mapping_domains.rst +++ b/docs/manual/about_dds/mapping_domains.rst @@ -1,14 +1,20 @@ -.. _`Mapping of DCPS domains to DDSI domains`: +.. index:: + single: DCPS; Mapping to DDSI domains + single: DDSI; Mapping DCPS domains + single: Domains: Mapping DCPS to DDSI + +.. _mapping_dcps_to_ddsi: *************************************** Mapping of DCPS Domains to DDSI Domains *************************************** -In DCPS, a domain is uniquely identified by a non-negative integer, the domain ID. In -the UDP/IP mapping, this domain ID is mapped to port numbers that are used for -communicating with the peer nodes. These port numbers are of significance for -the discovery protocol. This mapping of domain IDs to UDP/IP port numbers ensures -that accidental cross-domain communication is impossible with the default mapping. +In Data-Centric Publish-Subscribe (DCPS), a domain is uniquely identified by a +non-negative integer, the domain ID. In the UDP/IP mapping, this domain ID is mapped +to port numbers that are used for communicating with the peer nodes. These port +numbers are of significance for the discovery protocol. This mapping of domain IDs +to UDP/IP port numbers ensures that accidental cross-domain communication is +impossible with the default mapping. In DCPS there is a one-to-many mapping of domain ID to port numbers. In DDSI, there is a one-to-one mapping of domain ID to a port number, which is why DDSI does not diff --git a/docs/manual/config/mapping_entities.rst b/docs/manual/about_dds/mapping_entities.rst similarity index 100% rename from docs/manual/config/mapping_entities.rst rename to docs/manual/about_dds/mapping_entities.rst diff --git a/docs/manual/about_dds/publishers.rst b/docs/manual/about_dds/publishers.rst new file mode 100644 index 0000000000..ae37806680 --- /dev/null +++ b/docs/manual/about_dds/publishers.rst @@ -0,0 +1,66 @@ +.. index:: Publishers + +.. _publishers_bm: + +========== +Publishers +========== + +A Publisher is a producer of data on a Domain. It uses the :ref:`domainparticipants_bm` to gain +access to the Domain and is created using it. That is, the Publisher passes down the +Domain from its parent class DomainParticipant. A Publisher allows the :ref:`datawriters_bm` +associated with it to share the same behaviour, for example: + +- Liveliness notifications +- :ref:`qos_bm` +- :ref:`listeners_bm` callbacks + +To use the default settings: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::pub::Publisher pub(participant); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +To supply your own settings: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::pub::NoOpPublisherListener listener; /*you need to create your own class that derives from this listener, and implement your own callbacks*/ + /*the listener implementation should implement the on_publication_matched virtual function as we will rely on it later*/ + dds::pub::qos::PublisherQos pubqos; /*add custom QoS policies that you want for this publisher*/ + dds::pub::Publisher pub(participant, pubqos, &listener, dds::core::status::StatusMask::publication_matched()); /*in this case, the only status we are interested in is publication_matched*/ + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +.. note:: + Any :ref:`datawriters_bm` created using ``pub`` inherit the qos and listener functionality as set through it. diff --git a/docs/manual/about_dds/qos.rst b/docs/manual/about_dds/qos.rst new file mode 100644 index 0000000000..f9fc12187a --- /dev/null +++ b/docs/manual/about_dds/qos.rst @@ -0,0 +1,307 @@ +.. + Copyright(c) 2022 ZettaScale Technology and others + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0 which is available at + http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + v. 1.0 which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +.. index:: ! Quality of service + +.. _qos_bm: + +Quality of Service +================== + +Quality of Service is the collection of restrictions and expectations (called +QoSPolicies) that appy to the different components of CycloneDDS. Some QoSPolicies +only affect a single type of DDS entity, whereas others affect multiple DDS entities. + +.. important:: + QoSPolicies on a DDS entity **can not** be modified after creating the entity as they + affect matching/discovery of entities. + +The QoS used is linked to the type of DDS entity the QoS is used for. For example, a +SubscriberQoS is not accepted when creating a DataReader. + +- The entity-specific QoSes are found in the `qos` sub-namespace of the same namespace + the entity is defined in. + +- The different QoSPolicies are located in the `dds::core::policy` namespace. + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. table:: DDS entity types and associated QoSes + + +-----------------------+----------------------+ + | CDDS-CXX Entity Type | QoS Type | + +=======================+======================+ + | DomainParticipant | DomainParticipantQos | + +-----------------------+----------------------+ + | Publisher | PublisherQos | + +-----------------------+----------------------+ + | Subscriber | SubscriberQos | + +-----------------------+----------------------+ + | Topic | TopicQos | + +-----------------------+----------------------+ + | DataWriter | DataWriterQos | + +-----------------------+----------------------+ + | DataReader | DataReaderQos | + +-----------------------+----------------------+ + + .. table:: QoSPolicies and associated QoSes: + + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | QoSPolicy | DomainParticipantQos | PublisherQos | SubscriberQos | TopicQos | DataWriterQos | DataReaderQos | + +============================+======================+==============+===============+==========+===============+===============+ + | UserData | Y | N | N | N | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | EntityFactory | Y | Y | Y | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | TopicData | N | N | N | Y | N | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | Durability | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | DurabilityService | N | N | N | Y | Y | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | Deadline | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | LatencyBudget | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | Liveliness | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | Reliability | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | DestinationOrder | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | History | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | ResourceLimits | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | TransportPriority | N | N | N | Y | Y | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | Lifespan | N | N | N | Y | Y | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | Ownership | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | Presentation | N | Y | Y | N | N | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | Partition | N | Y | Y | N | N | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | GroupData | N | Y | Y | N | N | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | OwnershipStrength | N | N | N | N | Y | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | WriterDataLifecycle | N | N | N | N | Y | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | TimeBasedFilter | N | N | N | N | N | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | ReaderDataLifecycle | N | N | N | N | Y | N | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | DataRepresentation | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + | TypeConsistencyEnforcement | N | N | N | Y | Y | Y | + +----------------------------+----------------------+--------------+---------------+----------+---------------+---------------+ + + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + + +Setting of QoSPolicies can be done by: + +Either left-shifting the QoSPolicy "into" the QoS: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + dds::sub::qos::DataReaderQos rqos; + rqos << dds::core::policy::Durability(dds::core::policy::DurabilityKind::TRANSIENT_LOCAL); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + + +Or passing it as the parameter of the `policy` function: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + dds::pub::qos::DataWriterQos wqos; + dds::core::policy::Reliability rel(dds::core::policy::ReliabilityKind::RELIABLE, dds::core::Duration(8, 8)); + wqos.policy(rel); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + + +Getting of QoSPolicies can be done by: + +Either through the right-shifting the QoSPolicy "out of" the QoS: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + dds::topic::qos::TopicQos tqos; + dds::core::policy::TopicData td; + tqos >> td; + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + + +Or through the `policy` function, which is templated to indicate which QoSPolicy is +being accessed: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + dds::domain::qos::DomainParticipantQos dqos; + auto ud = dqos.policy(); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + + +For a detailed explanation of the different QoSPolicies and their effects on the +behaviour of CycloneDDS, refer to the |url::dds_spec| v1.4 section 2.2.3. + +Default and Inherited QoSes +--------------------------- + +QoSes have a number of default settings that are falled-back to when none are provided +on creation. These defaults are either defined in the DDS standard, or propagated from +"superior" entities. The default inherited QoS for entities is set through the +following functions: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. table:: Default QoSes and accessors + + +-------------------+--------------------+------------------------+ + | Superior Entity | Subordinate Entity | Default QoS accessor | + +===================+====================+========================+ + | DomainParticipant | Topic | default_topic_qos | + | +--------------------+------------------------+ + | | Publisher | default_publisher_qos | + | +--------------------+------------------------+ + | | Subscriber | default_subscriber_qos | + +-------------------+--------------------+------------------------+ + | Topic | DataReader | default_datareader_qos | + | +--------------------+------------------------+ + | | DataWriter | default_datawriter_qos | + +-------------------+--------------------+------------------------+ + | Publisher | DataWriter | default_datawriter_qos | + +-------------------+--------------------+------------------------+ + | Subscriber | DataReader | default_datareader_qos | + +-------------------+--------------------+------------------------+ + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +For example, in the following case: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + dds::sub::Subscriber sub(participant); + dds::sub::qos::DataReaderQos qos1, qos2; + qos1 << dds::core::policy::Durability(dds::core::policy::DurabilityKind::TRANSIENT_LOCAL); + qos2 << dds::core::policy::DestinationOrder(dds::core::policy::DestinationOrderKind::BY_SOURCE_TIMESTAMP); + sub.default_datareader_qos(qos1); + dds::sub::DataReader reader(sub,topic,qos2); + + `reader` has its `DestinationOrder` QoSPolicy set to the value set in the QoS supplied + in its constructor, which is `BY_SOURCE_TIMESTAMP`. `Durability` QoSPolicy defaults + to the one set as default on the Subscriber, which is `TRANSIENT_LOCAL`. All other + QosPolicies default to the DDS Spec, for example, the `Ownership` QoSPolicy has the + value `SHARED`. + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + diff --git a/docs/manual/config/reliable_communication.rst b/docs/manual/about_dds/reliable_communication.rst similarity index 100% rename from docs/manual/config/reliable_communication.rst rename to docs/manual/about_dds/reliable_communication.rst diff --git a/docs/manual/about_dds/status.rst b/docs/manual/about_dds/status.rst new file mode 100644 index 0000000000..9197c24f19 --- /dev/null +++ b/docs/manual/about_dds/status.rst @@ -0,0 +1,175 @@ +.. + Copyright(c) 2022 ZettaScale Technology and others + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0 which is available at + http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + v. 1.0 which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +.. index:: ! Statuses + +.. _statuses_bm: + +Statuses +======== + +Entities in DDS have statuses that indicate the internal state and/or history of an +entity.These statuses signal Waitsets and Listeners, and are different between types +of DDS entities. The following table lists the fields for each status and their meaning: + +.. table:: CycloneDDS-CXX Status entities and fields + + +-----------------------+--------------------------------+--------------------------+------------------------------------------------------+ + | CDDS-CXX Entity Type | Status Entity | Associated Fields | Meaning of field | + +=======================+================================+==========================+======================================================+ + | DomainParticipant | | | | + +-----------------------+--------------------------------+--------------------------+------------------------------------------------------+ + | Publisher | | | | + +-----------------------+--------------------------------+--------------------------+------------------------------------------------------+ + | Subscriber | | | | + +-----------------------+--------------------------------+--------------------------+------------------------------------------------------+ + | Topic | InconsistentTopicStatus | total_count | the total number of times an inconsistent topic was | + | | | | encountered | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + +-----------------------+--------------------------------+--------------------------+------------------------------------------------------+ + | DataWriter | OfferedDeadlineMissedStatus | total_count | the total number of times an offered deadline was | + | | | | missed by the writer committing itself to the | + | | | | deadline | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | last_instance_handle | handle to the last instance in a writer missing a | + | | | | committed deadline | + | +--------------------------------+--------------------------+------------------------------------------------------+ + | | OfferedIncompatibleQosStatus | total_count | the total number of times the writer encountered a | + | | | | reader requesting a QoS which was was not compatible | + | | | | with the one offered by the writer | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | last_policy_id | the last id of the QoSPolicy which was incompatible | + | | +--------------------------+------------------------------------------------------+ + | | | policies | a collection of QoSPolicy ids and the number times | + | | | | they were found to be incompatible | + | +--------------------------------+--------------------------+------------------------------------------------------+ + | | LivelinessLostStatus | total_count | the total number of times a writer became "dead" by | + | | | | not asserting its liveliness often enough | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + | +--------------------------------+--------------------------+------------------------------------------------------+ + | | PublicationMatchedStatus | total_count | the total number of times a writer has encountered a | + | | | | reader it has a "match" with | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | current_count | the current number of readers a writer has a "match" | + | | | | with | + | | +--------------------------+------------------------------------------------------+ + | | | current_count_change | the change in current_count since last being | + | | | | retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | last_subscription_handle | handle to the last reader causing this status to | + | | | | change | + +-----------------------+--------------------------------+--------------------------+------------------------------------------------------+ + | DataReader | RequestedDeadlineMissedStatus | total_count | total number of missed deadlines for instances read | + | | | | by the reader | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | last_instance_handle | the last instance handle to miss a deadline | + | +--------------------------------+--------------------------+------------------------------------------------------+ + | | RequestedIncompatibleQosStatus | total_count | the total number of times the reader encountered a | + | | | | writer offering a QoS which was was not compatible | + | | | | with the one requested by the reader | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | last_policy_id | the last id of the QoSPolicy which was incompatible | + | | +--------------------------+------------------------------------------------------+ + | | | policies | a collection of QoSPolicy ids and the number times | + | | | | they were found to be incompatible | + | +--------------------------------+--------------------------+------------------------------------------------------+ + | | SampleRejectedStatus | total_count | total number of samples rejected by the reader | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | last_reason | the last reason for rejecting a sample | + | | +--------------------------+------------------------------------------------------+ + | | | last_instance_handle | handle to last instance encountering a rejected | + | | | | sample | + | +--------------------------------+--------------------------+------------------------------------------------------+ + | | LivelinessChangedStatus | alive_count | the total number of matching writers that are alive | + | | +--------------------------+------------------------------------------------------+ + | | | alive_count_change | the change in alive_count since last being retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | not_alive_count | the total number of matching writers that are dead | + | | +--------------------------+------------------------------------------------------+ + | | | not_alive_count_change | the change in not_alive_count since last being | + | | | | retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | last_publication_handle | handle to the last writer causing this to change | + | +--------------------------------+--------------------------+------------------------------------------------------+ + | | SubscriptionMatchedStatus | total_count | the total number of times a reader has encountered a | + | | | | writer it has a "match" with | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | current_count | the current number of writers a reader has a "match" | + | | | | with | + | | +--------------------------+------------------------------------------------------+ + | | | current_count_change | the change in current_count since last being | + | | | | retrieved | + | | +--------------------------+------------------------------------------------------+ + | | | last_publication_handle | handle to the writer causing this status to change | + | +--------------------------------+--------------------------+------------------------------------------------------+ + | | SampleLostStatus | total_count | the total number of samples lost in the topic | + | | +--------------------------+------------------------------------------------------+ + | | | total_count_change | the change in total_count since last being retrieved | + +-----------------------+--------------------------------+--------------------------+------------------------------------------------------+ + +Fields of status objects containing counts of events will have both a cumulative and interval count, +where the cumulative count will keep track of all changes during the lifetime of the DDS entity, +and the interval count is the number of changes since the previous readout of the status. +To access the statuses, use the following functions on the entity: + +.. table:: CycloneDDS-CXX Status accessors + + +-----------------------+--------------------------------+----------------------------------+ + | CDDS-CXX Entity Type | Status Entity | Accessor | + +=======================+================================+==================================+ + | Topic | InconsistentTopicStatus | inconsistent_topic_status | + +-----------------------+--------------------------------+----------------------------------+ + | DataWriter | OfferedDeadlineMissedStatus | offered_deadline_missed_status | + | +--------------------------------+----------------------------------+ + | | OfferedIncompatibleQosStatus | offered_incompatible_qos_status | + | +--------------------------------+----------------------------------+ + | | LivelinessLostStatus | liveliness_lost_status | + | +--------------------------------+----------------------------------+ + | | PublicationMatchedStatus | publication_matched_status | + +-----------------------+--------------------------------+----------------------------------+ + | DataReader | RequestedDeadlineMissedStatus | requested_deadline_missed_status | + | +--------------------------------+----------------------------------+ + | | RequestedIncompatibleQosStatus | requested_incompatible_status | + | +--------------------------------+----------------------------------+ + | | SampleRejectedStatus | sample_rejected_status | + | +--------------------------------+----------------------------------+ + | | LivelinessChangedStatus | liveliness_changed_status | + | +--------------------------------+----------------------------------+ + | | SubscriptionMatchedStatus | subscription_matched_status | + | +--------------------------------+----------------------------------+ + | | SampleLostStatus | sample_lost_status | + +-----------------------+--------------------------------+----------------------------------+ + +The following code fragment shows statuses that make a writer wait until readers are present: + +.. code:: C++ + + dds::pub::DataWriter wr(publisher, topic); + while (0 == wr.publication_matched_status().current_count()) + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + +The writer polls the total number of readers that are receiving data from it at 20 millisecond intervals for as long as there are no readers. diff --git a/docs/manual/about_dds/subscribers.rst b/docs/manual/about_dds/subscribers.rst new file mode 100644 index 0000000000..904807b2ce --- /dev/null +++ b/docs/manual/about_dds/subscribers.rst @@ -0,0 +1,65 @@ +.. index:: Subscribers + +.. _subscribers_bm: + +=========== +Subscribers +=========== + +A Subscriber is a consumer of data on a Domain. It uses the :ref:`domainparticipants_bm` +to gain access to the Domain and is created using it. A Subscriber allows the +:ref:`datareaders_bm` associated with it to share the same behaviour, such as: + +- Liveliness notifications +- :ref:`qos_bm` +- :ref:`listeners_bm` callbacks + +To use the default settings: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::sub::Subscriber sub(participant); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +To supply your own settings: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::sub::NoOpSubscriberListener listener; /*you need to create your own class that derives from this listener, and implement your own callbacks*/ + /*the listener implementation should implement the on_subscription_matched virtual function as we will rely on it later*/ + dds::sub::qos::SubscriberQos subqos; /*add custom QoS policies that you want for this subscriber*/ + dds::sub::Subscriber sub(participant, subqos, &listener, dds::core::status::StatusMask::subscription_matched()); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +.. note:: + Any :ref:`datareaders_bm` created using ``sub`` inherit the qos and listener functionality as set through it. diff --git a/docs/manual/about_dds/topics.rst b/docs/manual/about_dds/topics.rst new file mode 100644 index 0000000000..76c3002112 --- /dev/null +++ b/docs/manual/about_dds/topics.rst @@ -0,0 +1,84 @@ +.. index:: ! Topics + +.. _topics_bm: + +====== +Topics +====== + +A topic is a subsection of a DDS Domain that enables exchange of data of a specific +type, and that complies with certain restrictions on the exchange before exchange can +occur. + +A topic is identifiable by: + +- **Name**: Identifies the topic on the Domain. Must be unique on the Domain. +- **Quality of Service** (optional): Determines the restrictions on the exchange. This is + an optional parameter, which can be derived from fallbacks to the participant or + defaults. + +- **Type**: The type of data being exchanged, which is the template parameter of the + topic class: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + :ref:`topic_bm` + + .. group-tab:: C++ + + `dds::topic::Topic class `_ + + .. code-block:: C++ + + template class Topic { + ... + // Constructor + Topic(const dds::domain::DomainParticipant& dp, + const std::string& name, + const std::string& type_name, + const dds::topic::qos::TopicQos& qos, + dds::topic::TopicListener* listener, + const dds::core::status::StatusMask& mask); + ... + } + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + + + +A topic is for exchanging data of the type **Data_Type**. The following shows how a +topic is created on the DomainParticipant participant: + + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code:: C++ + + dds::topic::Topic topic(participant, "DataType Topic"); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +To generate the data type of the topic from the user's IDL files, use CycloneDDS's ``idlc`` +generator (with the idlcxx library). + +.. important:: + Using types other than those generated from ``idlc`` + ``idlcxx`` in the template + does not have the prerequisite traits, and therefore does not result in working code. diff --git a/docs/manual/about_dds/waitset.rst b/docs/manual/about_dds/waitset.rst new file mode 100644 index 0000000000..6bfa76af15 --- /dev/null +++ b/docs/manual/about_dds/waitset.rst @@ -0,0 +1,152 @@ +.. + Copyright(c) 2022 ZettaScale Technology and others + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0 which is available at + http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + v. 1.0 which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +.. index:: Waitsets + +.. _waitsets_bm: + +Waitsets +======== + +The Waitsets tool in |var-project-short| holds execution of the program until a +specific condition is reached, or an amount of time has expired. Waitsets and +:ref:`listeners ` have two different requirement sets: + +- A Waitset allows the code to react when nothing changes. +- Listeners can only react to changes in state. Listeners allow instant callbacks to + specific changes. + +A StatusCondition (linked to an entity) signals to the waitset that its wait is finished. +The StatusCondition has a list of conditions (changes in status) that can trigger the +waitset to finish its wait. When creating a StatusCondition, the enabled statuses +should match the type of entity it is attached to. Different StatusConditions linked +to different Entities can be attached to a Waitset through the ``attach_condition`` +function, and detached through the ``detach_condition`` function. After creating a +waitset with StatusConditions attached, a wait can be triggered for the Duration +specified. Triggering the wait causes one of two things to happen: + +- The wait will time out, causing an exception of the type ``dds::core::TimeoutError``. +- A status change of one of the attached conditions occurs, and the returned container + contains the conditions that have triggered the end of the wait. + +The following code does not work because the ``subscription_matched`` is a status +associated with a DataReader: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + dds::sub::DataReader reader(sub, topic); + dds::core::cond::StatusCondition rsc(reader); + rsc.enabled_statuses(dds::core::status::StatusMask::subscription_matched()); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + + +The following code does not work because the ``liveliness_lost`` is not a status associated +with a Topic: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + dds::topic::Topic topic(participant,"topic"); + dds::core::cond::StatusCondition tsc(topic); + tsc.enabled_statuses(dds::core::status::StatusMask::liveliness_lost()); + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +The following code attempts to wait a specified amount of time for readers and writers +to see their counterparts, allowing two-way communication to occur: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + template + bool match_reader_and_writer(dds::sub::DataReader &rd, dds::pub::DataWriter &wr, const dds::core::Duration &dur) { + try { + + dds::core::cond::StatusCondition wsc(wr), rsc(rd); + wsc.enabled_statuses(dds::core::status::StatusMask::publication_matched()); + rsc.enabled_statuses(dds::core::status::StatusMask::subscription_matched()); + + dds::core::cond::WaitSet waitset; + waitset.attach_condition(wsc); + waitset.attach_condition(rsc); + + auto start = std::chrono::steady_clock::now(); + auto result = waitset.wait(dur); + + bool is_pub = false; + if (result.empty()) { + return false; + } if (result[0] == wsc) { + is_pub = true; + waitset.detach_condition(wsc); + } else if (result[0] == rsc) { + waitset.detach_condition(rsc); + } else { + return false; + } + + auto diff = std::chrono::steady_clock::now()-start; + dur -= dds::core::Duration(std::chrono::duration_cast(diff).count(), std::chrono::duration_cast(diff).count()%1000000000); + result = waitset.wait(dur); + + if (result.empty() || (is_pub && result[0] != rsc) || (!is_pub && result[0] != wsc)) + return false; + } catch (const dds::core::TimeoutError &) { + return false; + } + return true; + } + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + +The above function returns true if the reader and writer have encountered matching +publications and subscriptions before the timeout's duration expired, and false otherwise. diff --git a/docs/manual/api/topic.rst b/docs/manual/api/topic.rst index a00c4fccd8..877054f6cb 100644 --- a/docs/manual/api/topic.rst +++ b/docs/manual/api/topic.rst @@ -1,3 +1,7 @@ +.. index:: Topics + +.. _topic_bm: + Topics ====== diff --git a/docs/manual/getting_started/installation/benchmarking.rst b/docs/manual/config/benchmarking.rst similarity index 98% rename from docs/manual/getting_started/installation/benchmarking.rst rename to docs/manual/config/benchmarking.rst index 7769c88419..b7f3ed532b 100644 --- a/docs/manual/getting_started/installation/benchmarking.rst +++ b/docs/manual/config/benchmarking.rst @@ -1,3 +1,7 @@ +.. index:: Benchmarking + +.. _benchmarking_bm: + ################## Benchmarking Tools ################## @@ -19,7 +23,11 @@ parameterized sizes. benchmarking tools as they sacrifice performance for simplicity. You cannot compare test results from these tools with results from other tools. -.. include:: test_installation.part.rst +.. include:: ../test_installation.part.rst + +.. index:: Latency + +.. _latency_bm: Measuring latency ================= diff --git a/docs/manual/config/discovery-behavior.rst b/docs/manual/config/discovery-behavior.rst index 3935756698..424ee6be1f 100644 --- a/docs/manual/config/discovery-behavior.rst +++ b/docs/manual/config/discovery-behavior.rst @@ -14,18 +14,18 @@ Discovery behaviour Proxy participants and endpoints ******************************** -In the |url::ddsi_spec|, |var-project| is known as a *stateful* implementation. Writers -only send data to discovered Readers, and Readers only accept data from discovered -Writers. There is one exception: the ``Writer`` may choose to multicast the data so -that any Reader is able to receive it. If a Reader has already discovered the Writer +In the |url::ddsi_spec|, |var-project| is known as a *stateful* implementation. writers +only send data to discovered readers, and readers only accept data from discovered +writers. There is one exception: the ``writer`` may choose to multicast the data so +that any reader is able to receive it. If a reader has already discovered the writer but not vice-versa, it can accept the data even though the connection is not fully established. Such asymmetrical discovery can cause data to be delivered when it is not expected, which can also cause indefinite blocking. To avoid this, |var-project| internally -creates a proxy for each remote participant and Reader or Writer. In the discovery -process, Writers are matched with proxy Readers, and Readers are matched with proxy -Writers, based on the topic name, type name, and the QoS settings. +creates a proxy for each remote participant and reader or writer. In the discovery +process, writers are matched with proxy readers, and readers are matched with proxy +writers, based on the topic name, type name, and the :ref:`QoS ` settings. Proxies have the same natural hierarchy as 'normal' DDSI entities. Each proxy endpoint is owned by a proxy participant. When a proxy participant is deleted, all of its proxy @@ -76,57 +76,57 @@ participant or endpoint, it can generate some redundant network traffic. Lingering writers ***************** -When an application deletes a reliable DCPS Writer, there is no guarantee that all -its Readers have already acknowledged the correct receipt of all samples. |var-project| -lets the Writer (and the owning participant if necessary) linger in the system for some time, -controlled by the :ref:`Internal/WriterLingerDuration ` -option. The Writer is deleted when all Readers have acknowledged all samples, or the +When an application deletes a reliable DCPS writer, there is no guarantee that all +its readers have already acknowledged the correct receipt of all samples. |var-project| +lets the writer (and the owning participant if necessary) linger in the system for some time, +controlled by the :ref:`Internal/writerLingerDuration ` +option. The writer is deleted when all readers have acknowledged all samples, or the linger duration has elapsed, whichever comes first. .. note:: - The Writer linger duration setting is not applied when |var-project| + The writer linger duration setting is not applied when |var-project| is requested to terminate. -.. _`Writer history QoS and throttling`: +.. _`writer history QoS and throttling`: -.. index:: ! Writer History Cache +.. index:: ! writer History Cache ********************************* Writer history QoS and throttling ********************************* -The |url::ddsi_spec| relies on the Writer History Cache (WHC), in which a sequence number +The |url::ddsi_spec| relies on the writer History Cache (WHC), in which a sequence number uniquely identifies each sample. The WHC integrates two different indices on the samples -published by a Writer: +published by a writer: - The **sequence number** index is used for re-transmitting lost samples, and is therefore needed - for all reliable Writers (see :ref:`reliable_coms`). + for all reliable writers (see :ref:`reliable_coms`). - The **key value** index is used for retaining the current state of each instance in the WHC. When a new sample overwrites the state of an instance, the key value index allows dropping samples from the sequence number index. For transient-local behaviour (see :ref:`DDSI-specific transient-local behaviour`), the key value index also allows retaining -the current state of each instance even when all Readers have acknowledged a sample. +the current state of each instance even when all readers have acknowledged a sample. Transient-local data always requires the key values index, and by default is also -used for other Writers that have a history setting of ``KEEP_LAST``. The advantage of an +used for other writers that have a history setting of ``KEEP_LAST``. The advantage of an index on key value is that superseded samples can be dropped aggressively, instead of -delivering them to all Readers. The disadvantage is that it is somewhat more resource-intensive. +delivering them to all readers. The disadvantage is that it is somewhat more resource-intensive. The WHC distinguishes between: -- History to be retained for existing Readers (controlled by the Writer's history QoS setting). +- History to be retained for existing readers (controlled by the writer's history QoS setting). - History to be retained for late-joining readers for transient-local writers (controlled by the topic's durability-service history QoS setting). -It is therefore possible to create a Writer that never overwrites samples for live readers, +It is therefore possible to create a writer that never overwrites samples for live readers, while maintaining only the most recent samples for late-joining readers. This ensures that the data that is available for late-joining readers is the same for transient-local and for transient data. -.. Index:: ! Writer throttling +.. Index:: ! writer throttling Writer throttling ================= @@ -134,7 +134,7 @@ Writer throttling Writer throttling is based on the WHC size. The following settings control writer throttling: When the WHC contains at least ``high`` bytes in unacknowledged samples, it stalls the -Writer until the number of bytes in unacknowledged samples drops below the value set in: +writer until the number of bytes in unacknowledged samples drops below the value set in: :ref:`Internal/Watermarks/WhcLow `. Based on the transmit pressure and receive re-ransmit requests, the value of ``high`` is diff --git a/docs/manual/config/index.rst b/docs/manual/config/index.rst index 92a0a54c82..e9e54e0f7f 100644 --- a/docs/manual/config/index.rst +++ b/docs/manual/config/index.rst @@ -87,4 +87,6 @@ To determine the information included in the log file, change the :ref:`Tracing/ thread-config reporting-tracing conformance - config_file_reference \ No newline at end of file + config_file_reference + runtime_config + benchmarking \ No newline at end of file diff --git a/docs/manual/config/network_interfaces.rst b/docs/manual/config/network_interfaces.rst index 14bf5e2694..db76e2a28f 100644 --- a/docs/manual/config/network_interfaces.rst +++ b/docs/manual/config/network_interfaces.rst @@ -8,7 +8,7 @@ Networking interfaces |var-project| can use multiple network interfaces simultaneously (the default is a single network interface). The set of enabled interfaces determines the addresses that the host -advertises in the discovery information (see :ref:`Discovery of participants and endpoints`). +advertises in the discovery information (see :ref:`discovery_participants_endpoints`). ----------------- Default behaviour diff --git a/docs/manual/cpp/cpp_api_link.rst b/docs/manual/cpp/cpp_api_link.rst new file mode 100644 index 0000000000..e0b4b74612 --- /dev/null +++ b/docs/manual/cpp/cpp_api_link.rst @@ -0,0 +1,5 @@ +.. include:: ../external-links.part.rst + +=================== +|url::cpp_api_link| +=================== \ No newline at end of file diff --git a/docs/manual/cpp/cpp_custom_containers.rst b/docs/manual/cpp/cpp_custom_containers.rst new file mode 100644 index 0000000000..96fcc99c68 --- /dev/null +++ b/docs/manual/cpp/cpp_custom_containers.rst @@ -0,0 +1,194 @@ +.. + Copyright(c) 2021 ZettaScale Technology and others + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0 which is available at + http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + v. 1.0 which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +.. index:: Custom containers (C++) + +.. _cpp_custom_containers: + +C++ custom containers +===================== + +IDLCXX enables users to supply their own container classes, replacing the default containers +used for IDL sequences (bounded and unbounded), strings (bounded and unbounded), arrays and +unions. All custom containers templates are set through the ``-f`` command line option, followed +by the option to be set, an equals sign and the value to set it to. Each template can have a +varying number of tags, which are indicated by the following strings: + +- ``{TYPE}``: will replace type names in sequences and arrays + +- ``{BOUND}``: will replace maximum size values in bounded sequences and strings + +- ``{DIMENSION}``: will replace size in arrays + +For example, to set a custom container for the bounded sequence, you must add the following +to the command line options of ``idlc``: + +.. code:: bash + + -f bounded-sequence-template="company_name::special_bounded_sequence_impl<{TYPE}, {BOUND}>" + +Supplying this command line option converts the following IDL code from: + +.. code:: IDL + + sequence + +to the following C++ code: + +.. code:: C++ + + company_name::special_bounded_sequence_impl + +For each template, the ordering of the tags is not important, the generator will replace based +on tags, not positions, all other text is inserted into the generated code verbatim. This enables +custom allocators to also be added. + +For more information on all command line options, run ``idlc`` with the ``-h`` option, while loading +the idlcxx library. For example: + +.. code:: bash + + idlc -l libdidlcxx.so -h + +Sequences +--------- + +The default container for both bounded and unbounded IDL sequences is ``std::vector``. +The custom containers for bounded and unbounded sequences can be defined independently. +Any user-supplied container class that replaces ``std::vector`` must comply +with the following interface (with the same effect as these functions in std::vector): + +- ``size`` + +- ``resize`` + +- ``data`` + +- ``operator==`` + +- ``operator[]`` + +- ``copy assignment operator`` + +- ``copy constructor`` + +The command line options for custom sequence containers are: + +- ``bounded-sequence-template`` + + - template used for bounded sequences instead of ``std::vector`` + + - replaced tags: ``{TYPE}``, ``{BOUND}`` + +- ``bounded-sequence-include`` + + - header to include if ``bounded-sequence-template`` is used + +- ``sequence-template`` + + - template used for sequences instead of ``std::vector`` + + - replaced tags: ``{TYPE}`` + +- ``sequence-include`` + + - header to include if ``sequence-template`` is used + +Strings +------- + +The default container used for both bounded and unbounded IDL strings is ``std::string``. +The custom containers for bounded and unbounded strings can be defined independently. +Any user-supplied container class that replaces ``std::string`` must comply +with the following interface (with the same effect as these functions in ``std::string``): + +- ``length`` + +- ``assign`` + + - the variant taking an input pointer and a length + +- ``operator==`` + +- ``copy assignment operator`` + +- ``copy constructor`` + +The command line options for custom string containers are: + +- ``bounded-string-template`` + + - template to use for strings instead of ``std::string`` + + - replaced tags: ``{BOUND}`` + +- ``bounded-string-include`` + + - header to include if ``bounded-string-template`` is used + +- ``string-template`` + + - template to use for strings instead of ``std::string`` + + - replaced tags: none + +- ``string-include`` + + - header to include if ``string-template`` is used + +Arrays +------ + +The default container used for IDL arrays is ``std::array``. +Any user-supplied container class that replaces ``std::array`` must comply +with the following interface (with the same effect as these functions in ``std::array``): + +- support auto-range for loops + + - having begin() and end() functions returning iterators to the begin and end of the array + +- the function data() + +The command line options for custom array containers are: + +- ``array-template`` + + - template to use for arrays instead of ``std::array`` + + - replaced tags: ``{TYPE}``, ``{DIMENSION}`` + +- ``array-include`` + + - header to include if template for ``array-template`` is used + +Unions +------ + +IDL unions use the ``std::variant`` class by default as the container for the union values. +The only function needed from the custom union container is the templated getter function: + +.. code:: c++ + + templateT get(variant& var) + +The command line options for custom variant containers are: + +- ``union-getter-template`` + + - template to use for reading the value of a variant, copied verbatim + +- ``union-template`` + + - template to use for unions instead of ``std::variant``, copied verbatim + +- ``union-include`` + + - header to include if template for union-template is used diff --git a/docs/manual/cpp/ddscpp.rst b/docs/manual/cpp/ddscpp.rst new file mode 100644 index 0000000000..38ecd8d087 --- /dev/null +++ b/docs/manual/cpp/ddscpp.rst @@ -0,0 +1,28 @@ +.. + Copyright(c) 2006 to 2021 ZettaScale Technology and others + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0 which is available at + http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + v. 1.0 which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +.. include:: ../external-links.part.rst + +.. index:: + single: C++; API reference + single: API; C++ reference + +.. _cpp_api_ref_bm: + +================= +C++ API reference +================= + +.. toctree:: + :maxdepth: 1 + + cpp_api_link + cpp_custom_containers diff --git a/docs/manual/ddsc.rst b/docs/manual/ddsc.rst index d719070053..ad28d08d96 100644 --- a/docs/manual/ddsc.rst +++ b/docs/manual/ddsc.rst @@ -9,7 +9,11 @@ SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -C API Reference +.. index:: + single: C API reference + single: API; C reference + +C API reference =============== .. toctree:: diff --git a/docs/manual/examples/example_dds.rst b/docs/manual/examples/example_dds.rst new file mode 100644 index 0000000000..ece25658a9 --- /dev/null +++ b/docs/manual/examples/example_dds.rst @@ -0,0 +1,140 @@ +.. index:: + single: Examples; Example DDS DataType + single: DataType; DDS Example + single: DDS; Example DataType + +.. _datatype_example: + +=========== +Example DDS +=========== + +The following is example code for writing data of the type ``DataType``. The writer waits +for a reader to appear and then writes a single sample to the DDS service. It then +waits for the reader to disappear and then exits: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + /* for std::this_thread */ + #include + + /* include C++ DDS API. */ + #include "dds/dds.hpp" + + /* include the c++ data type, generated from idlcxx */ + #include "DataType.hpp" + + using namespace org::eclipse::cyclonedds; + + int main() { + /*errors in construction/etc are indicated by exceptions*/ + try { + dds::domain::DomainParticipant participant(domain::default_id()); + + dds::topic::Topic topic(participant, "DataType Topic"); + + dds::pub::Publisher publisher(participant); + + dds::pub::DataWriter writer(publisher, topic); + + /*we wait for a reader to appear*/ + while (writer.publication_matched_status().current_count() == 0) + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + + DataType msg; + + /*modify msg*/ + + writer.write(msg); + + /*we wait for the reader to disappear*/ + while (writer.publication_matched_status().current_count() > 0) + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } catch (const dds::core::Exception& e) { + std::cerr << "An exception occurred: " << e.what() << std::endl; + exit(1); + } + return 0; + } + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD + + +The reader periodically checks (every 20ms) for received data. When it receives some data, it stops: + +.. tabs:: + + .. group-tab:: Core DDS (C) + + .. code:: C + + C code sample TBD + + .. group-tab:: C++ + + .. code-block:: C++ + + /* for std::this_thread */ + #include + + /* include C++ DDS API. */ + #include "dds/dds.hpp" + + /* include the c++ data type, generated from idlcxx */ + #include "DataType.hpp" + + using namespace org::eclipse::cyclonedds; + + int main() { + + /*errors in construction/etc are indicated by exceptions*/ + try { + dds::domain::DomainParticipant participant(domain::default_id()); + + dds::topic::Topic topic(participant, "DataType Topic"); + + dds::sub::Subscriber subscriber(participant); + + dds::sub::DataReader reader(subscriber, topic); + + /*we periodically check the reader for new samples*/ + bool reading = true; + while (reading) { + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + auto samples = reader.take(); + for (const auto & p:samples) { + const auto& info = p.info(); /*metadata*/ + if (info.valid()) { + /*this sample contains valid data*/ + const auto& msg = p.data(); /* the actual data */ + std::cout << "Message received." << std::endl; + reading = false; /*we are done reading*/ + } + } + } + } catch (const dds::core::Exception& e) { + std::cerr << "An exception occurred: " << e.what() << std::endl; + exit(1); + } + return 0; + } + + .. group-tab:: Python + + .. code:: Python + + Python code sample TBD diff --git a/docs/manual/examples/index.rst b/docs/manual/examples/index.rst index ce4479060e..c497270b3e 100644 --- a/docs/manual/examples/index.rst +++ b/docs/manual/examples/index.rst @@ -15,6 +15,7 @@ Examples throughput listtopics dynsub + dds_datatype_example - :ref:`helloworld_bm` @@ -37,6 +38,9 @@ Examples The dynsub example is a :term:`PoC` for a C-based JSON printer for arbitrary data. It assumes that topic discovery is enabled (but doesn't require it). +- :ref:`_datatype_example` + This is a DDS example for writing data of the type ``DataType``. + .. note:: |var-project| has various configuration parameters and comes with a default built-in configuration. To run an example, or any application that uses |var-project| for its data diff --git a/docs/manual/external-links.part.rst b/docs/manual/external-links.part.rst index b5e6da77f0..82efee2827 100644 --- a/docs/manual/external-links.part.rst +++ b/docs/manual/external-links.part.rst @@ -197,6 +197,19 @@ GitHub ddsperf +.. |url::cpp_api_link| raw:: html + + C++ API reference + .. |url::idl_4.2| raw:: html + + OMG IDL + +.. |url::py_api_link| raw:: html + + Python API reference + +.. |url::runtype_link| raw:: html + + runtype - OMG IDL \ No newline at end of file diff --git a/docs/manual/genindex.rst b/docs/manual/genindex.rst new file mode 100644 index 0000000000..66a235227a --- /dev/null +++ b/docs/manual/genindex.rst @@ -0,0 +1,2 @@ +Index +===== \ No newline at end of file diff --git a/docs/manual/getting_started/contributing.rst b/docs/manual/getting_started/contributing.rst deleted file mode 100644 index a67d4c3073..0000000000 --- a/docs/manual/getting_started/contributing.rst +++ /dev/null @@ -1,82 +0,0 @@ -.. include:: ../external-links.part.rst - -.. index:: Contributing - -.. _contributing_to_dds: - -Contributing to |var-project| -============================= - -We welcome all contributions to the project, including questions, -examples, bug fixes, enhancements or improvements to the documentation, -etc. - - -.. tip:: - - Contributing to |var-project| means donating your code to the Eclipse foundation. It requires that you - sign the |url::eclipse_link| using |url::eclipse-form_link|. In summary, this means that your contribution is - yours to give away, and that you allow others to use and distribute it. However, don't take legal advice - from this getting started guide, read the terms linked above. - -To contribute code, it may be helpful to know that build configurations for Azure DevOps Pipelines -are present in the repositories. -There is a test suite using CTest and |url::cunit_link| that can be built locally. - -The following sections explain how to do this for the different -operating systems. - -Linux and macOS ---------------- - -Set the CMake variable ``BUILD_TESTING`` to ``ON`` when configuring, e.g.: - -.. code-block:: bash - - cd build - cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON .. - cmake --build . - ctest - -This build requires |url::cunit_link|. You can -install this yourself, or you can choose to instead rely on the -|url::conan_link| packaging system that the CI build -infrastructure also uses. In that case, install Conan in the build -directory before running CMake: - -.. code-block:: bash - - conan install .. --build missing - - -Windows -------- - -Set the CMake variable ``BUILD_TESTING`` to ``ON`` when configuring, e.g.: - -.. code-block:: bash - - cd build - cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON .. - cmake --build . - ctest - -This build requires |url::cunit_link|. You can -install this yourself, or you can choose to instead rely on the -|url::conan_link| packaging system that the CI build -infrastructure also uses. In that case, install Conan in the build -directory before running CMake: - -.. code-block:: bash - - conan install .. --build missing - -This automatically downloads and builds CUnit (and currently OpenSSL for transport security). - -.. note:: - - Depending on the generator, you may also need to add switches to select the architecture and build type, e.g.: - - .. code-block:: bash - - conan install -s arch=x86_64 -s build_type=Debug .. diff --git a/docs/manual/getting_started/helloworld/helloworld_idl.rst b/docs/manual/getting_started/helloworld/helloworld_idl.rst index 78b935506f..fe2785873d 100644 --- a/docs/manual/getting_started/helloworld/helloworld_idl.rst +++ b/docs/manual/getting_started/helloworld/helloworld_idl.rst @@ -35,8 +35,7 @@ In our simplistic case, the data type Msg contains two fields: ``userID`` and ``message`` payload. The ``userID`` is used to uniquely identify each message instance. This is done using the ``@key`` annotation. -IDL Compilers -============= +For further information, refer to :ref:`idl_compilers`. .. tabs:: @@ -55,23 +54,6 @@ IDL Compilers .. group-tab:: C++ - The |var-project-short| C++ IDL compiler translates module names into namespaces - and structure names into classes. - - It also generates code for public accessor functions for all fields mentioned in - the IDL struct, separate public constructors, and a destructor: - - - A default (empty) constructor that recursively invokes the constructors of - all fields. - - A copy-constructor that performs a deep copy from the existing class. - - A move-constructor that moves all arguments to its members. - - The destructor recursively releases all fields. It also generates code for - assignment operators that recursively construct all fields based on the - parameter class (copy and move versions). The following code snippet is - provided without warranty: the internal format may change, but the API - delivered to your application code is stable. - .. code-block:: C++ namespace HelloWorldData @@ -142,14 +124,6 @@ IDL Compilers } -.. note:: - - When translated into a different programming language, the data has another - representation specific to the target language. This highlights the advantage - of using a neutral language such as IDL to describe the data model. It can be - translated into different languages that can be shared between different - applications written in other programming languages. - Generated files with the IDL compiler ===================================== diff --git a/docs/manual/getting_started/index.rst b/docs/manual/getting_started/index.rst index a19bda971f..f00647accc 100644 --- a/docs/manual/getting_started/index.rst +++ b/docs/manual/getting_started/index.rst @@ -16,12 +16,7 @@ Getting Started :maxdepth: 2 :caption: Contents - installation/installation helloworld/helloworld - py_tutorial/index - installation/benchmarking - contributing + py_tutorial_link -.. include:: disclaimer.part.rst - diff --git a/docs/manual/getting_started/py_tutorial_link.rst b/docs/manual/getting_started/py_tutorial_link.rst new file mode 100644 index 0000000000..6dd673d5e4 --- /dev/null +++ b/docs/manual/getting_started/py_tutorial_link.rst @@ -0,0 +1 @@ +.. include:: ../python/py_tutorial.rst \ No newline at end of file diff --git a/docs/manual/index.rst b/docs/manual/index.rst index 954ec755f4..fafb6f1f36 100644 --- a/docs/manual/index.rst +++ b/docs/manual/index.rst @@ -11,6 +11,8 @@ .. _documentation_top: +.. image:: _static/gettingstarted-figures/Cyclone_DDS_logo.svg + |var-project| |var-release| documentation ========================================= @@ -18,17 +20,20 @@ :maxdepth: 1 about_dds/eclipse_cyclone_dds + installation/installation getting_started/index config/index examples/index security/dds_security shared_memory/shared_memory ddsc + cpp/ddscpp + python/ddspython glossary + genindex Indices and tables ================== -* :ref:`genindex` * :ref:`modindex` * :ref:`search` diff --git a/docs/manual/getting_started/installation/closing_remarks.part.rst b/docs/manual/installation/closing_remarks.part.rst similarity index 98% rename from docs/manual/getting_started/installation/closing_remarks.part.rst rename to docs/manual/installation/closing_remarks.part.rst index 98710122e6..a1ffe2058c 100644 --- a/docs/manual/getting_started/installation/closing_remarks.part.rst +++ b/docs/manual/installation/closing_remarks.part.rst @@ -1,5 +1,5 @@ -Want to know more about DDS? -============================ - -The primary source of information is the OMG website at `http://www.omg.org `__, specifically the `DDS -Getting Started `__\ page and the `DDS specification `__. +Want to know more about DDS? +============================ + +The primary source of information is the OMG website at `http://www.omg.org `__, specifically the `DDS +Getting Started `__\ page and the `DDS specification `__. diff --git a/docs/manual/getting_started/installation/core_cpp_common_build.rst b/docs/manual/installation/core_cpp_common_build.rst similarity index 100% rename from docs/manual/getting_started/installation/core_cpp_common_build.rst rename to docs/manual/installation/core_cpp_common_build.rst diff --git a/docs/manual/getting_started/installation/dsperf_tool.rst b/docs/manual/installation/dsperf_tool.rst similarity index 100% rename from docs/manual/getting_started/installation/dsperf_tool.rst rename to docs/manual/installation/dsperf_tool.rst diff --git a/docs/manual/getting_started/installation/installation.cpp.rst b/docs/manual/installation/installation.cpp.rst similarity index 100% rename from docs/manual/getting_started/installation/installation.cpp.rst rename to docs/manual/installation/installation.cpp.rst diff --git a/docs/manual/getting_started/installation/installation.dds_core.rst b/docs/manual/installation/installation.dds_core.rst similarity index 100% rename from docs/manual/getting_started/installation/installation.dds_core.rst rename to docs/manual/installation/installation.dds_core.rst diff --git a/docs/manual/getting_started/installation/installation.python.rst b/docs/manual/installation/installation.python.rst similarity index 100% rename from docs/manual/getting_started/installation/installation.python.rst rename to docs/manual/installation/installation.python.rst diff --git a/docs/manual/getting_started/installation/installation.rst b/docs/manual/installation/installation.rst similarity index 100% rename from docs/manual/getting_started/installation/installation.rst rename to docs/manual/installation/installation.rst diff --git a/docs/manual/getting_started/installation/language_install.rst b/docs/manual/installation/language_install.rst similarity index 100% rename from docs/manual/getting_started/installation/language_install.rst rename to docs/manual/installation/language_install.rst diff --git a/docs/manual/getting_started/installation/platforms.rst b/docs/manual/installation/platforms.rst similarity index 100% rename from docs/manual/getting_started/installation/platforms.rst rename to docs/manual/installation/platforms.rst diff --git a/docs/manual/getting_started/installation/prerequisites.rst b/docs/manual/installation/prerequisites.rst similarity index 100% rename from docs/manual/getting_started/installation/prerequisites.rst rename to docs/manual/installation/prerequisites.rst diff --git a/docs/manual/getting_started/installation/test_installation.part.rst b/docs/manual/installation/test_installation.part.rst similarity index 97% rename from docs/manual/getting_started/installation/test_installation.part.rst rename to docs/manual/installation/test_installation.part.rst index 5536849a2e..114dc2b54f 100644 --- a/docs/manual/getting_started/installation/test_installation.part.rst +++ b/docs/manual/installation/test_installation.part.rst @@ -1,52 +1,52 @@ -.. index:: - single: Testing your installation - single: Installation; Testing - single: HelloWorld - -.. _test__install: - -Test your installation -====================== - -To test if your installation and configuration are working correctly, either: - -- Use the |var-project-short| :ref:`dsperf_tool` - The ``ddsperf`` tool sends a continuous stream of data at a variable frequency. This is useful for sanity checks and to bypass other sporadic network issues. -- Use the :ref:`helloworld_test` example. - The **Hello World!** example sends a single message. - -.. include:: dsperf_tool.rst - -.. index:: HelloWorld - -.. _helloworld_test: - -HelloWorld ----------- - -To test your installation, |var-project| includes a simple **HelloWorld!** application -(see also the :ref:`helloworld_bm` example). **HelloWorld!** consists of two executables: - - - ``HelloworldPublisher`` - - ``HelloworldSubscriber`` - -The **HelloWorld!** executables are located in: - -- ``\build\bin\Debug`` on Windows -- ``/build/bin`` on Linux/macOS. - -.. note:: - Requires CMake with ``-DBUILD_EXAMPLES=ON``. - -.. include:: ../helloworld/helloworld_run.part.rst - -.. note:: - There are some common issues with multiple network interface cards on machine - configurations. The default behavior automatically detects the first available - network interface card on your machine for exchanging the ``hello world`` message. - To ensure that your publisher and subscriber applications are on the same network, - you must select the correct interface card. To override the default behavior, - create or edit a deployment file (for example, ``cyclonedds.xml``) and update the - property :ref:`//CycloneDDS/Domain/General/Interfaces/NetworkInterface[@address]` - to point to it through the ``CYCLONEDDS\_URI`` OS environment variable. For further +.. index:: + single: Testing your installation + single: Installation; Testing + single: HelloWorld + +.. _test__install: + +Test your installation +====================== + +To test if your installation and configuration are working correctly, either: + +- Use the |var-project-short| :ref:`dsperf_tool` + The ``ddsperf`` tool sends a continuous stream of data at a variable frequency. This is useful for sanity checks and to bypass other sporadic network issues. +- Use the :ref:`helloworld_test` example. + The **Hello World!** example sends a single message. + +.. include:: dsperf_tool.rst + +.. index:: HelloWorld + +.. _helloworld_test: + +HelloWorld +---------- + +To test your installation, |var-project| includes a simple **HelloWorld!** application +(see also the :ref:`helloworld_bm` example). **HelloWorld!** consists of two executables: + + - ``HelloworldPublisher`` + - ``HelloworldSubscriber`` + +The **HelloWorld!** executables are located in: + +- ``\build\bin\Debug`` on Windows +- ``/build/bin`` on Linux/macOS. + +.. note:: + Requires CMake with ``-DBUILD_EXAMPLES=ON``. + +.. include:: ../helloworld/helloworld_run.part.rst + +.. note:: + There are some common issues with multiple network interface cards on machine + configurations. The default behavior automatically detects the first available + network interface card on your machine for exchanging the ``hello world`` message. + To ensure that your publisher and subscriber applications are on the same network, + you must select the correct interface card. To override the default behavior, + create or edit a deployment file (for example, ``cyclonedds.xml``) and update the + property :ref:`//CycloneDDS/Domain/General/Interfaces/NetworkInterface[@address]` + to point to it through the ``CYCLONEDDS\_URI`` OS environment variable. For further information, refer to :ref:`config-docs` and the :ref:`configuration_reference`. \ No newline at end of file diff --git a/docs/manual/getting_started/installation/uninstallation.rst b/docs/manual/installation/uninstallation.rst similarity index 100% rename from docs/manual/getting_started/installation/uninstallation.rst rename to docs/manual/installation/uninstallation.rst diff --git a/docs/manual/getting_started/installation/windows.environments.rst b/docs/manual/installation/windows.environments.rst similarity index 100% rename from docs/manual/getting_started/installation/windows.environments.rst rename to docs/manual/installation/windows.environments.rst diff --git a/docs/manual/python/ddspython.rst b/docs/manual/python/ddspython.rst new file mode 100644 index 0000000000..c653bb0852 --- /dev/null +++ b/docs/manual/python/ddspython.rst @@ -0,0 +1,34 @@ +.. + Copyright(c) 2006 to 2021 ZettaScale Technology and others + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0 which is available at + http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + v. 1.0 which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +.. include:: ../external-links.part.rst + +.. index:: + single: Python; API reference + single: API; Python reference + +.. _py_api_ref_bm: + +==================== +Python API reference +==================== + +To install Python, refer to :ref:`installing_python`. + +.. toctree:: + :maxdepth: 1 + + py_api_link + py_tutorial + py_idl + py_cltools + + diff --git a/docs/manual/python/intro.rst b/docs/manual/python/intro.rst new file mode 100644 index 0000000000..6694ac7486 --- /dev/null +++ b/docs/manual/python/intro.rst @@ -0,0 +1,133 @@ +.. _intro: + +Introduction +============ + +This is the documentation for |var-project|, wrapping the |var-core-project| C API for easy creation of DDS applications. + +.. _installing: + +Prerequisites +------------- + +|var-project-short| requires Python version 3.7 or higher, with 3.11 support provisional. The wheels on PyPi contain a pre-built binary of the |var-core-project| C library and IDL compiler. These have a couple of caveats. The pre-built package: + + * has no support for DDS Security, + * has no support for shared memory via Iceoryx, + * comes with generic |var-core-project| binaries that are not optimized per-platform. + +If you need these features or cannot use the binaries for other reasons you can install the |var-project| library from source. You will need to set the environment variable ``CYCLONEDDS_HOME`` to allow the installer to locate the |var-core-project| C library if it is on a non-standard path. At runtime we leverage several mechanisms to locate the library that are appropriate for the platform. If you get an exception about non-locatable libraries or wish to manage multiple |var-core-project| installations you can use the environment variable ``CYCLONEDDS_HOME`` to override the load location. + +Installation +------------ + +Simply install with pip from PyPi. + +.. code-block:: shell + + pip install cyclonedds + + +You can install from the github link directly: + +.. code-block:: shell + + CYCLONEDDS_HOME="/path/to/cyclonedds" pip install git+https://github.com/eclipse-cyclonedds/cyclonedds-python + + +If you wish to run the testsuite or build the documentation you will need additional dependencies. These can be installed by means of Python installation optional components: + +.. code-block:: shell + + git clone https://github.com/eclipse-cyclonedds/cyclonedds-python + cd cyclonedds-python + + # Testsuite: + pip install .[dev] + pytest + + # Documentation + pip install .[docs] + cd docs + sphinx-build ./source ./build + python -m http.server --directory build + + +If you get permission errors you are using your system python. This is not recommended, we recommend using `a virtual environment`_, `poetry`_, `pipenv`_ or `pyenv`_. If you *just* want to get going, you can add ``--user`` to your pip command to install for the current user. See the `Installing Python Modules`_ documentation. + +.. _first_app: + +Your first Python DDS application +----------------------------------- + +Let's make our entry into the world of DDS by making our presence known. We will not worry about configuration or what DDS does under the hood but just write a single message. To publish anything to DDS we need to define the type of message first. If you are worried about talking to other applications that are not necessarily running Python you would use the IDL compiler, but for now we will just manually define our message type directly in Python using the ``cyclonedds.idl`` tools: + +.. code-block:: python3 + :linenos: + + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + + @dataclass + class Message(IdlStruct): + text: str + + + name = input("What is your name? ") + message = Message(text=f"{name} has started their first DDS Python application!") + + +With ``cyclonedds.idl`` we write typed classes with the standard library module :external+python:py:mod:`~dataclasses`. For this simple application we just put in a piece of text, but this system has the same expressive power as the OMG IDL specification, allowing you to use almost any complex datastructure you can think of. + +Now to send our message over DDS we need to perform a few steps: + + * Join the DDS network using a DomainParticipant + * Define which datatype and under what name we will publish our message as a Topic + * Make the DataWriter that publishes that Topic + * And finally publish the message. + +.. code-block:: python3 + :linenos: + + from cyclonedds.domain import DomainParticipant + from cyclonedds.topic import Topic + from cyclonedds.pub import DataWriter + + participant = DomainParticipant() + topic = Topic(participant, "Announcements", Message) + writer = DataWriter(participant, topic) + + writer.write(message) + +Hurray, we have published are first message! However, it is hard to tell if that actually did anything, since we don't have anything set up that is listening. Let's make a second script that takes messages from DDS and prints them to the terminal: + +.. code-block:: python3 + :linenos: + + from dataclasses import dataclass + from cyclonedds.domain import DomainParticipant + from cyclonedds.topic import Topic + from cyclonedds.sub import DataReader + from cyclonedds.util import duration + from cyclonedds.idl import IdlStruct + + @dataclass + class Message(IdlStruct): + text: str + + participant = DomainParticipant() + topic = Topic(participant, "Announcements", Message) + reader = DataReader(participant, topic) + + # If we don't receive a single announcement for five minutes we want the script to exit. + for msg in reader.take_iter(timeout=duration(minutes=5)): + print(msg.text) + +Now with this script running in a secondary terminal you should see the message pop up when you run the first script again. + +.. _a virtual environment: https://docs.python.org/3/tutorial/venv.html +.. _poetry: https://python-poetry.org/ +.. _pipenv: https://pipenv.pypa.io/en/latest/ +.. _pyenv: https://github.com/pyenv/pyenv +.. _Installing Python Modules: https://docs.python.org/3/installing/index.html + diff --git a/docs/manual/python/py_api_link.rst b/docs/manual/python/py_api_link.rst new file mode 100644 index 0000000000..bb8328f971 --- /dev/null +++ b/docs/manual/python/py_api_link.rst @@ -0,0 +1,5 @@ +.. include:: ../external-links.part.rst + +================== +|url::py_api_link| +================== \ No newline at end of file diff --git a/docs/manual/python/py_cltools.rst b/docs/manual/python/py_cltools.rst new file mode 100644 index 0000000000..0af8b515d1 --- /dev/null +++ b/docs/manual/python/py_cltools.rst @@ -0,0 +1,101 @@ +.. index:: Python; Command line tool + +.. _py_cltools: + +The ``cyclonedds`` command line tool +==================================== + +Included with the ``cyclonedds`` Python package is the ``cyclonedds`` command line tool. + +The command line tool provides a quick insight into what your DDS dataspace currently looks like. It allows you to verify that the public view of your applications matches what you had intended. + +The following is a list of the ``cyclonedds`` subcommands: + +* ``cyclonedds --help``: Shows the help for the ``cyclonedds`` subcommands. +* ``cyclonedds ls``: Shows the entities and their QoS settings in your DDS system. +* ``cyclonedds ps``: Lists the applications in your DDS system. +* ``cyclonedds typeof``: Shows the type(s) of a topic in your system. +* ``cyclonedds subscribe``: Dynamically subscribes to a topic and displays the data as it arrives. +* ``cyclonedds publish``: Dynamically builds a REPL with datatypes and a writer for a topic and displays the data as it arrives. +* ``cyclonedds performance``: A front-end to ``ddsperf`` with four modes: ``publish``, ``subscribe``, ``ping`` and ``pong``. + + The help screen shows the available commands: + +.. image:: ../_static/python_images/cyclonedds-help.svg + :alt: ``cyclonedds --help`` + +``cyclonedds ls`` +----------------- + +The ``ls`` subcommand shows the entities and their QoS settings in your DDS system. + +.. image:: ../_static/python_images/cyclonedds-ls-help.svg + :alt: ``cyclonedds ls --help`` + +The following screen shows the output from ``cyclonedds ls``, while running the Python ``Vehicle`` example in the background: + +.. image:: ../_static/python_images/cyclonedds-ls-demo.svg + :alt: ``cyclonedds ls --suppress-progress-bar --force-color-mode`` + +``cyclonedds ps`` +----------------- + +The ``ps`` subcommand lists the applications in your DDS system. Note: This depends on 'Participant Properties', which are known as "QoS properties" for DDS participants (merged into CycloneDDS version 0.10.0). + +.. image:: ../_static/python_images/cyclonedds-ps-help.svg + :alt: ``cyclonedds ps --help`` + +The following screen shows the output from ``cyclonedds ps``, while running the Python ``Vehicle`` example in the background: + +.. image:: ../_static/python_images/cyclonedds-ps-demo.svg + :alt: ``cyclonedds ps --suppress-progress-bar --force-color-mode`` + +``cyclonedds typeof`` +--------------------- + +The ``typeof`` subcommand shows the type(s) of a topic in your system. + +For XTypes, it is possible to have more than one type for each topic that exists, while maintaining compatability. The types are represented in IDL. For information on the XTypes specification, refer to: :ref:`https://www.omg.org/spec/DDS-XTypes/`_. + +.. image:: ../_static/python_images/cyclonedds-typeof-help.svg + :alt: ``cyclonedds typeof --help`` + +The following example screen shows the output from the ``Vehicle`` example: + +.. image:: ../_static/python_images/cyclonedds-typeof-demo.svg + :alt: ``cyclonedds typeof Vehicle --suppress-progress-bar --force-color-mode`` + + +``cyclonedds subscribe`` +------------------------ + +The ``subscribe`` subcommand dynamically subscribes to a topic and displays the data as it arrives. The type is discovered in a similar manner as ``typeof``. + +.. image:: ../_static/python_images/cyclonedds-subscribe-help.svg + :alt: ``cyclonedds subscribe --help`` + +The following example screen shows the output from the ``Vehicle`` example: + +.. image:: ../_static/python_images/cyclonedds-subscribe-demo.svg + :alt: ``timeout -s INT 10s cyclonedds subscribe Vehicle --suppress-progress-bar --force-color-mode`` + +``cyclonedds publish`` +------------------------ + +The ``publish`` subcommand dynamically builds a REPL with datatypes and a writer for a topic and displays the data as it arrives. The type is discovered in a similar manner as ``typeof``. + +.. image:: ../_static/python_images/cyclonedds-publish-help.svg + :alt: ``cyclonedds publish --help`` + +``cyclonedds performance`` +-------------------------- + +The ``performance`` subcommand is a front-end to ``ddsperf`` with four modes: ``publish``, ``subscribe``, ``ping`` and ``pong``. + +.. image:: ../_static/python_images/cyclonedds-performance-help.svg + :alt: ``cyclonedds performance --help`` + +The following example screen shows a performance-run in the ``cyclonedds performance subscribe`` mode, rendered with ``cyclonedds performance publish`` running in the background. + +.. image:: ../_static/python_images/cyclonedds-performance-subscribe-demo.svg + :alt: ``cyclonedds performance --duration 21s --render-output-once-on-exit --force-color-mode subscribe --triggering-mode waitset`` \ No newline at end of file diff --git a/docs/manual/python/py_idl.rst b/docs/manual/python/py_idl.rst new file mode 100644 index 0000000000..e6ebdd459c --- /dev/null +++ b/docs/manual/python/py_idl.rst @@ -0,0 +1,362 @@ +.. include:: ../external-links.part.rst + +.. index:: IDL; Python + +.. _py_idl: + +========== +Python IDL +========== + +There is no official OMG specification for mapping IDL to Python. The solutions +here are therefore not standardized and are not compatible with other DDS +implementations. However, they are based purely on the standard library +type-hinting functionality as introduced in Python 3.5, so that any Python tooling +that works with type-hints is also compatible with our implementation. + +To generate initializers and string representations use the :py:mod:`dataclasses` +standard library module. This is applied outside of the other IDL machinery, +therefore you can control immutability, equality checking, or even use a different +``dataclasses`` representation, for example |url::runtype_link|. + +Working with the IDL compiler +----------------------------- + +If you already have an IDL file that defines your types, or if you require +interoperability with non-Python projects. The ``idlpy`` library is built as part of +the python package. + +After installing the CycloneDDS Python backend you can run ``idlc`` with the ``-l py`` +flag to generate Python code: + +.. code-block:: shell + + idlc -l py your_file.idl + +To nest the resulting Python module inside an existing package, you can specify the +path from the intended root. If you have a package 'wubble' with a submodule 'fruzzy' +and want the generated modules and types under there you can pass ``py-root-prefix``: + +.. code-block:: shell + + idlc -l py -p py-root-prefix=wubble.fruzzy your_file.idl + +IDL Datatypes in Python +----------------------- + +The ``cyclonedds.idl`` package implements the IDL unions, structs, and their +OMG XCDR-V1 encoding, in python. In most cases, the IDL compiler writes the code that +references this package without the need to edit the objects. However, for python-only +projects it is possible to write the objects manually (where cross-language +interactions are not required). To manually write IDL objects, you can make your +classes inherit from the following classes: + +- :class:`IdlStruct` +- :class:`IdlStruct` +- :class:`IdlStruct` +- :class:`IdlStruct` + +The following is a basic example of how to use dataclasses (For further information +refer to the standard library documentation of :mod:`dataclasses`): + +.. code-block:: python + :linenos: + + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + + @dataclass + class Point2D(IdlStruct): + x: int + y: int + + p1 = Point2D(20, -12) + p2 = Point2D(x=12, y=-20) + p1.x += 5 + +The :func:`dataclass` decorator turns a class with just +names and types into a dataclass. The :class:`IdlStruct` +parent class makes use of the type information defined in the dataclass to +:ref:`(de)serialize messages`. All normal dataclasses functionality is +preserved, therefore to define default factories use :func:`field` +from the dataclasses module, or add a `__post_init__` method for more complicated +construction scenarios. + +Types +----- + +Not all Python types are encodable with OMG XCDR-V1. Therefore, there are limitations +to what you can put in an :class:`IdlStruct` class. The +following is an exhaustive list of types: + +Integers +^^^^^^^^ + +The default Python :class:`int` type maps to an OMG XCDR-V1 64-bit integer. +The :mod:`types` module has all the other integers types that +are supported in python. + +.. code-block:: python + :linenos: + + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + from cyclonedds.idl.types import int8, uint8, int16, uint16, int32, uint32, int64, uint64 + + @dataclass + class SmallPoint2D(IdlStruct): + x: int8 + y: int8 + +.. note:: + These special types are just normal :class:`int`s at runtime. They are + only used to indicate the serialization functionality what type to use on the + network. If you store a number that is not supported by that integer type you will + get an error during encoding. The ``int128`` and ``uint128`` are not supported. + +Floats +^^^^^^ + +The Python :class:`float` type maps to a 64-bit float, which is a +`double` in C-style languages. The :mod:`types` module has a +``float32`` and ``float64`` type, ``float128`` is not supported. + +Strings +^^^^^^^ + +The Python :class:`str` type maps directly to the XCDR string. It is +encoded with utf-8. Inside :mod:`types` there is the +:class:`bounded_str` type for a string with maximum +length. + + +.. code-block:: python + :linenos: + + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + from cyclonedds.idl.types import bounded_str + + @dataclass + class Textual(IdlStruct): + x: str + y: bounded_str[20] + + +Lists +^^^^^ + +The Python :func:`list` is a versatile type. In normal python, a list +is able to contain other types, but to be able to encode it, all of the contents +must be the same type, and this type must be known beforehand. This can be achieved +by using the :class:`sequence` type. + +.. code-block:: python + :linenos: + + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + from cyclonedds.idl.types import sequence + + @dataclass + class Names(IdlStruct): + names: sequence[str] + + n = Names(names=["foo", "bar", "baz"]) + + +In XCDR, this results in an 'unbounded sequence', which in most cases should be +acceptable. However, use annotations to change to either: + +- A 'bounded sequence'. For example, to limit the maximum allowed number of items. +- An 'array'. For example, if the length of the list is always the same. + +.. code-block:: python + :linenos: + + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + from cyclonedds.idl.types import sequence, array + + @dataclass + class Numbers(IdlStruct): + ThreeNumbers: array[int, 3] + MaxFourNumbers: sequence[int, 4] + + +Dictionaries +^^^^^^^^^^^^ + +.. Note:: + Currently, dictionaries are not supported by the IDL compiler. However, if your + project is pure python there is no problem in using them. + +Unlike the built-in Python :class:`dict` both the key and the value must +have a constant type. To define a dictionary, use the :class:`Dict` +from the :mod:`typing` module. + +.. code-block:: python + :linenos: + + from typing import Dict + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + + @dataclasses + class ColourMap(IdlStruct): + mapping: Dict[str, str] + + c = ColourMap({"red": "#ff0000", "blue": "#0000ff"}) + + +Unions +^^^^^^ + +Unions in IDL are different to the unions defined in the :mod:`typing` +module. IDL unions are *discriminated*, which means that they have a value that +indicates which of the possibilities is active. + +To write discriminated unions, use the following: + +- :func:`@union` decorator +- :func:`case` helper type. +- :func:`default` helper type. + +Write the class in a dataclass style, except only one of the values can be active +at a time. The :func:`@union` decorator takes one type +as argument, which determines the type of what is differentiating the cases. + +.. code-block:: python + :linenos: + + from enum import Enum, auto + from dataclasses import dataclass + from cyclonedds.idl import IdlUnion, IdlStruct + from cyclonedds.idl.types import uint8, union, case, default, MaxLen + + + class Direction(Enum): + North = auto() + East = auto() + South = auto() + West = auto() + + + class WalkInstruction(IdlUnion, discriminator=Direction): + steps_n: case[Direction.North, int] + steps_e: case[Direction.East, int] + steps_s: case[Direction.South, int] + steps_w: case[Direction.West, int] + jumps: default[int] + + @dataclass + class TreasureMap(IdlStruct): + description: str + steps: sequence[WalkInstruction, 20] + + + map = TreasureMap( + description="Find my Coins, Diamonds and other Riches!\nSigned\nCaptain Corsaro", + steps=[ + WalkInstruction(steps_n=5), + WalkInstruction(steps_e=3), + WalkInstruction(jumps=1), + WalkInstruction(steps_s=9) + ] + ) + + print (map.steps[0].discriminator) # You can always access the discriminator, which in this case would print 'Direction.North' + + +Objects +^^^^^^^ + +To reference other classes as member a type, use +:class:`IdlStruct` or +:class:`IdlUnion` classes that only contain serializable members. + +.. code-block:: python + :linenos: + + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + from cyclonedds.idl.types import sequence + + @dataclass + class Point2D(IdlStruct): + x: int + y: int + + @dataclass + class Cloud(IdlStruct): + points: sequence[Point] + +.. _Serialization: + +Serialization +^^^^^^^^^^^^^ + +Serialization and deserialization automatically occur within the backend. For debug +purposes, or outside a DDS context it can be useful to look at the serialized data, +or create Python objects from raw bytes. By inheriting from +:class:`IdlStruct` or +:class:`IdlUnion`, the defined classes automatically gain +``instance.serialize() -> bytes`` and ``cls.deserialize(data: bytes) -> cls`` functions. + +- Serialize is a member function that returns :class:`bytes` with the + serialized object. +- Deserialize is a :func:`classmethod` that takes the + :class:`bytes` and returns the resultant object. + + To inspect the member types, use the built-in Python ``cls.__annotations__``, and + for for idl information, use the ``cls.__idl_annotations__`` and + ``cls.__idl_field_annotations__``. + +.. code-block:: python + :linenos: + + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + + @dataclass + class Point2D(IdlStruct): + x: int + y: int + + p = Point2D(10, 10) + data = p.serialize() + q = Point2D.deserialize(data) + + assert p == q + + +Idl Annotations +^^^^^^^^^^^^^^^ + +In IDL you can annotate structs and members with several different annotations, for +example ``@key``. In Python we have decorators, but they only apply to classes not to +fields. This is the reason why the syntax in Python for a class or field annotation +differ slightly. Note: The IDL ``#pragma keylist`` is a class annotation in python, +but functions in exactly the same way. + +.. code-block:: python + :linenos: + + from dataclasses import dataclass + from cyclonedds.idl import IdlStruct + from cyclonedds.idl.annotations import key, keylist + + @dataclass + class Type1(IdlStruct): + id: int + key(id) + value: str + + @dataclass + @keylist(["id"]) + class Type2(IdlStruct): + id: int + value: str + + +.. _runtype: https://pypi.org/project/runtype/ \ No newline at end of file diff --git a/docs/manual/getting_started/py_tutorial/index.rst b/docs/manual/python/py_tutorial.rst similarity index 63% rename from docs/manual/getting_started/py_tutorial/index.rst rename to docs/manual/python/py_tutorial.rst index 4ac2490aa9..2850b59e3e 100644 --- a/docs/manual/getting_started/py_tutorial/index.rst +++ b/docs/manual/python/py_tutorial.rst @@ -1,9 +1,19 @@ +.. index:: Python: Tutorial + +.. _py_tutorial: + ############### Python Tutorial ############### -Let's enter the world of DDS by making our presence known. We will not worry about configuration or what DDS does under the hood but write a single message. -To publish anything to DDS we need to define the type of message first. Suppose you are worried about talking to other applications that are not necessarily running Python. In that case, you will use the IDL compiler, but for now, we will manually define our message type directly in Python using the ``cyclonedds.idl`` tools: +This tutorial describes how to write a single message. To publish anything to DDS it +is necessary to first define the type of message. + +.. note:: + In order to talk to other applications that are not necessarily running Python, + use the IDL compiler. + +To manually define a message type in Python using the ``cyclonedds.idl`` tools: .. code-block:: python3 :linenos: @@ -19,13 +29,15 @@ To publish anything to DDS we need to define the type of message first. Suppose name = input("What is your name? ") message = Message(text=f"{name} has started his first DDS Python application!") - -With ``cyclonedds.idl`` write typed classes with the standard library module `dataclasses `. For this simple application, the data being transmitted only contains a piece of text, but this system has the same expressive power as the OMG IDL specification, allowing you to use almost any complex datastructure. +With ``cyclonedds.idl`` write typed classes with the standard library module +`dataclasses `. For this simple application, the data being +transmitted only contains a piece of text, but this system has the same expressive +power as the OMG IDL specification, allowing you to use almost any complex datastructure. To send your message over a DDS domain, carry out the following steps: 1. Join the DDS network using a DomainParticipant -2. Define which data type and under what name you will publish your message as a Topic +2. Define which data type and under what name you will publish your message as a topic 3. Create the ``DataWriter`` that publishes that Topic 4. And finally, publish the message. @@ -42,7 +54,10 @@ To send your message over a DDS domain, carry out the following steps: writer.write(message) -You have now published your first message successfully! However, it is hard to tell if that did anything since we don't have anything set up to listen for incoming messages. Let's make a second script that takes messages from DDS and prints them to the terminal: +You have now published your first message successfully! However, it is hard to tell +if that did anything since we don't have anything set up to listen for incoming +messages. Let's make a second script that takes messages from DDS and prints them +to the terminal: .. code-block:: python3 :linenos: @@ -66,4 +81,5 @@ You have now published your first message successfully! However, it is hard to t for msg in reader.take_iter(timeout=duration(minutes=5)): print(msg.text) -Now with this script running in a second terminal, you should see the message pop up when you rerun the first script. +Now with this script running in a second terminal, you should see the message pop up +when you rerun the first script. diff --git a/docs/manual/python/tools.ddsls.rst b/docs/manual/python/tools.ddsls.rst new file mode 100644 index 0000000000..d6bf4da66e --- /dev/null +++ b/docs/manual/python/tools.ddsls.rst @@ -0,0 +1,318 @@ +.. index:: Python; DDSLS tool + +.. _py_ddsls_tool: + +Command line tool: ddsls +======================== + +Introduction +------------ + +When using DDS, it's sometimes useful to know what DDS entities are running in the system. The ddsls is a tool that subscribes to the Built-in topics, and shows the information of the domain participants, data readers and data writers in the system. + + +Usage +----- + +To run the **ddsls**, you can use: + +.. code-block:: console + + $ ddsls [Options] + +You can view what options you have with the **ddsls** by using the command: + +.. code-block:: console + + $ ddsls --help + +And the help message is as follows: + +.. code-block:: console + + usage: ddsls [-h] [-i ID] [-f FILENAME] [-j] [-w] [-v] [-r RUNTIME] (-a | -t {dcpsparticipant,dcpssubscription,dcpspublication}) + + optional arguments: + -h, --help show this help message and exit + -i ID, --id ID Define the domain participant id + -f FILENAME, --filename FILENAME + Write results to file in JSON format + -j, --json Print output in JSON format + -w, --watch Watch for data reader & writer & qoses changes + -v, --verbose View the sample when Qos changes + -r RUNTIME, --runtime RUNTIME + Limit the runtime of the tool, in seconds. + -a, --all for all topics + -t {dcpsparticipant,dcpssubscription,dcpspublication}, --topic {dcpsparticipant,dcpssubscription,dcpspublication} + for one specific topic + +There are several options you can choose to use the **ddsls** according to your needs, which will be further explained in the following sections. + +For checking the DDS entity information, you can use the ``--topic`` or ``--all`` option to specify which entity's information you want to see, the ``--id`` option to define which domain you like to check using the id of the domain participant, the ``--watch`` option to monitor the changes in the system as entities being created and disposed. + +For viewing options, you can use the ``--json`` option to view the output data in JSON format, the ``--verbose`` option to view the full sample information when the entity's QoS changes. + +For additional options, you can use the ``--filename`` option to define the name of file you want to output the result to, the ``--runtime`` option to specify how long the **ddsls** will run. + + +Topic +^^^^^ + +To use the **ddsls**, you need to specify the topic you're subscribing to using the ``--topic`` or ``--all`` option. + +For ``--topic`` option, you can choose from ``dcpsparticipant``, ``dcpssubscription`` and ``dcpspublication``. + +The ``dcpsparticipant``, ``dcpssubscription`` and ``dcpspublication`` subscribes to the **BuiltinTopicDcpsParticipant**, **BuiltinTopicSubscription** and **BuiltinTopicDcpsPublication** topic respectively, and will show the information of all the participants, subscribers and publishers in the domain respectively. + +Here's an example of running **ddsls** with the ``dcpsparticipant`` topic, run the command: + +.. code-block:: console + + $ ddsls --all + +If there are DDS participant, data reader and data writer running in the default domain, it will show up in the **ddsls** like this: + +.. code-block:: console + + -- New PARTICIPANT -- + key: 9ce21001-ad00-8ac9-4428-52f1000001c1 + qos: Qos() + + key: 350c1001-c5e3-ca6b-712a-ee09000001c1 + qos: Qos() + + + -- New PUBLICATION -- + key: 9ce21001-ad00-8ac9-4428-52f100000102 + participant_key: 9ce21001-ad00-8ac9-4428-52f1000001c1 + participant_instance_handle: 11822753457071331301 + topic_name: Vehicle + type_name: vehicles::Vehicle + qos: Qos(Policy.Deadline(deadline=10000), Policy.DestinationOrder.ByReceptionTimestamp, Policy.Durability.Transient, Policy.DurabilityService(cleanup_delay=0, history=Policy.History.KeepLast(depth=1), max_samples=-1, max_instances=-1, max_samples_per_instance=-1), Policy.History.KeepLast(depth=10), Policy.IgnoreLocal.Nothing, Policy.LatencyBudget(budget=0), Policy.Lifespan(lifespan=9223372036854775807), Policy.Liveliness.Automatic(lease_duration=9223372036854775807), Policy.Ownership.Shared, Policy.OwnershipStrength(strength=0), Policy.PresentationAccessScope.Instance(coherent_access=False, ordered_access=False), Policy.Reliability.BestEffort, Policy.ResourceLimits(max_samples=-1, max_instances=-1, max_samples_per_instance=-1), Policy.TransportPriority(priority=0), Policy.WriterDataLifecycle(autodispose=True)) + + + -- New SUBSCRIPTION -- + key: 350c1001-c5e3-ca6b-712a-ee0900000107 + participant_key: 350c1001-c5e3-ca6b-712a-ee09000001c1 + participant_instance_handle: 5513147631977453825 + topic_name: Vehicle + type_name: vehicles::Vehicle + qos: Qos(Policy.Deadline(deadline=10000), Policy.DestinationOrder.ByReceptionTimestamp, Policy.Durability.Transient, Policy.History.KeepLast(depth=10), Policy.IgnoreLocal.Nothing, Policy.LatencyBudget(budget=0), Policy.Liveliness.Automatic(lease_duration=9223372036854775807), Policy.Ownership.Shared, Policy.PresentationAccessScope.Instance(coherent_access=False, ordered_access=False), Policy.ReaderDataLifecycle(autopurge_nowriter_samples_delay=9223372036854775807, autopurge_disposed_samples_delay=9223372036854775807), Policy.Reliability.BestEffort, Policy.ResourceLimits(max_samples=-1, max_instances=-1, max_samples_per_instance=-1), Policy.TimeBasedFilter(filter_time=0), Policy.TransportPriority(priority=0)) + + +Comprehend output +""""""""""""""""" + +* The result above shows that there is two participant, one data reader and one data writer running in the default domain; + +* **New** in "New PARTICIPANT", "New SUBSCRIPTION", "New PUBLICATION" indicates that the entities are alive. If the entities are no longer alive, the message will be **Disposed** instead, such as "Disposed PARTICIPANT". + +* And the fields for the entities are: + + * **PARTICIPANT**: + + * **key**: The GUID (Globally Unique Identifier) of the domain participant. + + * **SUBSCRIPTION** and **PUBLICATION**: + + * **key**: The GUID of the data reader or data writer; + * **participant_key**: The GUID of the domain participant that created the data reader or data writer; + * **participant_instance_handle**: The instance handle of the domain participant; + * **topic_name**: The name of the topic that the data reader / data writer is subscribing / writing to; + * **type_name**: The type name used in the topic of the data reader / data writer; + * **qos**: The QoS (Quality of Service) of the data reader / data writer. + +Domain participant id +^^^^^^^^^^^^^^^^^^^^^ + +By default, the **ddsls** subscribes to the default domain (domain 0) and displays information of entities in that domain. However, if you want to view the entity information in another domain, you can use the option ``-- id`` to change the domain to which the **ddsls** subscribes. + +The ``--id`` option will set the id of the **ddsls** domain participant, allowing the **ddsls** to view entities in the domain you chooses. + +For example, if you run a small script using domain 1 as the domain participant: + +.. code-block:: python + :linenos: + + from cyclonedds.domain import DomainParticipant + + dp = DomainParticipant(1) + +If you run ``ddsls --topic dcpsparticipant``, the participant you've just created will not be there, since it's only viewing entities in the default domain. + +To view this participant information, you need to use: + +.. code-block:: console + + $ ddsls --topic dcpsparticipant --id 1 + +And the result of the participant in domain 1 will be: + +.. code-block:: console + + -- New PARTICIPANT -- + key: 02371001-8251-a889-325a-cad5000001c1 + qos: Qos() + + +Watch mode +^^^^^^^^^^ +By default, the **ddsls** will run for 1 second and then automatically exit. However, if you want to monitor the entities in the system, you can use the ``--watch`` option to enable the watch mode. + +In watch mode, the **ddsls** will not automatically exit (if the ``--runtime`` option is not selected). The watch mode monitors entities and displays entity information as they are created and disposed, or as their QoS changes. + + +For example, if you have the **ddsls** monitoring the ``dcpsparticipant`` topic, using the command: + +.. code-block:: console + + $ ddsls --topic dcpsparticipant --watch + +Then start and exit a script that creates a domain participant entity in the default domain, you can get a result like this: + +.. code-block:: console + + -- New PARTICIPANT -- + key: 713b1001-bb82-49db-9f2a-46f4000001c1 + qos: Qos() + + + -- Disposed PARTICIPANT -- + key: 713b1001-68a5-e15c-2709-d195000001c1 + qos: Qos() + +* **New** indicates that the participant is alive in the domain; +* **Disposed** indicates that the participant has already been disposed. + +Verbose mode +^^^^^^^^^^^^ + +Verbose mode is an optional mode for the **ddsls**. By default, the **ddsls** will only display information of the specific QoS policies that has been changed. But you can use the ``--verbose`` option to enable to verbose mode, to not only view the specific information, but also the complete information of the entity that has QoS changed. + +By default, when the QoS changes in an entity, the **ddsls** will display which policy has been changed, on which topic and which entity, and the old and new value for the policy. + +For example, when QoS changes in a data writer, you can get a result like this: + +.. code-block:: console + + Qos changed on topic 'MessageTopic' publication: + key = 1d681001-c040-7b68-2e4d-5fb900000102 + Policy.OwnershipStrength(strength=10) -> Policy.OwnershipStrength(strength=20) + Policy.Userdata(data=b'Old') -> Policy.Userdata(data=b'New') + +In this example: + +* The QoS changed happened in the **publication**, which means it's a data writer or a publisher, writing to the topic named "MessageTopic"; +* The **key** is the GUID of the entity that has QoS changed; +* The changed QoS **policy** are OwnershipStrength" and "Userdata", "OwnershipStrength" changed from 10 to 20 and "Userdata" changed from "Old" to "New". + +When verbose mode is activated, using the command: + +.. code-block:: console + + $ ddsls --all --watch --verbose + +The **ddsls** will not only display the specific QoS change information, but also display the entity information on which the QoS changes occurs. + +.. code-block:: console + + Qos changed on topic 'MessageTopic' publication: + key = e4921001-4edb-926f-14be-adb500000102 + Policy.OwnershipStrength(strength=10) -> Policy.OwnershipStrength(strength=20) + Policy.Userdata(data=b'Old') -> Policy.Userdata(data=b'New') + + -- New PUBLICATION -- + key: e4921001-4edb-926f-14be-adb500000102 + participant_key: e4921001-4edb-926f-14be-adb5000001c1 + participant_instance_handle: 2236347693610277994 + topic_name: MessageTopic + type_name: testtopics::message::Message + qos: Qos(Policy.Deadline(deadline=9223372036854775807), Policy.DestinationOrder.ByReceptionTimestamp, Policy.Durability.Volatile, Policy.DurabilityService(cleanup_delay=0, history=Policy.History.KeepLast(depth=1), max_samples=-1, max_instances=-1, max_samples_per_instance=-1), Policy.History.KeepLast(depth=1), Policy.IgnoreLocal.Nothing, Policy.LatencyBudget(budget=0), Policy.Lifespan(lifespan=9223372036854775807), Policy.Liveliness.Automatic(lease_duration=9223372036854775807), Policy.Ownership.Shared, Policy.OwnershipStrength(strength=20), Policy.PresentationAccessScope.Instance(coherent_access=False, ordered_access=False), Policy.Reliability.Reliable(max_blocking_time=100000000), Policy.ResourceLimits(max_samples=-1, max_instances=-1, max_samples_per_instance=-1), Policy.TransportPriority(priority=0), Policy.Userdata(data=b'New'), Policy.WriterDataLifecycle(autodispose=True)) + +In this verbose mode example: + +* The **key** in "New PUBLICATION" is the same as the one in the specific QoS change information, indicating that this is the entity that had QoS changed; +* The value of the policies "OwnershipStrength" and "Userdata" has been changed to the new values. + +JSON mode +^^^^^^^^^ + +For better viewing the entity information, you can use the ``--json`` option to view the results in JSON format. + +For example, start up the **ddsls** in JSON mode using the command: + +.. code-block:: console + + $ ddsls --topic participant --json + +And you can get a result in JSON format like this: + +.. code-block:: JSON + + [ + { + "type": "PARTICIPANT", + "event": "new", + "value": [ + { + "key": "5dc81001-75dc-1fe3-5468-48b3000001c1" + }, + { + "key": "764e1001-d9da-53dd-ca0b-ab06000001c1" + } + ] + }] + +In JSON mode, the output result is divided into 3 parts: + +* **type** is the type of entity, "PARTICIPANT" or "SUBSCRIPTION" or "PUBLICATION"; +* **event** indicates whether the entity is alive or disposed, using "new" or "disposed"; +* **value** is the properties of the entity, such as the GUID of the entity. + +Write to file +^^^^^^^^^^^^^ +Other than printing the results in the terminal, you can also choose to write the results to a file using the ``--filename`` option, providing the name of the file you want to write to. The results will be written to the file in JSON format. + +For example, you can choose to write the result to a file named "test.json" using the command: + +.. code-block:: console + + $ ddsls --topic participant --watch --filename ddsls_data.json + +After stopping the **ddsls**, the results will be written to the test.json file in your current directory. And the ddsls_data.json file will look like this: + +.. code-block:: JSON + + { + "PARTICIPANT": { + "New": { + "da531001-77b3-aef6-0cb8-647f000001c1": { + "key": "da531001-77b3-aef6-0cb8-647f000001c1" + } + }, + "Disposed": { + "8e281001-e010-0c8d-305c-20a3000001c1": { + "key": "8e281001-e010-0c8d-305c-20a3000001c1" + } + } + } + } + +In the output file: + +* **"PARTICIPANT"** is the type of the entity; +* **"New"** or **"Disposed"** indicates whether the entity is alive or disposed at the time **ddsls** stopped running; +* The **GUID** of the entity will group the entity information, such as the **"key"**, **"qos"**, in a JSON dictionary. + +Runtime +^^^^^^^ + +Besides using the **ddsls** by default, which will only run for 1 seconds, and using the **ddsls** in watch mode, which will run indefinitely until there is an interrupt, you can use the ``--runtime`` option to customize the running time according to your needs. + +For example, if you want to run the **ddsls** for 10 seconds, you can use the command: + +.. code-block:: console + + $ ddsls --all --runtime 10 + +And the tool will automatically shut down after running for 10 seconds. This ``--runtime`` option can also apply to watch mode. \ No newline at end of file diff --git a/docs/manual/python/tools.pubsub.rst b/docs/manual/python/tools.pubsub.rst new file mode 100644 index 0000000000..0ee42093ca --- /dev/null +++ b/docs/manual/python/tools.pubsub.rst @@ -0,0 +1,290 @@ +.. index:: Python: Pubsub tool + +.. _py_pubsub_tool: + +Command line tool: pubsub +========================= + +Introduction +------------ + +When using DDS, it's sometimes useful to do some manual testing, publishing and subscribing to specific topics. Pubsub is the tool for that. + +For now, the **pubsub** can be used to read/write to a user-defined topic with customized QoS, and you can do the read/write by simply typing what to publish. + +In the future, with the support of XTypes, the **pubsub** will also be able to read/write to arbitrary topic that exists in the system. This way, you will be able to use the **pubsub** to read/write to any topics in the system. + +Usage +----- + +To use the **pubsub**, you can use: + +.. code-block:: console + + $ pubsub [Options] + +You can view what options you have with the **pubsub** by using the command: + +.. code-block:: console + + $ pubsub --help + +And the help message is as follows: + +.. code-block:: console + + usage: pubsub [-h] [-T TOPIC] [-f FILENAME] [-eqos {all,topic,publisher,subscriber,datawriter,datareader}] [-q QOS [QOS ...]] [-r RUNTIME] [--qoshelp] + + optional arguments: + -h, --help show this help message and exit + -T TOPIC, --topic TOPIC + The name of the topic to publish/subscribe to + -f FILENAME, --filename FILENAME + Write results to file in JSON format + -eqos {all,topic,publisher,subscriber,datawriter,datareader}, --entityqos {all,topic,publisher,subscriber,datawriter,datareader} + Select the entites to set the qos. + Choose between all entities, topic, publisher, subscriber, datawriter and datareader. (default: all). + Inapplicable qos will be ignored. + -q QOS [QOS ...], --qos QOS [QOS ...] + Set QoS for entities, check '--qoshelp' for available QoS and usage + -r RUNTIME, --runtime RUNTIME + Limit the runtime of the tool, in seconds. + --qoshelp e.g.: + --qos Durability.TransientLocal + --qos History.KeepLast 10 + --qos ReaderDataLifecycle 10, 20 + --qos Partition [a, b, 123] + --qos PresentationAccessScope.Instance False, True + --qos DurabilityService 1000, History.KeepLast 10, 100, 10, 10 + --qos Durability.TransientLocal History.KeepLast 10 + + Available QoS and usage are: + --qos Reliability.BestEffort + --qos Reliability.Reliable [max_blocking_time] + --qos Durability.Volatile + --qos Durability.TransientLocal + --qos Durability.Transient + --qos Durability.Persistent + --qos History.KeepAll + --qos History.KeepLast [depth] + --qos ResourceLimits [max_samples], [max_instances], [max_samples_per_instance] + --qos PresentationAccessScope.Instance [coherent_access], [ordered_access] + --qos PresentationAccessScope.Topic [coherent_access], [ordered_access] + --qos PresentationAccessScope.Group [coherent_access], [ordered_access] + --qos Lifespan [lifespan] + --qos Deadline [deadline] + --qos LatencyBudget [budget] + --qos Ownership.Shared + --qos Ownership.Exclusive + --qos OwnershipStrength [strength] + --qos Liveliness.Automatic [lease_duration] + --qos Liveliness.ManualByParticipant [lease_duration] + --qos Liveliness.ManualByTopic [lease_duration] + --qos TimeBasedFilter [filter_time] + --qos Partition [partitions] + --qos TransportPriority [priority] + --qos DestinationOrder.ByReceptionTimestamp + --qos DestinationOrder.BySourceTimestamp + --qos WriterDataLifecycle [autodispose] + --qos ReaderDataLifecycle [autopurge_nowriter_samples_delay], [autopurge_disposed_samples_delay] + --qos DurabilityService [cleanup_delay], [History.KeepAll / History.KeepLast [depth]], [max_samples], [max_instances], [max_samples_per_instance] + --qos IgnoreLocal.Nothing + --qos IgnoreLocal.Participant + --qos IgnoreLocal.Process + --qos Userdata [data] + --qos Groupdata [data] + --qos Topicdata [data] + +There are several options to configure the **pubsub**, the options will be further explained in the following sections. + +For publishing and subscribing data, you can use the ``--topic`` option to define the topic to publish/subscribe to. + +You can also modify QoS using the ``--qos`` option, and use the ``--entityqos`` option if you want to modify the QoS for a particular entity. If you need help setting up the QoS, the ``--qoshelp`` option will show you some examples and the policies you can choose from. + +For additional options, you can use the ``--filename`` option to define the name of file you want to output the result to, the ``--runtime`` option to specify how long the **pubsub** will run. + +Topic +^^^^^ + +To startup the pubsub tool, you need to use the ``--topic`` option to specify the topic you want to read/write to. + +For example, if you want the **pubsub** to read/write to the topic "HelloWord", you can use the command: + +.. code-block:: console + + $ pubsub --topic HelloWorld + + +Read/write data +""""""""""""""" + +After starting up the **pubsub** with a specif topic, you can read/write data by simply publishing your data in the terminal. + +For now, the supported data types for read/write are integer, string, integer and string array, integer and string sequence. + +For example, writing "420", "test", "[1, 8, 3]", "['h', 'e', 'l', 'l', 'o']", "[20]", "['test']" to the terminal respectively, you can see the subscribed message with their datatype printing in the terminal. + +.. code-block:: console + + 420 + Subscribed: Integer(seq=0, keyval=420) + test + Subscribed: String(seq=1, keyval='test') + [1, 8, 3] + Subscribed: IntArray(seq=2, keyval=[1, 8, 3]) + ['h','e','l','l','o'] + Subscribed: StrArray(seq=3, keyval=['h', 'e', 'l', 'l', 'o']) + [20] + Subscribed: IntSequence(seq=4, keyval=[20]) + ['test'] + Subscribed: StrSequence(seq=5, keyval=['test']) + +In the output result: + +* **Subscribed** indicates that the **pubsub** tool has subscribed to data in the topic you defined; +* The **Integer**, **String**, etc., is the datatype of the subscribed data. +* **seq** is the sequence number for the **pubsub** subscribed data; +* **keyval** is the data published. + +QoS +^^^ + +By default, the **pubsub** uses the default QoS for DDS, but you can use the ``--qos`` option to change the QoS according to your needs. + +For example, if you want to set the Reliability QoS to best effort, you can run the **pubsub** with command: + +.. code-block:: console + + $ pubsub --topic hello --qos Reliability.BestEffort + +You can also change multiple QoS for the **pubsub**. For example, in addition to setting the Reliability QoS, you also want to set the History to keep the last 10 samples, you can use the command: + +.. code-block:: console + + $ pubsub --topic hello --qos Reliability.BestEffort History.KeepLast 10 + +If a policy requires multiple arguments, simply use a space or comma to separate the arguments. For example, you can set the DurabilityService QoS by the command: + +.. code-block:: console + + $ pubsub --topic hello --qos DurabilityService 1000, History.KeepLast 10, 100, 10, 10 + +There are some freedom to type the QoS and the arguments on the command line: + +* The QoS policy is case insensitive, so you can use the command like ``-qos reliAbility.REliable``; +* To separate arguments, you can use space, comma, or colon. For example ``--qos ResourceLimits: 100, -1 100``; +* For writing duration, you can use arguments like "'seconds=10;minutes=2'". For example ``--qos lifespan "seconds=10;days=1"``; +* For boolean, other than "True" and "False", you can also use "1", "on", "yes" to represent "True", and use "0", "off", "no" to represent "False". For example ``--qos WriterDataLifecycle off``. + +Entity QoS +^^^^^^^^^^ + +When setting the QoS in the **pubsub**, it will set the QoS for all the entities by default. However, you can also use the ``--entityqos`` option to set the QoS for a certain entity. You can choose to set the desired QoS on topic, subscriber, publisher, data reader or data writer. + +For example, to set the Durability QoS to TransientLocal on the data writer, use the command: + +.. code-block:: console + + $ pubsub --topic hello --qos Durability.TransientLocal --entityqos datawriter + +.. note:: + The ``--entityqos`` option needs to be used together with the ``--qos`` option. + +Inapplicable QoS for entity +""""""""""""""""""""""""""" + +Some QoS policy has limitation as to which entity it can apply to, such as the Topicdata QoS can only be applied to the topic. + +If you selected a QoS policy that is not applicable to the entity you selected, the QoS will be ignored and use the default QoS policy value for the entity. + +For example, if you set Topicdata QoS on data reader, using the command: + +.. code-block:: console + + $ pubsub --topic hello --qos Topicdata test --entityqos datareader + +It will show a warning stating that the policy is not applicable and will be ignored, like this: + +.. code-block:: console + + InapplicableQosWarning: The Policy.Topicdata(data=b'test') is not applicable for datareader, will be ignored. + + +Incompatible QoS +"""""""""""""""" + +To publish and subscribe to data, some QoS need to be compatible between the publisher and subscriber ends, this is the RxO (Requested/Offered) property. + +When setting the entity QoS in the **pubsub**, if the QoS you set has RxO property, and if the QoS policy is incompatible between what is requested by the subscriber and what is offered by the publisher, the **pubsub** will print out a warning message, stating that it detects request/offer incompatibility, may not be able to publish and subscribe successfully. + +For example, if you set the Durability QoS to TransientLocal for data reader, using the command: + +.. code-block:: console + + $ pubsub --topic hello --qos Durability.TransientLocal --entityqos datareader + +The **pubsub** will print out a warning message for incompatible QoS, like this: + +.. code-block:: console + + IncompatibleQosWarning: The Qos requested for subscription is incompatible with the Qos offered by publication.PubSub may not be available. + + +And if you try to publish data in the terminal, the **pubsub** won't be able to subscribe to that published data. + +Write to file +^^^^^^^^^^^^^ + +When data is subscribed in the **pubsub**, the subscribed data will be printed out in the terminal. There is an option to also write the subscribed data to a file, using the ``--filename`` option to provide the name of the file you want to write to. The outputted file will be written in JSON format. + +For example, you can choose to write the result to a file named "pubsub_data.json" using the command: + +.. code-block:: + + $ pubsub --topic hello --filename pubsub_data.json + +When publishing data in the terminal, you can view the subscribed results in the terminal and the results will be written to the "pubsub_data.json" file when the **pubsub** stops running. The "pubsub_data.json" file will look like this: + +.. code-block:: JSON + + { + "sequence 0": { + "type": "integer", + "keyval": 420 + }, + "sequence 1": { + "type": "integer", + "keyval": 33 + }, + "sequence 2": { + "type": "string", + "keyval": "hello" + }, + "sequence 3": { + "type": "int_array", + "keyval": [ + 2, + 3, + 3 + ] + } + } + +In the output file: + +* **"sequence "** is the sequence number for the subscribed data; +* **"type"** is the datatype for the topic; +* **"keyval"** is the data you published. + +Runtime +^^^^^^^ + +By default, the **pubsub** will run indefinitely until there is an interrupt, but you can also use the ``--runtime`` option to stop the **pubsub** after running for a certain time. + +For example, if you want to run the **pubsub** for 5 seconds, you can use the command: + +.. code-block:: console + + $ pubsub --topic hello --runtime 5 + +And the **pubsub** will be run for 5 seconds, publish and subscribe to data in the terminal within the 5 seconds, then automatically exit the tool after 5 seconds. \ No newline at end of file diff --git a/docs/manual/shared_memory/shared_memory.rst b/docs/manual/shared_memory/shared_memory.rst index 31669956d5..a1b7354009 100644 --- a/docs/manual/shared_memory/shared_memory.rst +++ b/docs/manual/shared_memory/shared_memory.rst @@ -36,7 +36,7 @@ Prerequisites sudo apt install cmake libacl1-dev libncurses5-dev pkg-config maven -#. Get and build iceoryx. The following assumes that the istall is in your home directory: +#. Get and build iceoryx. The following assumes that the install is in your home directory: .. code-block:: bash