r2r/
qos.rs

1// The content of this file has the Apache 2.0 licence due to its origin in the rclrust repo (https://github.com/rclrust/rclrust). The licence of that repo is included below.
2//
3//                                 Apache License
4//                           Version 2.0, January 2004
5//                        http://www.apache.org/licenses/
6//
7//   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
8//
9//   1. Definitions.
10//
11//      "License" shall mean the terms and conditions for use, reproduction,
12//      and distribution as defined by Sections 1 through 9 of this document.
13//
14//      "Licensor" shall mean the copyright owner or entity authorized by
15//      the copyright owner that is granting the License.
16//
17//      "Legal Entity" shall mean the union of the acting entity and all
18//      other entities that control, are controlled by, or are under common
19//      control with that entity. For the purposes of this definition,
20//      "control" means (i) the power, direct or indirect, to cause the
21//      direction or management of such entity, whether by contract or
22//      otherwise, or (ii) ownership of fifty percent (50%) or more of the
23//      outstanding shares, or (iii) beneficial ownership of such entity.
24//
25//      "You" (or "Your") shall mean an individual or Legal Entity
26//      exercising permissions granted by this License.
27//
28//      "Source" form shall mean the preferred form for making modifications,
29//      including but not limited to software source code, documentation
30//      source, and configuration files.
31//
32//      "Object" form shall mean any form resulting from mechanical
33//      transformation or translation of a Source form, including but
34//      not limited to compiled object code, generated documentation,
35//      and conversions to other media types.
36//
37//      "Work" shall mean the work of authorship, whether in Source or
38//      Object form, made available under the License, as indicated by a
39//      copyright notice that is included in or attached to the work
40//      (an example is provided in the Appendix below).
41//
42//      "Derivative Works" shall mean any work, whether in Source or Object
43//      form, that is based on (or derived from) the Work and for which the
44//      editorial revisions, annotations, elaborations, or other modifications
45//      represent, as a whole, an original work of authorship. For the purposes
46//      of this License, Derivative Works shall not include works that remain
47//      separable from, or merely link (or bind by name) to the interfaces of,
48//      the Work and Derivative Works thereof.
49//
50//      "Contribution" shall mean any work of authorship, including
51//      the original version of the Work and any modifications or additions
52//      to that Work or Derivative Works thereof, that is intentionally
53//      submitted to Licensor for inclusion in the Work by the copyright owner
54//      or by an individual or Legal Entity authorized to submit on behalf of
55//      the copyright owner. For the purposes of this definition, "submitted"
56//      means any form of electronic, verbal, or written communication sent
57//      to the Licensor or its representatives, including but not limited to
58//      communication on electronic mailing lists, source code control systems,
59//      and issue tracking systems that are managed by, or on behalf of, the
60//      Licensor for the purpose of discussing and improving the Work, but
61//      excluding communication that is conspicuously marked or otherwise
62//      designated in writing by the copyright owner as "Not a Contribution."
63//
64//      "Contributor" shall mean Licensor and any individual or Legal Entity
65//      on behalf of whom a Contribution has been received by Licensor and
66//      subsequently incorporated within the Work.
67//
68//   2. Grant of Copyright License. Subject to the terms and conditions of
69//      this License, each Contributor hereby grants to You a perpetual,
70//      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
71//      copyright license to reproduce, prepare Derivative Works of,
72//      publicly display, publicly perform, sublicense, and distribute the
73//      Work and such Derivative Works in Source or Object form.
74//
75//   3. Grant of Patent License. Subject to the terms and conditions of
76//      this License, each Contributor hereby grants to You a perpetual,
77//      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
78//      (except as stated in this section) patent license to make, have made,
79//      use, offer to sell, sell, import, and otherwise transfer the Work,
80//      where such license applies only to those patent claims licensable
81//      by such Contributor that are necessarily infringed by their
82//      Contribution(s) alone or by combination of their Contribution(s)
83//      with the Work to which such Contribution(s) was submitted. If You
84//      institute patent litigation against any entity (including a
85//      cross-claim or counterclaim in a lawsuit) alleging that the Work
86//      or a Contribution incorporated within the Work constitutes direct
87//      or contributory patent infringement, then any patent licenses
88//      granted to You under this License for that Work shall terminate
89//      as of the date such litigation is filed.
90//
91//   4. Redistribution. You may reproduce and distribute copies of the
92//      Work or Derivative Works thereof in any medium, with or without
93//      modifications, and in Source or Object form, provided that You
94//      meet the following conditions:
95//
96//      (a) You must give any other recipients of the Work or
97//          Derivative Works a copy of this License; and
98//
99//      (b) You must cause any modified files to carry prominent notices
100//          stating that You changed the files; and
101//
102//      (c) You must retain, in the Source form of any Derivative Works
103//          that You distribute, all copyright, patent, trademark, and
104//          attribution notices from the Source form of the Work,
105//          excluding those notices that do not pertain to any part of
106//          the Derivative Works; and
107//
108//      (d) If the Work includes a "NOTICE" text file as part of its
109//          distribution, then any Derivative Works that You distribute must
110//          include a readable copy of the attribution notices contained
111//          within such NOTICE file, excluding those notices that do not
112//          pertain to any part of the Derivative Works, in at least one
113//          of the following places: within a NOTICE text file distributed
114//          as part of the Derivative Works; within the Source form or
115//          documentation, if provided along with the Derivative Works; or,
116//          within a display generated by the Derivative Works, if and
117//          wherever such third-party notices normally appear. The contents
118//          of the NOTICE file are for informational purposes only and
119//          do not modify the License. You may add Your own attribution
120//          notices within Derivative Works that You distribute, alongside
121//          or as an addendum to the NOTICE text from the Work, provided
122//          that such additional attribution notices cannot be construed
123//          as modifying the License.
124//
125//      You may add Your own copyright statement to Your modifications and
126//      may provide additional or different license terms and conditions
127//      for use, reproduction, or distribution of Your modifications, or
128//      for any such Derivative Works as a whole, provided Your use,
129//      reproduction, and distribution of the Work otherwise complies with
130//      the conditions stated in this License.
131//
132//   5. Submission of Contributions. Unless You explicitly state otherwise,
133//      any Contribution intentionally submitted for inclusion in the Work
134//      by You to the Licensor shall be under the terms and conditions of
135//      this License, without any additional terms or conditions.
136//      Notwithstanding the above, nothing herein shall supersede or modify
137//      the terms of any separate license agreement you may have executed
138//      with Licensor regarding such Contributions.
139//
140//   6. Trademarks. This License does not grant permission to use the trade
141//      names, trademarks, service marks, or product names of the Licensor,
142//      except as required for reasonable and customary use in describing the
143//      origin of the Work and reproducing the content of the NOTICE file.
144//
145//   7. Disclaimer of Warranty. Unless required by applicable law or
146//      agreed to in writing, Licensor provides the Work (and each
147//      Contributor provides its Contributions) on an "AS IS" BASIS,
148//      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
149//      implied, including, without limitation, any warranties or conditions
150//      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
151//      PARTICULAR PURPOSE. You are solely responsible for determining the
152//      appropriateness of using or redistributing the Work and assume any
153//      risks associated with Your exercise of permissions under this License.
154//
155//   8. Limitation of Liability. In no event and under no legal theory,
156//      whether in tort (including negligence), contract, or otherwise,
157//      unless required by applicable law (such as deliberate and grossly
158//      negligent acts) or agreed to in writing, shall any Contributor be
159//      liable to You for damages, including any direct, indirect, special,
160//      incidental, or consequential damages of any character arising as a
161//      result of this License or out of the use or inability to use the
162//      Work (including but not limited to damages for loss of goodwill,
163//      work stoppage, computer failure or malfunction, or any and all
164//      other commercial damages or losses), even if such Contributor
165//      has been advised of the possibility of such damages.
166//
167//   9. Accepting Warranty or Additional Liability. While redistributing
168//      the Work or Derivative Works thereof, You may choose to offer,
169//      and charge a fee for, acceptance of support, warranty, indemnity,
170//      or other liability obligations and/or rights consistent with this
171//      License. However, in accepting such obligations, You may act only
172//      on Your own behalf and on Your sole responsibility, not on behalf
173//      of any other Contributor, and only if You agree to indemnify,
174//      defend, and hold each Contributor harmless for any liability
175//      incurred by, or claims asserted against, such Contributor by reason
176//      of your accepting any such warranty or additional liability.
177//
178//   END OF TERMS AND CONDITIONS
179//
180//   APPENDIX: How to apply the Apache License to your work.
181//
182//      To apply the Apache License to your work, attach the following
183//      boilerplate notice, with the fields enclosed by brackets "[]"
184//      replaced with your own identifying information. (Don't include
185//      the brackets!)  The text should be enclosed in the appropriate
186//      comment syntax for the file format. We also recommend that a
187//      file or class name and description of purpose be included on the
188//      same "printed page" as the copyright notice for easier
189//      identification within third-party archives.
190//
191//   Copyright [yyyy] [name of copyright owner]
192//
193//   Licensed under the Apache License, Version 2.0 (the "License");
194//   you may not use this file except in compliance with the License.
195//   You may obtain a copy of the License at
196//
197//       http://www.apache.org/licenses/LICENSE-2.0
198//
199//   Unless required by applicable law or agreed to in writing, software
200//   distributed under the License is distributed on an "AS IS" BASIS,
201//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
202//   See the License for the specific language governing permissions and
203//   limitations under the License.
204
205//! QoS (Quality of Service)
206//! full credit goes to <https://github.com/rclrust/rclrust/blob/main/rclrust/src/qos.rs>
207
208use std::time::Duration;
209
210use r2r_rcl::{
211    rmw_qos_durability_policy_t, rmw_qos_history_policy_t, rmw_qos_liveliness_policy_t,
212    rmw_qos_reliability_policy_t, rmw_time_t,
213};
214
215#[derive(Debug, Clone, PartialEq, Eq)]
216pub enum HistoryPolicy {
217    KeepAll,
218    KeepLast,
219    SystemDefault,
220    Unknown,
221}
222
223impl From<HistoryPolicy> for rmw_qos_history_policy_t {
224    fn from(history_policy: HistoryPolicy) -> Self {
225        match history_policy {
226            HistoryPolicy::KeepAll => rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_KEEP_ALL,
227            HistoryPolicy::KeepLast => rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_KEEP_LAST,
228            HistoryPolicy::SystemDefault => {
229                rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT
230            }
231            HistoryPolicy::Unknown => rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_UNKNOWN,
232        }
233    }
234}
235
236impl From<rmw_qos_history_policy_t> for HistoryPolicy {
237    fn from(rmw_history_policy: rmw_qos_history_policy_t) -> Self {
238        match rmw_history_policy {
239            rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_KEEP_ALL => HistoryPolicy::KeepAll,
240            rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_KEEP_LAST => HistoryPolicy::KeepLast,
241            rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT => {
242                HistoryPolicy::SystemDefault
243            }
244            rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_UNKNOWN => HistoryPolicy::Unknown,
245        }
246    }
247}
248
249#[derive(Debug, Clone, PartialEq, Eq)]
250pub enum ReliabilityPolicy {
251    BestEffort,
252    Reliable,
253    SystemDefault,
254    #[cfg(any(r2r__ros__distro__iron, r2r__ros__distro__jazzy, r2r__ros__distro__rolling))]
255    BestAvailable,
256    Unknown,
257}
258impl From<ReliabilityPolicy> for rmw_qos_reliability_policy_t {
259    fn from(reliability_policy: ReliabilityPolicy) -> Self {
260        match reliability_policy {
261            ReliabilityPolicy::BestEffort => {
262                rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT
263            }
264            ReliabilityPolicy::Reliable => {
265                rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_RELIABLE
266            }
267            ReliabilityPolicy::SystemDefault => {
268                rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT
269            }
270            #[cfg(any(r2r__ros__distro__iron, r2r__ros__distro__jazzy, r2r__ros__distro__rolling))]
271            ReliabilityPolicy::BestAvailable => {
272                rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_BEST_AVAILABLE
273            }
274            ReliabilityPolicy::Unknown => {
275                rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_UNKNOWN
276            }
277        }
278    }
279}
280
281impl From<rmw_qos_reliability_policy_t> for ReliabilityPolicy {
282    fn from(rmw_reliability_policy: rmw_qos_reliability_policy_t) -> Self {
283        match rmw_reliability_policy {
284            rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT => {
285                ReliabilityPolicy::BestEffort
286            }
287            rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_RELIABLE => {
288                ReliabilityPolicy::Reliable
289            }
290            rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT => {
291                ReliabilityPolicy::SystemDefault
292            }
293            #[cfg(any(r2r__ros__distro__iron, r2r__ros__distro__jazzy, r2r__ros__distro__rolling))]
294            rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_BEST_AVAILABLE => {
295                ReliabilityPolicy::BestAvailable
296            }
297            rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_UNKNOWN => {
298                ReliabilityPolicy::Unknown
299            }
300        }
301    }
302}
303
304#[derive(Debug, Clone, PartialEq, Eq)]
305pub enum DurabilityPolicy {
306    TransientLocal,
307    Volatile,
308    SystemDefault,
309    #[cfg(any(r2r__ros__distro__iron, r2r__ros__distro__jazzy, r2r__ros__distro__rolling))]
310    BestAvailable,
311    Unknown,
312}
313
314impl From<DurabilityPolicy> for rmw_qos_durability_policy_t {
315    fn from(durability_policy: DurabilityPolicy) -> Self {
316        match durability_policy {
317            DurabilityPolicy::TransientLocal => {
318                rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL
319            }
320            DurabilityPolicy::Volatile => {
321                rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_VOLATILE
322            }
323            DurabilityPolicy::SystemDefault => {
324                rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT
325            }
326            #[cfg(any(r2r__ros__distro__iron, r2r__ros__distro__jazzy, r2r__ros__distro__rolling))]
327            DurabilityPolicy::BestAvailable => {
328                rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_BEST_AVAILABLE
329            }
330            DurabilityPolicy::Unknown => {
331                rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_UNKNOWN
332            }
333        }
334    }
335}
336
337impl From<rmw_qos_durability_policy_t> for DurabilityPolicy {
338    fn from(rmw_durability_policy: rmw_qos_durability_policy_t) -> Self {
339        match rmw_durability_policy {
340            rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL => {
341                DurabilityPolicy::TransientLocal
342            }
343            rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_VOLATILE => {
344                DurabilityPolicy::Volatile
345            }
346            rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT => {
347                DurabilityPolicy::SystemDefault
348            }
349            #[cfg(any(r2r__ros__distro__iron, r2r__ros__distro__jazzy, r2r__ros__distro__rolling))]
350            rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_BEST_AVAILABLE => {
351                DurabilityPolicy::BestAvailable
352            }
353            rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_UNKNOWN => {
354                DurabilityPolicy::Unknown
355            }
356        }
357    }
358}
359
360#[derive(Debug, Clone, PartialEq, Eq)]
361pub enum LivelinessPolicy {
362    Automatic,
363    ManualByNode,
364    ManualByTopic,
365    SystemDefault,
366    #[cfg(any(r2r__ros__distro__iron, r2r__ros__distro__jazzy, r2r__ros__distro__rolling))]
367    BestAvailable,
368    Unknown,
369}
370
371impl From<LivelinessPolicy> for rmw_qos_liveliness_policy_t {
372    fn from(liveliness_policy: LivelinessPolicy) -> Self {
373        match liveliness_policy {
374            LivelinessPolicy::Automatic => {
375                rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_AUTOMATIC
376            }
377            LivelinessPolicy::ManualByNode => {
378                rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE
379            }
380            LivelinessPolicy::ManualByTopic => {
381                rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC
382            }
383            LivelinessPolicy::SystemDefault => {
384                rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT
385            }
386            #[cfg(any(r2r__ros__distro__iron, r2r__ros__distro__jazzy, r2r__ros__distro__rolling))]
387            LivelinessPolicy::BestAvailable => {
388                rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_BEST_AVAILABLE
389            }
390            LivelinessPolicy::Unknown => {
391                rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_UNKNOWN
392            }
393        }
394    }
395}
396
397impl From<rmw_qos_liveliness_policy_t> for LivelinessPolicy {
398    fn from(rmw_liveliness_policy: rmw_qos_liveliness_policy_t) -> Self {
399        match rmw_liveliness_policy {
400            rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_AUTOMATIC => {
401                LivelinessPolicy::Automatic
402            }
403            rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE => {
404                LivelinessPolicy::ManualByNode
405            }
406            rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC => {
407                LivelinessPolicy::ManualByTopic
408            }
409            rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT => {
410                LivelinessPolicy::SystemDefault
411            }
412            #[cfg(any(r2r__ros__distro__iron, r2r__ros__distro__jazzy, r2r__ros__distro__rolling))]
413            rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_BEST_AVAILABLE => {
414                LivelinessPolicy::BestAvailable
415            }
416            rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_UNKNOWN => {
417                LivelinessPolicy::Unknown
418            }
419        }
420    }
421}
422
423/// QoS profile
424#[derive(Debug, Clone, PartialEq, Eq)]
425pub struct QosProfile {
426    /// History QoS policy setting.
427    pub history: HistoryPolicy,
428    /// Size of the message queue.
429    pub depth: usize,
430    /// Reliabiilty QoS policy setting.
431    pub reliability: ReliabilityPolicy,
432    /// Durability QoS policy setting.
433    pub durability: DurabilityPolicy,
434    /// The period at which messages are expected to be sent/received.
435    pub deadline: Duration,
436    /// The age at which messages are considered expired and no longer valid.
437    pub lifespan: Duration,
438    /// Liveliness QoS policy setting.
439    pub liveliness: LivelinessPolicy,
440    /// The time within which the RMW node or publisher must show that it is alive.
441    pub liveliness_lease_duration: Duration,
442    /// If true, any ROS specific namespacing conventions will be circumvented.
443    ///
444    /// In the case of DDS and topics, for example, this means the typical ROS specific prefix of rt
445    /// would not be applied as described here:
446    ///
447    /// <http://design.ros2.org/articles/topic_and_service_names.html#ros-specific-namespace-prefix>
448    ///
449    /// This might be useful when trying to directly connect a native DDS topic with a ROS 2 topic.
450    pub avoid_ros_namespace_conventions: bool,
451}
452
453impl QosProfile {
454    /// Sensor Data QoS class
455    ///    - History: Keep last,
456    ///    - Depth: 5,
457    ///    - Reliability: Best effort,
458    ///    - Durability: Volatile,
459    ///    - Deadline: Default,
460    ///    - Lifespan: Default,
461    ///    - Liveliness: System default,
462    ///    - Liveliness lease duration: Default,
463    ///    - avoid ros namespace conventions: false
464    pub const fn sensor_data() -> Self {
465        Self {
466            history: HistoryPolicy::KeepLast,
467            depth: 5,
468            reliability: ReliabilityPolicy::BestEffort,
469            durability: DurabilityPolicy::Volatile,
470            ..Self::common()
471        }
472    }
473
474    /// Parameters QoS class
475    ///    - History: Keep last,
476    ///    - Depth: 1000,
477    ///    - Reliability: Reliable,
478    ///    - Durability: Volatile,
479    ///    - Deadline: Default,
480    ///    - Lifespan: Default,
481    ///    - Liveliness: System default,
482    ///    - Liveliness lease duration: Default,
483    ///    - Avoid ros namespace conventions: false
484    pub const fn parameters() -> Self {
485        Self {
486            history: HistoryPolicy::KeepLast,
487            depth: 1000,
488            reliability: ReliabilityPolicy::Reliable,
489            durability: DurabilityPolicy::Volatile,
490            ..Self::common()
491        }
492    }
493
494    /// Default QoS class
495    ///    - History: Keep last,
496    ///    - Depth: 10,
497    ///    - Reliability: Reliable,
498    ///    - Durability: Volatile,
499    ///    - Deadline: Default,
500    ///    - Lifespan: Default,
501    ///    - Liveliness: System default,
502    ///    - Liveliness lease duration: Default,
503    ///    - Avoid ros namespace conventions: false
504    pub const fn default() -> Self {
505        Self {
506            history: HistoryPolicy::KeepLast,
507            depth: 10,
508            reliability: ReliabilityPolicy::Reliable,
509            durability: DurabilityPolicy::Volatile,
510            ..Self::common()
511        }
512    }
513
514    /// Services QoS class
515    ///    - History: Keep last,
516    ///    - Depth: 10,
517    ///    - Reliability: Reliable,
518    ///    - Durability: Volatile,
519    ///    - Deadline: Default,
520    ///    - Lifespan: Default,
521    ///    - Liveliness: System default,
522    ///    - Liveliness lease duration: Default,
523    ///    - Avoid ros namespace conventions: false
524    pub const fn services_default() -> Self {
525        Self {
526            history: HistoryPolicy::KeepLast,
527            depth: 10,
528            reliability: ReliabilityPolicy::Reliable,
529            durability: DurabilityPolicy::Volatile,
530            ..Self::common()
531        }
532    }
533
534    /// Parameter events QoS class
535    ///    - History: Keep last,
536    ///    - Depth: 1000,
537    ///    - Reliability: Reliable,
538    ///    - Durability: Volatile,
539    ///    - Deadline: Default,
540    ///    - Lifespan: Default,
541    ///    - Liveliness: System default,
542    ///    - Liveliness lease duration: Default,
543    ///    - Avoid ros namespace conventions: false
544    pub const fn parameter_events() -> Self {
545        Self {
546            history: HistoryPolicy::KeepLast,
547            depth: 1000,
548            reliability: ReliabilityPolicy::Reliable,
549            durability: DurabilityPolicy::Volatile,
550            ..Self::common()
551        }
552    }
553
554    /// System defaults QoS class
555    ///    - History: System default,
556    ///    - Depth: System default,
557    ///    - Reliability: System default,
558    ///    - Durability: System default,
559    ///    - Deadline: Default,
560    ///    - Lifespan: Default,
561    ///    - Liveliness: System default,
562    ///    - Liveliness lease duration: Default,
563    ///    - Avoid ros namespace conventions: false
564    pub const fn system_default() -> Self {
565        Self::common()
566    }
567
568    /// Unknow QoS class
569    ///    - History: Unknown,
570    ///    - Depth: System default,
571    ///    - Reliability: Unknown,
572    ///    - Durability: Unknown,
573    ///    - Deadline: Default,
574    ///    - Lifespan: Default,
575    ///    - Liveliness: Unknown,
576    ///    - Liveliness lease duration: Default,
577    ///    - Avoid ros namespace conventions: false
578    pub const fn unknown() -> Self {
579        Self {
580            history: HistoryPolicy::Unknown,
581            reliability: ReliabilityPolicy::Unknown,
582            durability: DurabilityPolicy::Unknown,
583            liveliness: LivelinessPolicy::Unknown,
584            ..Self::common()
585        }
586    }
587
588    const fn common() -> Self {
589        Self {
590            history: HistoryPolicy::SystemDefault,
591            depth: r2r_rcl::RMW_QOS_POLICY_DEPTH_SYSTEM_DEFAULT as usize,
592            reliability: ReliabilityPolicy::SystemDefault,
593            durability: DurabilityPolicy::SystemDefault,
594            deadline: Duration::ZERO,
595            lifespan: Duration::ZERO,
596            liveliness: LivelinessPolicy::SystemDefault,
597            liveliness_lease_duration: Duration::ZERO,
598            avoid_ros_namespace_conventions: false,
599        }
600    }
601
602    /// Set the history policy.
603    ///
604    /// # Examples
605    ///
606    /// ```
607    /// # use r2r::qos::{HistoryPolicy, QosProfile};
608    /// #
609    /// let qos = QosProfile::default().history(HistoryPolicy::KeepAll);
610    /// ```
611    pub const fn history(self, history: HistoryPolicy) -> Self {
612        Self { history, ..self }
613    }
614
615    /// Set the history to keep last.
616    ///
617    /// # Examples
618    ///
619    /// ```
620    /// # use r2r::qos::QosProfile;
621    /// #
622    /// let qos = QosProfile::default().keep_last(10);
623    /// ```
624    pub const fn keep_last(self, depth: usize) -> Self {
625        Self {
626            history: HistoryPolicy::KeepLast,
627            depth,
628            ..self
629        }
630    }
631
632    /// Set the history to keep all.
633    ///
634    /// # Examples
635    ///
636    /// ```
637    /// # use r2r::qos::QosProfile;
638    /// #
639    /// let qos = QosProfile::default().keep_all();
640    /// ```
641    pub const fn keep_all(self) -> Self {
642        Self {
643            history: HistoryPolicy::KeepAll,
644            depth: 0,
645            ..self
646        }
647    }
648
649    /// Set the reliability setting.
650    ///
651    /// # Examples
652    ///
653    /// ```
654    /// # use r2r::qos::{QosProfile, ReliabilityPolicy};
655    /// #
656    /// let qos = QosProfile::default().reliability(ReliabilityPolicy::Reliable);
657    /// ```
658    pub const fn reliability(self, reliability: ReliabilityPolicy) -> Self {
659        Self {
660            reliability,
661            ..self
662        }
663    }
664
665    /// Set the reliability setting to reliable.
666    ///
667    /// # Examples
668    ///
669    /// ```
670    /// # use r2r::qos::QosProfile;
671    /// #
672    /// let qos = QosProfile::default().reliable();
673    /// ```
674    pub const fn reliable(self) -> Self {
675        self.reliability(ReliabilityPolicy::Reliable)
676    }
677
678    /// Set the reliability setting to best effort.
679    ///
680    /// # Examples
681    ///
682    /// ```
683    /// # use r2r::qos::QosProfile;
684    /// #
685    /// let qos = QosProfile::default().best_effort();
686    /// ```
687    pub const fn best_effort(self) -> Self {
688        self.reliability(ReliabilityPolicy::BestEffort)
689    }
690
691    /// Set the durability setting.
692    ///
693    /// # Examples
694    ///
695    /// ```
696    /// # use r2r::qos::{DurabilityPolicy, QosProfile};
697    /// #
698    /// let qos = QosProfile::default().durability(DurabilityPolicy::Volatile);
699    /// ```
700    pub const fn durability(self, durability: DurabilityPolicy) -> Self {
701        Self { durability, ..self }
702    }
703
704    /// Set the durability setting to volatile.
705    ///
706    /// # Examples
707    ///
708    /// ```
709    /// # use r2r::qos::QosProfile;
710    /// #
711    /// let qos = QosProfile::default().volatile();
712    /// ```
713    pub const fn volatile(self) -> Self {
714        self.durability(DurabilityPolicy::Volatile)
715    }
716
717    /// Set the durability setting to transient local.
718    ///
719    /// # Examples
720    ///
721    /// ```
722    /// # use r2r::qos::QosProfile;
723    /// #
724    /// let qos = QosProfile::default().transient_local();
725    /// ```
726    pub const fn transient_local(self) -> Self {
727        self.durability(DurabilityPolicy::TransientLocal)
728    }
729
730    /// Set the deadline setting.
731    ///
732    /// # Examples
733    ///
734    /// ```
735    /// # use std::time::Duration;
736    /// #
737    /// # use r2r::qos::QosProfile;
738    /// #
739    /// let qos = QosProfile::default().deadline(Duration::from_secs(5));
740    /// ```
741    pub const fn deadline(self, deadline: Duration) -> Self {
742        Self { deadline, ..self }
743    }
744
745    /// Set the lifespan setting.
746    ///
747    /// # Examples
748    ///
749    /// ```
750    /// # use std::time::Duration;
751    /// #
752    /// # use r2r::qos::QosProfile;
753    /// #
754    /// let qos = QosProfile::default().lifespan(Duration::from_secs(5));
755    /// ```
756    pub const fn lifespan(self, lifespan: Duration) -> Self {
757        Self { lifespan, ..self }
758    }
759
760    /// Set the liveliness setting.
761    ///
762    /// # Examples
763    ///
764    /// ```
765    /// # use r2r::qos::{LivelinessPolicy, QosProfile};
766    /// #
767    /// let qos = QosProfile::default().liveliness(LivelinessPolicy::Automatic);
768    /// ```
769    pub const fn liveliness(self, liveliness: LivelinessPolicy) -> Self {
770        Self { liveliness, ..self }
771    }
772
773    /// Set the liveliness_lease_duration setting.
774    ///
775    /// # Examples
776    ///
777    /// ```
778    /// # use std::time::Duration;
779    /// #
780    /// # use r2r::qos::QosProfile;
781    /// #
782    /// let qos = QosProfile::default().liveliness_lease_duration(Duration::from_secs(5));
783    /// ```
784    pub const fn liveliness_lease_duration(self, liveliness_lease_duration: Duration) -> Self {
785        Self {
786            liveliness_lease_duration,
787            ..self
788        }
789    }
790
791    /// Set the avoid_ros_namespace_conventions setting.
792    ///
793    /// # Examples
794    ///
795    /// ```
796    /// # use r2r::qos::QosProfile;
797    /// #
798    /// let qos = QosProfile::default().avoid_ros_namespace_conventions(true);
799    /// ```
800    pub const fn avoid_ros_namespace_conventions(
801        self, avoid_ros_namespace_conventions: bool,
802    ) -> Self {
803        Self {
804            avoid_ros_namespace_conventions,
805            ..self
806        }
807    }
808}
809
810impl From<QosProfile> for r2r_rcl::rmw_qos_profile_t {
811    fn from(qos: QosProfile) -> Self {
812        Self {
813            history: qos.history.into(),
814            depth: qos.depth,
815            reliability: qos.reliability.into(),
816            durability: qos.durability.into(),
817            deadline: qos.deadline.to_rmw_time_t(),
818            lifespan: qos.lifespan.to_rmw_time_t(),
819            liveliness: qos.liveliness.into(),
820            liveliness_lease_duration: qos.liveliness_lease_duration.to_rmw_time_t(),
821            avoid_ros_namespace_conventions: qos.avoid_ros_namespace_conventions,
822        }
823    }
824}
825
826impl From<r2r_rcl::rmw_qos_profile_t> for QosProfile {
827    fn from(rmw_qos: r2r_rcl::rmw_qos_profile_t) -> Self {
828        QosProfile {
829            history: rmw_qos.history.into(),
830            depth: rmw_qos.depth,
831            reliability: rmw_qos.reliability.into(),
832            durability: rmw_qos.durability.into(),
833            deadline: Duration::from_rmw_time_t(&rmw_qos.deadline),
834            lifespan: Duration::from_rmw_time_t(&rmw_qos.lifespan),
835            liveliness: rmw_qos.liveliness.into(),
836            liveliness_lease_duration: Duration::from_rmw_time_t(
837                &rmw_qos.liveliness_lease_duration,
838            ),
839            avoid_ros_namespace_conventions: rmw_qos.avoid_ros_namespace_conventions,
840        }
841    }
842}
843
844pub(crate) trait RclDurationT {
845    fn to_rmw_time_t(&self) -> rmw_time_t;
846    fn from_rmw_time_t(rmw_time: &rmw_time_t) -> Self;
847}
848
849impl RclDurationT for Duration {
850    fn to_rmw_time_t(&self) -> rmw_time_t {
851        rmw_time_t {
852            sec: self.as_secs(),
853            nsec: self.subsec_nanos().into(),
854        }
855    }
856
857    fn from_rmw_time_t(rmw_time: &rmw_time_t) -> Self {
858        #[cfg(not(r2r__ros__distro__foxy))]
859        {
860            assert!(
861                rmw_time.nsec < 1_000_000_000,
862                "nsec part of rmw_time_t should be less than 1 billion"
863            );
864        }
865
866        #[cfg(r2r__ros__distro__foxy)]
867        {
868            // FIXME: In foxy, duration data obtained from publisher with default qos profile is
869            // sec: 7FFFFFFF (2147483647), nsec: FFFFFFFF (4294967295)
870            if rmw_time.nsec == 4294967295 {
871                // 0s indicates deadline policies are not tracked or enforced in foxy
872                return Duration::new(0, 0);
873            } else if rmw_time.nsec > 1_000_000_000 {
874                panic!("nsec part of rmw_time_t should be less than 1 billion");
875            }
876        }
877
878        Duration::new(rmw_time.sec, rmw_time.nsec as u32)
879    }
880}