-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
EVALG-75: Add Application Design tutorial (#693)
- Loading branch information
Showing
7 changed files
with
534 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Tutorial: Application Design | ||
|
||
This code is part of the Connext Application Design tutorial. | ||
|
||
There are multiple subfolders which contain a toolchain-specific tutorial. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<?xml-model href="https://community.rti.com/schema/7.3.0/rti_dds_profiles.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?> | ||
<dds> | ||
<types> | ||
<const name="VIN_LENGTH" type="uint8" value="17"/> | ||
<typedef name="VIN" type="string" stringMaxLength="VIN_LENGTH"/> | ||
|
||
<struct name="Coord" extensibility="final" nested="true"> | ||
<member name="lat" type="float64"/> | ||
<member name="lon" type="float64"/> | ||
</struct> | ||
<struct name="VehicleTransit" extensibility="appendable"> | ||
<member name="vehicle_vin" | ||
type="nonBasic" | ||
nonBasicTypeName="VIN" | ||
key="true" /> | ||
<member name="current_position" | ||
type="nonBasic" | ||
nonBasicTypeName="Coord" /> | ||
<member name="current_route" | ||
type="nonBasic" | ||
nonBasicTypeName="Coord" | ||
sequenceMaxLength="-1" | ||
optional="true" /> <!-- 'no route' == standby --> | ||
</struct> | ||
|
||
<typedef name="Percentage" type="float64" min="0.0" max="100.0"/> | ||
<struct name="VehicleMetrics" extensibility="appendable"> | ||
<member name="vehicle_vin" | ||
type="nonBasic" | ||
nonBasicTypeName="VIN" | ||
key="true"/> | ||
<member name="fuel_level" | ||
type="nonBasic" | ||
nonBasicTypeName="Percentage"/> | ||
</struct> | ||
</types> | ||
|
||
<qos_library name="VehicleModeling_Library"> | ||
<qos_profile name="VehicleMetrics_Profile"> | ||
<datawriter_qos base_name="BuiltinQosLib::Generic.BestEffort"> | ||
<deadline> | ||
<period> | ||
<sec>10</sec> | ||
<nanosec>0</nanosec> | ||
</period> | ||
</deadline> | ||
</datawriter_qos> | ||
<datareader_qos base_name="BuiltinQosLib::Generic.BestEffort"> | ||
<deadline> | ||
<period> | ||
<sec>15</sec> | ||
<nanosec>0</nanosec> | ||
</period> | ||
</deadline> | ||
</datareader_qos> | ||
</qos_profile> | ||
<qos_profile name="VehicleTransit_Profile"> | ||
<datawriter_qos base_name="BuiltinQosLib::Generic.StrictReliable"> | ||
<durability> | ||
<kind>TRANSIENT_LOCAL_DURABILITY_QOS</kind> | ||
</durability> | ||
</datawriter_qos> | ||
<datareader_qos base_name="BuiltinQosLib::Generic.KeepLastReliable"> | ||
<durability> | ||
<kind>TRANSIENT_LOCAL_DURABILITY_QOS</kind> | ||
</durability> | ||
</datareader_qos> | ||
</qos_profile> | ||
</qos_library> | ||
|
||
<domain_library name="DomainLibrary"> | ||
<domain name="VehicleDomain" domain_id="0"> | ||
<topic name="VehicleMetricsTopic" register_type_ref="VehicleMetrics" /> | ||
<topic name="VehicleTransitTopic" register_type_ref="VehicleTransit" /> | ||
</domain> | ||
</domain_library> | ||
|
||
<domain_participant_library name="ParticipantLibrary"> | ||
<domain_participant name="PublisherApp" domain_ref="DomainLibrary::VehicleDomain"> | ||
<publisher name="Publisher"> | ||
<data_writer name="MetricsWriter" topic_ref="VehicleMetricsTopic"> | ||
<datawriter_qos base_name="VehicleModeling_Library::VehicleMetrics_Profile" /> | ||
</data_writer> | ||
|
||
<data_writer name="TransitWriter" topic_ref="VehicleTransitTopic"> | ||
<datawriter_qos base_name="VehicleModeling_Library::VehicleTransit_Profile" /> | ||
</data_writer> | ||
</publisher> | ||
</domain_participant> | ||
|
||
<domain_participant name="SubscriberApp" domain_ref="DomainLibrary::VehicleDomain"> | ||
<subscriber name="Subscriber"> | ||
<data_reader name="MetricsReader" topic_ref="VehicleMetricsTopic"> | ||
<datareader_qos base_name="VehicleModeling_Library::VehicleMetrics_Profile" /> | ||
</data_reader> | ||
<data_reader name="TransitReader" topic_ref="VehicleTransitTopic"> | ||
<datareader_qos base_name="VehicleModeling_Library::VehicleTransit_Profile" /> | ||
</data_reader> | ||
</subscriber> | ||
</domain_participant> | ||
</domain_participant_library> | ||
</dds> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Tutorial: Data Persistence | ||
|
||
This code is part of the Connext Application Design tutorial and is included | ||
here in full for convenience. | ||
Please see the tutorial for instructions. | ||
|
||
This code targets Python 3.8 and uses the Connext Python API. | ||
|
||
## How to build | ||
|
||
The example already provides generated types (`VehicleModeling.py`), so nothing | ||
needs to be done for Python applications. | ||
|
||
## How to run | ||
|
||
The publisher can be run as a file or module. The expected output contains a | ||
description of the application. It will end once the vehicle has run out of fuel. | ||
|
||
```console | ||
$ python publisher.py | ||
Running simulation: simulation=Simulation(self._metrics_writer=<rti.connextdds.DataWriter object at 0x7f7e693cdb30>, self._transit_writer=<rti.connextdds.DataWriter object at 0x7f7e697d83f0>, self._vehicle_vin='3P524A8JB256YZOQY', self._vehicle_fuel=100.0, self._vehicle_route=[Coord(lat=10.851231171123665, lon=4.549741897319626), Coord(lat=-19.336436875210726, lon=45.5761709545348), Coord(lat=-28.473080284108043, lon=-3.3714508132107524), Coord(lat=-44.45875114267031, lon=11.536506807784141), Coord(lat=-30.68510788813299, lon=3.7515235253391954), Coord(lat=-45.485688894791096, lon=-19.45044753805537)], self._vehicle_position=Coord(lat=-9.361148743978752, lon=10.532865637410172)) | ||
Vehicle '3P524A8JB256YZOQY' has reached its destination, now moving to a new location... | ||
Vehicle '3P524A8JB256YZOQY' has reached its destination, now moving to a new location... | ||
Vehicle '3P524A8JB256YZOQY' ran out of fuel! | ||
|
||
``` | ||
|
||
The subscriber can be run as a file or a module. The expected output contains a | ||
description of the application, followed by periodic updates on the understanding | ||
of the system. It will run until interrupted. | ||
|
||
```console | ||
$ python subscriber.py | ||
[[ DASHBOARD: 2024-07-11 13:28:39.503181 ]] | ||
Online vehicles: 1 | ||
- Vehicle F01UV8KCSAY5EVBL3: | ||
Fuel updates: 4 | ||
Last known destination: Coord(lat=-29.739379575147705, lon=8.811412382546946) | ||
Last known fuel level: 90.24212596289948 | ||
Offline vehicles: 1 | ||
- Vehicle V93YZUZIYQB71P77Z: | ||
Mean fuel consumption: 2.5009597229252654 | ||
Known reached destinations: 3 | ||
- Coord(lat=-19.42303588068077, lon=4.543146614919191) | ||
- Coord(lat=-23.903966240016082, lon=-1.5759817176247415) | ||
- Coord(lat=-27.18890271220428, lon=-23.879609290719095) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# | ||
# (c) 2024 Copyright, Real-Time Innovations, Inc. All rights reserved. | ||
# | ||
# RTI grants Licensee a license to use, modify, compile, and create derivative | ||
# works of the Software solely for use with RTI products. The Software is | ||
# provided "as is", with no warranty of any type, including any warranty for | ||
# fitness for any purpose. RTI is under no obligation to maintain or support | ||
# the Software. RTI shall not be liable for any incidental or consequential | ||
# damages arising out of the use or inability to use the software. | ||
# | ||
|
||
import os | ||
import sys | ||
from dataclasses import field | ||
from enum import IntEnum | ||
from typing import Optional, Sequence, Union | ||
|
||
import rti.idl as idl | ||
|
||
VIN_LENGTH = 17 | ||
|
||
VIN = str | ||
|
||
|
||
@idl.struct(type_annotations=[idl.final]) | ||
class Coord: | ||
lat: float = 0.0 | ||
lon: float = 0.0 | ||
|
||
|
||
VehicleMetricsTopic = "VehicleMetrics" | ||
|
||
|
||
@idl.struct( | ||
member_annotations={ | ||
"vehicle_vin": [idl.key, idl.bound(VIN_LENGTH)], | ||
"current_route": [idl.bound(100)], | ||
} | ||
) | ||
class VehicleTransit: | ||
vehicle_vin: str = "" | ||
current_position: Coord = field(default_factory=Coord) | ||
current_route: Optional[Sequence[Coord]] = None | ||
|
||
|
||
Percentage = float | ||
|
||
VehicleTransitTopic = "VehicleTransit" | ||
|
||
|
||
@idl.struct( | ||
member_annotations={ | ||
"vehicle_vin": [idl.key, idl.bound(VIN_LENGTH)], | ||
} | ||
) | ||
class VehicleMetrics: | ||
vehicle_vin: str = "" | ||
fuel_level: float = 0.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
# | ||
# (c) 2024 Copyright, Real-Time Innovations, Inc. All rights reserved. | ||
# | ||
# RTI grants Licensee a license to use, modify, compile, and create derivative | ||
# works of the Software solely for use with RTI products. The Software is | ||
# provided "as is", with no warranty of any type, including any warranty for | ||
# fitness for any purpose. RTI is under no obligation to maintain or support | ||
# the Software. RTI shall not be liable for any incidental or consequential | ||
# damages arising out of the use or inability to use the software. | ||
# | ||
|
||
import random | ||
import time | ||
import typing | ||
|
||
import rti.connextdds as dds | ||
|
||
from VehicleModeling import Coord, VehicleMetrics, VehicleTransit | ||
|
||
|
||
def new_route( | ||
n: int = 5, | ||
start: typing.Optional[Coord] = None, | ||
end: typing.Optional[Coord] = None, | ||
): | ||
def new_random_coord(): | ||
return Coord( | ||
(0.5 - random.random()) * 100, | ||
(0.5 - random.random()) * 100, | ||
) | ||
|
||
start = start or new_random_coord() | ||
intermediate = (new_random_coord() for _ in range(n)) | ||
end = end or new_random_coord() | ||
|
||
return [start, *intermediate, end] | ||
|
||
|
||
class PublisherSimulation: | ||
def __init__( | ||
self, | ||
metrics_writer: "dds.DataWriter", | ||
transit_writer: "dds.DataWriter", | ||
): | ||
self._metrics_writer = metrics_writer | ||
self._transit_writer = transit_writer | ||
self._vehicle_vin: str = "".join( | ||
random.choices("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", k=17) | ||
) | ||
self._vehicle_fuel = 100.0 | ||
self._vehicle_route = new_route() | ||
self._vehicle_position = self._vehicle_route.pop(0) | ||
|
||
def __repr__(self): | ||
return ( | ||
f"Simulation(" | ||
f"{self._metrics_writer=}, " | ||
f"{self._transit_writer=}, " | ||
f"{self._vehicle_vin=}, " | ||
f"{self._vehicle_fuel=}, " | ||
f"{self._vehicle_route=}, " | ||
f"{self._vehicle_position=})" | ||
) | ||
|
||
@property | ||
def has_ended(self): | ||
return self._is_out_of_fuel | ||
|
||
@property | ||
def _is_out_of_fuel(self): | ||
return self._vehicle_fuel <= 0.0 | ||
|
||
@property | ||
def _is_on_standby(self): | ||
return not self._vehicle_route | ||
|
||
def run(self): | ||
while not self.has_ended: | ||
self._metrics_writer.write( | ||
VehicleMetrics( | ||
self._vehicle_vin, | ||
self._vehicle_fuel, | ||
) | ||
) | ||
|
||
self._transit_writer.write( | ||
VehicleTransit( | ||
self._vehicle_vin, | ||
current_route=self._vehicle_route, | ||
current_position=self._vehicle_position, | ||
) | ||
) | ||
|
||
time.sleep(1) | ||
|
||
if self._is_on_standby: | ||
print( | ||
f"Vehicle '{self._vehicle_vin}' has reached its destination, now moving to a new location..." | ||
) | ||
self._vehicle_route = new_route(start=self._vehicle_position) | ||
|
||
self._vehicle_position = self._vehicle_route.pop(0) | ||
self._vehicle_fuel -= 10 * random.random() | ||
|
||
if self._is_out_of_fuel: | ||
self._vehicle_fuel = 0.0 | ||
|
||
print(f"Vehicle '{self._vehicle_vin}' ran out of fuel!") | ||
|
||
|
||
def main(): | ||
dds.DomainParticipant.register_idl_type(VehicleMetrics, "VehicleMetrics") | ||
dds.DomainParticipant.register_idl_type(VehicleTransit, "VehicleTransit") | ||
|
||
qos_provider = dds.QosProvider("../VehicleModeling.xml") | ||
|
||
with qos_provider.create_participant_from_config( | ||
"ParticipantLibrary::PublisherApp" | ||
) as participant: | ||
metrics_writer = dds.DataWriter( | ||
participant.find_datawriter("Publisher::MetricsWriter") | ||
) | ||
transit_writer = dds.DataWriter( | ||
participant.find_datawriter("Publisher::TransitWriter") | ||
) | ||
|
||
simulation = PublisherSimulation( | ||
metrics_writer=metrics_writer, transit_writer=transit_writer | ||
) | ||
print(f"Running simulation: {simulation=}") | ||
simulation.run() | ||
|
||
|
||
if __name__ == "__main__": | ||
try: | ||
main() | ||
except KeyboardInterrupt: | ||
pass |
Oops, something went wrong.