Skip to content

Repository files navigation

hla-federepl

A small deps.edn Clojure project for joining an HLA 1516e federation from a REPL, subscribing to interactions, and inspecting received traffic interactively.

RTI dependencies

The HLA 1516e API is declared as the Maven dependency nl.tno/rti1516e.

You may still need an RTI implementation available at runtime, depending on how your local RTI is installed and how RtiFactoryFactory discovers it. If you want to use the vendored Portico jar, include the :portico alias. The user can add a :pitch alias to their ~/.clojure/deps.edn to include the Pitch pRTI jar if they have it installed:

The vendored Portico jar is built from the Yet Analytics Portico fork:

make vendor/portico-local.jar

To force a rebuild:

make vendor-portico

By default this builds yetanalytics/portico at yet_patch_object_subs. You can build from a local checkout or override the source ref/repository:

make vendor-portico PORTICO_SRC=/Users/milt/projects/portico
make vendor-portico PORTICO_REF=my-branch
make vendor-portico PORTICO_REPO_URL=https://github.com/openlvc/portico.git PORTICO_REF=v3.0.0
{:aliases
 {:pitch
  {:extra-paths ["/path/to/prti1516e/lib/prti1516e.jar"
                 "/path/to/prti1516e/lib/prticore.jar"]
   :jvm-opts ["-Djava.library.path=/path/to/prti1516e/lib"]}}}

Start a REPL

clojure -M:repl

To run with the vendored Portico implementation:

clojure -M:portico:repl

Portico also needs a Portico RTI process running. Start it in a separate terminal before connecting from the REPL:

clojure -M:portico:portico-rti

The project-local RTI.rid configures that RTI on loopback TCP and configures federates to connect to the same local endpoint.

To run with the Pitch pRTI implementation:

clojure -M:pitch:repl

From the REPL:

(require '[hla-federepl.core :as hla])

(def system
  (hla/start {:local-settings-designator ""
              :fom-path "/absolute/path/to/fom.xml"
              :federation-name "Federation"
              :federate-name "federepl"
              :interactions ["HLAinteractionRoot.SomeInteraction"]}))

(:config system)
(hla/status system)
(hla/events system)
(hla/latest system)
(hla/event-values system)
(hla/latest-values system)
(hla/subscribe! system "HLAinteractionRoot.AnotherInteraction")
(hla/stop! system)

start does not create or destroy the federation by default, which is usually the safer behavior when attaching to an already-running simulation.

To create the federation if needed:

(hla/start {... :create-federation? true})

To destroy then recreate when possible:

(hla/start {... :recreate-federation? true})

To request federation destruction on shutdown:

(hla/stop! system {:destroy-federation? true})

Run the toy sim federate

Start the RTI process first:

clojure -M:portico:portico-rti

Then run the simulation federate in another terminal:

clojure -M:portico:run-sim --create-federation true

Useful options include:

clojure -M:portico:run-sim \
  --federation-name HlaFedereplSimulation \
  --federate-name hla-federepl-sim \
  --world-size 10 \
  --initial-carrots 10 \
  --initial-rabbits 5 \
  --initial-wolves 3 \
  --step-interval-ms 1000 \
  --max-rabbit-hunger 5 \
  --max-wolf-hunger 5 \
  --state-log-interval-steps 1 \
  --max-steps 20

The runner publishes World, Carrot, Rabbit, and Wolf object instances, sends lifecycle interactions such as EntityCreated, EntityMoved, EntityAte, EntityRemoved, and StepCompleted, and subscribes to InitializeWorld. Pass --wait-for-initialize true to avoid local initialization until an InitializeWorld interaction is received. The runner prints a compact emoji view of the world every simulation step by default; set --state-log-interval-steps to a larger cadence or 0 to disable it. By default, the runner suppresses Portico's portico.lrc logger so Portico LRC logging does not drown out the state visualization. The runner lets the RTI assign object instance names for Portico compatibility; pass --deterministic-object-names true if your RTI supports name reservation and you want names derived from simulation UUIDs.

Send interactions from EDN

start parses the configured FOM and keeps the metadata in the running system. You can then declare and send interactions from ordinary Clojure maps:

(hla/publish-interaction-class! system "HLAinteractionRoot.InitializeWorld")

(hla/send-interaction!
 system
 "HLAinteractionRoot.InitializeWorld"
 {:world-size 10
  :initial-carrots 20
  :initial-rabbits 5
  :initial-wolves 2})

Parameter keys are matched leniently against FOM names. For example, :InitialCarrots, :initial-carrots, and "InitialCarrots" all refer to the same parameter.

For repeated use, build a publisher from a FOM and interaction name:

(def sim-fom (hla/load-fom "dev-resources/HlaFedereplFOM.xml"))

(def send-entity-moved
  (hla/publisher
   sim-fom
   "HLAinteractionRoot.EntityMoved"))

(send-entity-moved
 system
 {:entity-id "rabbit-1"
  :entity-type :rabbit
  :from-position {:x 1 :y 2}
  :to-position {:x 2 :y 2}
  :location-history [{:x 1 :y 2} {:x 2 :y 2}]})

The encoder currently supports HLA primitive encodings, simple data aliases, enumerations, dynamic arrays, one-dimensional fixed arrays with numeric cardinality, and fixed records. Variant records are parsed as unsupported and will produce raw values when encountered in received data.

Received events keep the raw parameter bytes under :parameters and add decoded Clojure data under :values when the interaction and parameter datatypes are defined in the loaded FOM:

(pprint (hla/latest system))
(pprint (hla/latest-values system))

If a parameter cannot be decoded, its decoded value is an opaque wrapper instead of failing the whole interaction decode:

(hla/raw-value? (:vendor-payload (hla/latest-values system)))
(vec (hla/raw-bytes (:vendor-payload (hla/latest-values system))))

That wrapper can be passed back to send-interaction! as a parameter value when you want to forward an unsupported custom value without interpreting it.

Run tests

To run tests against Portico RTI:

make test

License

Copyright © 2026 Yet Analytics, Inc.

Distributed under the Apache License version 2.0.

About

A Clojure REPL for poking around inside HLA simulations.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages