Skip to content

Commit 408dc17

Browse files
authored
Merge branch 'omg-dds:master' into master
2 parents 164d254 + f872030 commit 408dc17

7 files changed

Lines changed: 2070 additions & 54 deletions

File tree

.github/workflows/1_run_interoperability_tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ jobs:
4444
latest: true
4545
fileName: "*"
4646
out-file-path: zipped_executables
47+
preRelease: true
4748
- name: Unzip executables
4849
run: unzip 'zipped_executables/*.zip' -d executables
4950
- name: Install Python requirements

CLA/CLA_HDDS.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# OMG DDS INTEROPERABILITY REPOSITORY - CONTRIBUTOR LICENSE AGREEMENT
2+
3+
**This Contributor License Agreement ("Agreement") specifies the terms under which the individual or corporate entity specified in the signature block below ("You") agree to make intellectual property contributions to the OMG DDS Interoperability Repository. BY SIGNING BELOW YOU ARE AGREEING TO BE BOUND BY THE TERMS OF THIS AGREEMENT. If You are signing this Agreement in Your capacity as an employee, THEN YOUR EMPLOYER AND YOU ARE BOTH BOUND BY THIS AGREEMENT.**
4+
5+
1. Definitions
6+
7+
1. "OMG DDS Interoperability Repository" (or "Repository") means the Git repository [https://github.com/omg-dds/dds-rtps](https://github.com/omg-dds/dds-rtps).
8+
9+
2. "Moderator" means an entity or individual responsible for authorizing changes to the Repository.
10+
11+
3. "Submit" (or "Submitted") means any submission, including source code, binaries, code, pull requests, issue reports, comments, etc., made to the Moderators for inclusion in the Repository either through the Git repository interface or through electronic file transfer.
12+
13+
4. A "Contribution" is any original work of authorship, including any modifications or additions to an existing work, that You Submit to the DDS Interoperability Repository.
14+
15+
5. A "User" is anyone who accesses the Repository.
16+
17+
2. Allowable Contribution Representations
18+
19+
1. You represent that You have the necessary rights to the Contribution(s) to meet the obligations of this Agreement. If You are employed, Your employer has authorized Contribution(s) under this Agreement.
20+
21+
2. You represent that you have no knowledge of third-party intellectual property rights that are likely to be infringed by the Contribution(s). You represent that you have no knowledge that such infringement or any allegation of misappropriation of intellectual property rights is likely to be claimed or has already been claimed.
22+
23+
3. License
24+
25+
You grant Moderators a perpetual, worldwide, non-exclusive, assignable, paid-up license to publish, display, and redistribute the Contribution as part of the Repository. You also license to Moderators under the same terms any other intellectual property rights required to publish, display, and redistribute the Contributions as part of the Repository. You further grant all Users of the Repository a license to the Contribution under the terms of the [OMG DDS Interoperability Testing License](../LICENSE.md) included in the Repository. Moderators are under no obligation to publish Contributions.
26+
27+
4. No Warranty, Consequential Damages. Limited Liability
28+
29+
Other than explicitly stated herein, You provide the Contribution(s) "as is" with no warranty nor claims of fitness to any purpose. Neither party shall be liable for consequential or special damages of any kind. Other than for breach of warranty or representations herein, the liability of either party to the other shall be limited to $1000.
30+
31+
5. General
32+
33+
1. If You are an agency of the United States Government, then this Agreement will be governed by the United States federal common law. Otherwise, this Agreement will be governed by the laws of the State of California except with regard to its choice of law rules.
34+
35+
2. A party may assign this Agreement to an entity acquiring essentially all of the party's relevant business.
36+
37+
6. Electronic Signatures
38+
39+
"Electronic Signature" means any electronic sound, symbol, or process attached to or logically associated with a record and executed and adopted by a party with the intent to sign such record.
40+
41+
Each party agrees that the Electronic Signatures, whether digital or encrypted, of the parties included in this Agreement are intended to authenticate this writing and to have the same force and effect as manual signatures.
42+
43+
44+
IN WITNESS WHEREOF, You, intending to be legally bound, have executed this Agreement or caused Your employer's proper and duly authorized officer to execute and deliver this Agreement, for good and valuable consideration, the sufficiency of which is hereby acknowledged, as of the day and year first written below.
45+
46+
**For:**
47+
48+
Entity Name: Olivier Esteve
49+
50+
Address: Loiret, France
51+
52+
("**You**")
53+
54+
**By:**
55+
56+
Name: Olivier Esteve
57+
58+
Title: Founder, naskel.com
59+
60+
Date: March 28, 2026

srcRs/DustDDS/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ publish = false
1717
clap = { version = "4.5.47", features = ["derive", "string"] }
1818
rand = "0.8.5"
1919
ctrlc = "3.4"
20-
dust_dds = "0.14.0"
20+
dust_dds = { version = "0.15.0" }
2121

2222
[build-dependencies]
23-
dust_dds_gen = "0.14.0"
23+
dust_dds_gen = "0.15.0"

srcRs/DustDDS/build.rs

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
1-
use std::{
2-
fs::{self, File},
3-
io::Write,
4-
path::Path,
5-
};
6-
7-
fn main() {
8-
let cargo_target_dir = std::env::var("OUT_DIR").unwrap();
9-
let cargo_manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
10-
let cargo_target_path = Path::new(&cargo_target_dir);
11-
let cargo_manifest_path = Path::new(&cargo_manifest_dir);
12-
let build_path = cargo_target_path.join("idl");
13-
let idl_path = cargo_manifest_path.join("..").join("..").join("srcCxx").join("shape.idl");
14-
let compiled_idl = dust_dds_gen::compile_idl(&idl_path).expect("Couldn't parse IDL file");
15-
let compiled_idl_path = build_path.as_path().join("shape.rs");
16-
fs::create_dir_all(build_path).expect("Creating build path failed");
17-
let mut file = File::create(compiled_idl_path).expect("Failed to create file");
18-
file.write_all(compiled_idl.as_bytes())
19-
.expect("Failed to write to file");
20-
}
1+
use std::{
2+
fs::{self, File},
3+
io::Write,
4+
path::Path,
5+
};
6+
7+
fn main() {
8+
let cargo_target_dir = std::env::var("OUT_DIR").unwrap();
9+
let cargo_manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
10+
let cargo_target_path = Path::new(&cargo_target_dir);
11+
let cargo_manifest_path = Path::new(&cargo_manifest_dir);
12+
let build_path = cargo_target_path.join("idl");
13+
let idl_path = cargo_manifest_path
14+
.join("..")
15+
.join("..")
16+
.join("srcCxx")
17+
.join("shape.idl");
18+
let compiled_idl = dust_dds_gen::compile_idl(&idl_path).expect("Couldn't parse IDL file");
19+
let compiled_idl_path = build_path.as_path().join("shape.rs");
20+
fs::create_dir_all(build_path).expect("Creating build path failed");
21+
let mut file = File::create(compiled_idl_path).expect("Failed to create file");
22+
file.write_all(compiled_idl.as_bytes())
23+
.expect("Failed to write to file");
24+
}

srcRs/DustDDS/src/main.rs

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ use dust_dds::{
2222
},
2323
listener::NO_LISTENER,
2424
publication::data_writer::DataWriter,
25-
runtime::DdsRuntime,
26-
std_runtime::StdRuntime,
2725
subscription::data_reader::DataReader,
2826
};
2927
use rand::{Rng, random, thread_rng};
@@ -227,6 +225,16 @@ struct Options {
227225
/// uses take()/read() instead of take_next_instance() read_next_instance()
228226
#[clap(short = 'K', long = "take-read")]
229227
take_read: bool,
228+
229+
/// ContentFilteredTopic filter expression (quotes required around the expression). Cannot be used with -c on
230+
/// subscriber applications
231+
#[clap(short = 'F', long = "cft")]
232+
cft_expression: Option<String>,
233+
234+
/// If set, the modulo operation is applied to the shapesize. This will make that shapesize is in the range [1,N].
235+
/// This only applies if shapesize is increased (-z 0)
236+
#[clap(short = 'Q', long = "size-modulo")]
237+
size_modulo: Option<i32>,
230238
}
231239

232240
impl Options {
@@ -240,7 +248,7 @@ impl Options {
240248
Ok(())
241249
}
242250

243-
fn color_for_publisher(&self) -> String {
251+
fn interpret_color(&self) -> String {
244252
match self.color.clone() {
245253
Some(color) => color,
246254
None => {
@@ -331,10 +339,10 @@ impl Options {
331339
}
332340

333341
struct Listener;
334-
impl<R: DdsRuntime> DomainParticipantListener<R> for Listener {
342+
impl DomainParticipantListener for Listener {
335343
async fn on_inconsistent_topic(
336344
&mut self,
337-
the_topic: TopicAsync<R>,
345+
the_topic: TopicAsync,
338346
_status: InconsistentTopicStatus,
339347
) {
340348
println!(
@@ -346,7 +354,7 @@ impl<R: DdsRuntime> DomainParticipantListener<R> for Listener {
346354

347355
async fn on_offered_incompatible_qos(
348356
&mut self,
349-
the_writer: dust_dds::dds_async::data_writer::DataWriterAsync<R, ()>,
357+
the_writer: dust_dds::dds_async::data_writer::DataWriterAsync<()>,
350358
status: dust_dds::infrastructure::status::OfferedIncompatibleQosStatus,
351359
) {
352360
let policy_name = qos_policy_name(status.last_policy_id);
@@ -361,7 +369,7 @@ impl<R: DdsRuntime> DomainParticipantListener<R> for Listener {
361369

362370
async fn on_publication_matched(
363371
&mut self,
364-
the_writer: dust_dds::dds_async::data_writer::DataWriterAsync<R, ()>,
372+
the_writer: dust_dds::dds_async::data_writer::DataWriterAsync<()>,
365373
status: dust_dds::infrastructure::status::PublicationMatchedStatus,
366374
) {
367375
if !the_writer.get_topic().get_name().starts_with("DCPS") {
@@ -377,7 +385,7 @@ impl<R: DdsRuntime> DomainParticipantListener<R> for Listener {
377385

378386
async fn on_offered_deadline_missed(
379387
&mut self,
380-
the_writer: dust_dds::dds_async::data_writer::DataWriterAsync<R, ()>,
388+
the_writer: dust_dds::dds_async::data_writer::DataWriterAsync<()>,
381389
status: dust_dds::infrastructure::status::OfferedDeadlineMissedStatus,
382390
) {
383391
println!(
@@ -391,7 +399,7 @@ impl<R: DdsRuntime> DomainParticipantListener<R> for Listener {
391399

392400
async fn on_liveliness_lost(
393401
&mut self,
394-
the_writer: dust_dds::dds_async::data_writer::DataWriterAsync<R, ()>,
402+
the_writer: dust_dds::dds_async::data_writer::DataWriterAsync<()>,
395403
status: dust_dds::infrastructure::status::LivelinessLostStatus,
396404
) {
397405
println!(
@@ -405,7 +413,7 @@ impl<R: DdsRuntime> DomainParticipantListener<R> for Listener {
405413

406414
async fn on_requested_incompatible_qos(
407415
&mut self,
408-
the_reader: dust_dds::dds_async::data_reader::DataReaderAsync<R, ()>,
416+
the_reader: dust_dds::dds_async::data_reader::DataReaderAsync<()>,
409417
status: dust_dds::infrastructure::status::RequestedIncompatibleQosStatus,
410418
) {
411419
let policy_name = qos_policy_name(status.last_policy_id);
@@ -420,7 +428,7 @@ impl<R: DdsRuntime> DomainParticipantListener<R> for Listener {
420428

421429
async fn on_subscription_matched(
422430
&mut self,
423-
the_reader: dust_dds::dds_async::data_reader::DataReaderAsync<R, ()>,
431+
the_reader: dust_dds::dds_async::data_reader::DataReaderAsync<()>,
424432
status: dust_dds::infrastructure::status::SubscriptionMatchedStatus,
425433
) {
426434
if !the_reader
@@ -440,7 +448,7 @@ impl<R: DdsRuntime> DomainParticipantListener<R> for Listener {
440448

441449
async fn on_requested_deadline_missed(
442450
&mut self,
443-
the_reader: dust_dds::dds_async::data_reader::DataReaderAsync<R, ()>,
451+
the_reader: dust_dds::dds_async::data_reader::DataReaderAsync<()>,
444452
status: dust_dds::infrastructure::status::RequestedDeadlineMissedStatus,
445453
) {
446454
println!(
@@ -454,7 +462,7 @@ impl<R: DdsRuntime> DomainParticipantListener<R> for Listener {
454462

455463
async fn on_liveliness_changed(
456464
&mut self,
457-
the_reader: dust_dds::dds_async::data_reader::DataReaderAsync<R, ()>,
465+
the_reader: dust_dds::dds_async::data_reader::DataReaderAsync<()>,
458466
status: dust_dds::infrastructure::status::LivelinessChangedStatus,
459467
) {
460468
println!(
@@ -495,9 +503,9 @@ fn move_shape(
495503
}
496504

497505
fn init_publisher(
498-
participant: &DomainParticipant<StdRuntime>,
506+
participant: &DomainParticipant,
499507
options: Options,
500-
) -> Result<DataWriter<StdRuntime, ShapeType>, InitializeError> {
508+
) -> Result<DataWriter<ShapeType>, InitializeError> {
501509
let topic = participant
502510
.lookup_topicdescription(&options.topic_name)
503511
.expect("lookup_topicdescription succeeds")
@@ -510,7 +518,7 @@ fn init_publisher(
510518
println!(
511519
"Create writer for topic: {} color: {}",
512520
options.topic_name,
513-
options.color_for_publisher()
521+
options.interpret_color()
514522
);
515523

516524
let mut data_writer_qos = DataWriterQos {
@@ -541,7 +549,7 @@ fn init_publisher(
541549
}
542550

543551
fn run_publisher(
544-
data_writer: &DataWriter<StdRuntime, ShapeType>,
552+
data_writer: &DataWriter<ShapeType>,
545553
options: Options,
546554
all_done: Receiver<()>,
547555
) -> Result<(), RunningError> {
@@ -550,7 +558,7 @@ fn run_publisher(
550558
let da_width = 240;
551559
let da_height = 270;
552560
let mut shape = ShapeType {
553-
color: options.color_for_publisher(),
561+
color: options.interpret_color(),
554562
x: random::<i32>() % da_width,
555563
y: random::<i32>() % da_height,
556564
shapesize: options.shapesize,
@@ -571,7 +579,12 @@ fn run_publisher(
571579

572580
while all_done.try_recv().is_err() {
573581
if options.shapesize == 0 {
574-
shape.shapesize += 1;
582+
if let Some(size_modulo) = options.size_modulo {
583+
// Size cannot be 0, so increase it after modulo operation
584+
shape.shapesize = (shape.shapesize % size_modulo) + 1;
585+
} else {
586+
shape.shapesize += 1;
587+
}
575588
}
576589

577590
move_shape(&mut shape, &mut x_vel, &mut y_vel, da_width, da_height);
@@ -594,9 +607,9 @@ fn run_publisher(
594607
}
595608

596609
fn init_subscriber(
597-
participant: &DomainParticipant<StdRuntime>,
610+
participant: &DomainParticipant,
598611
options: Options,
599-
) -> Result<DataReader<StdRuntime, ShapeType>, InitializeError> {
612+
) -> Result<DataReader<ShapeType>, InitializeError> {
600613
let topic = participant
601614
.lookup_topicdescription(&options.topic_name)
602615
.expect("lookup_topicdescription succeeds")
@@ -621,18 +634,21 @@ fn init_subscriber(
621634
);
622635
}
623636

624-
let data_reader = match options.color {
625-
// filter on specified color
626-
Some(color) => {
637+
let data_reader = match options.cft_expression {
638+
Some(cft_expression) => {
627639
let filtered_topic_name = options.topic_name + "_filtered";
628-
println!(
629-
"Create reader for topic: {} color: {}",
630-
filtered_topic_name, &color
631-
);
640+
println!("ContentFilterTopic = \"{cft_expression}\"");
641+
println!("Create reader for topic: {} ", filtered_topic_name);
642+
let color = cft_expression
643+
.split("=")
644+
.nth(1)
645+
.unwrap()
646+
.trim_matches(&[' ', '\''])
647+
.to_string();
632648
let content_filtered_topic = participant.create_contentfilteredtopic(
633649
&filtered_topic_name,
634650
&topic,
635-
String::from("color = %0"),
651+
cft_expression,
636652
vec![color],
637653
)?;
638654

@@ -643,7 +659,6 @@ fn init_subscriber(
643659
NO_STATUS,
644660
)?
645661
}
646-
// No filter on specified color
647662
None => {
648663
println!("Create reader for topic: {} ", options.topic_name);
649664
subscriber.create_datareader::<ShapeType>(
@@ -659,7 +674,7 @@ fn init_subscriber(
659674
}
660675

661676
fn run_subscriber(
662-
data_reader: &DataReader<StdRuntime, ShapeType>,
677+
data_reader: &DataReader<ShapeType>,
663678
options: Options,
664679
all_done: Receiver<()>,
665680
) -> Result<(), RunningError> {
@@ -713,7 +728,7 @@ fn run_subscriber(
713728
Ok(())
714729
}
715730

716-
fn initialize(options: &Options) -> Result<DomainParticipant<StdRuntime>, InitializeError> {
731+
fn initialize(options: &Options) -> Result<DomainParticipant, InitializeError> {
717732
let participant_factory = DomainParticipantFactory::get_instance();
718733
let participant = participant_factory.create_participant(
719734
options.domain_id,

srcRs/HDDS/Cargo.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
name = "hdds_shape_main_linux"
3+
version = "0.1.0"
4+
edition = "2021"
5+
rust-version = "1.75"
6+
description = "OMG DDS-RTPS Interoperability"
7+
authors = ["Olivier Esteve <olivier@naskel.com>"]
8+
repository = "https://github.com/hdds-team/hdds"
9+
publish = false
10+
readme = false
11+
12+
[[bin]]
13+
name = "shape_main"
14+
path = "src/main.rs"
15+
16+
[dependencies]
17+
hdds = "1.1"
18+
19+
[profile.release]
20+
opt-level = 3
21+
lto = true
22+
strip = "debuginfo"

0 commit comments

Comments
 (0)