46 explicit SplitMix64(std::uint64_t seed) : state_(seed) {}
198 int id()
const {
return id_; }
208 int flow, seq, src, dst, ttl, hops;
210 double created, firstQueued, expire;
221 mutable double gmSpeed_ = 0;
222 mutable Vec3 gmDir_{1, 0, 0};
223 mutable int mhDir_ = 0;
224 mutable bool rwpPaused_ =
false;
225 std::unique_ptr<anthocnet::core::AntRouterLogic> logic_;
228 double busyUntil_ = 0;
229 std::deque<Pending> pending_;
230 std::set<NodeAddress> everRouted_;
232 mutable std::vector<Leg> legs_;
233 mutable std::size_t routeIdx_ = 0;
234 double battery0_ = -1;
236 double batteryAt_ = 0;
237 double groundMinSinEl_ = 2;
238 bool satellite_ =
false;
303 void addJammingZone(
const std::vector<double>& xy,
double from,
double until,
double vx = 0,
325 double now()
const {
return now_; }
327 std::uint64_t
seed()
const {
return seed_; }
339 int nodeCount()
const {
return static_cast<int>(nodes_.size()); }
345 bool linkUp(
int a,
int b)
const {
return linkUpAt(a, b, now_); }
347 const Node&
node(
int i)
const {
return *nodes_[i]; }
349 const std::vector<Flow>&
flows()
const {
return flows_; }
353 const std::vector<LogEvent>&
log()
const {
return log_; }
363 const std::vector<std::uint8_t>&
antBytes(std::uint64_t
id)
const;
371 double range()
const {
return range_; }
391 std::function<void()> fn;
394 bool operator()(
const Scheduled& a,
const Scheduled& b)
const {
395 return a.t > b.t || (a.t == b.t && a.seq > b.seq);
399 void schedule(
double t, std::function<
void()> fn);
400 void emit(
double t,
Ev kind,
int node,
int peer,
int a,
int b,
double v);
403 void extendLegs(
Node& n,
double until)
const;
404 void armTimers(
Node& n);
405 Vec3 positionAt(
int node,
double t)
const;
407 Vec3 velocityAt(
int node,
double t)
const;
408 bool linkUpAt(
int a,
int b,
double t)
const;
409 bool lineOfSight(
const Vec3& a,
const Vec3& b)
const;
412 void helloTimer(
int node);
413 void proactiveTimer(
int node);
414 void retryTimer(
int node);
415 void flowTick(
int flow);
416 double jittered(
Node& n,
double base,
bool first);
419 void execute(
Node& n,
const std::vector<anthocnet::core::RouteDecision>& ds);
421 void recvAnt(
int node,
int from,
const std::vector<std::uint8_t>& bytes);
422 void routeData(
Node& n, Node::Pending p,
int prevHop);
423 void sendData(
Node& n, Node::Pending p,
int next);
424 void recvData(
int node,
int from, Node::Pending p);
425 void enqueue(
Node& n, Node::Pending p);
426 void flushQueue(
Node& n, NodeAddress dst);
429 double txDuration(std::size_t bytes)
const {
return bytes * 8.0 / bitrate_; }
430 double propagation(
int a,
int b,
double t)
const;
436 Vec3 area_{1000, 1000, 0};
439 int blocksX_ = 4, blocksY_ = 4;
440 double streetWidth_ = 20;
441 std::set<std::pair<int, int>> isl_;
442 double bitrate_ = 2e6;
444 std::vector<std::unique_ptr<Node>> nodes_;
445 std::vector<Flow> flows_;
446 std::priority_queue<Scheduled, std::vector<Scheduled>, Later> events_;
447 std::uint64_t seq_ = 0;
449 bool started_ =
false;
450 std::vector<LogEvent> log_;
451 std::uint64_t antTx_ = 0;
452 std::deque<std::pair<std::uint64_t, std::vector<std::uint8_t>>>
456 std::vector<double> xy;
460 std::vector<Zone> zones_;
462 std::vector<double> xy;
463 double from, until, vx, vy;
465 std::vector<JamZone> jams_;
467 bool jammed(
const Vec3& a,
const Vec3& b,
double t)
const;
469 double rangeFactorAt(
const Vec3& p)
const;
471 void drainBattery(
Node& n,
double txSeconds);
472 void batteryTimer(
int node);
474 bool groundSees(
int g,
int s,
double t)
const;
477 static constexpr double kTimerJitter = 0.05;
478 static constexpr double kQueueTimeout = 3.0;
479 static constexpr double kReconvHoldCap = 0.2;
480 static constexpr double kRetryInterval = 0.25;
481 static constexpr std::size_t kQueueLen = 64;
482 static constexpr int kTtl = 64;
483 static constexpr std::size_t kDataBytes = 64 + 28;
484 static constexpr int kMacRetries = 7;
487 static constexpr double kIdleW = 0.82;
488 static constexpr double kTxW = 1.14;
One AntHocNet node: the core logic plus the adapter state around it.
double residualEnergyFraction() const override
IEnergy (#575, #145): the battery's residual fraction, NaN without a battery.
int uniformInt(int n) override
IRng: uniform integer in [0, n).
void onRouteChanged(NodeAddress dest, NodeAddress nb, bool added) override
IRouterObserver: report-only – route changes feed the event log.
bool self(anthocnet::core::Kinematics &out) const override
IKinematics (ADR-0025): position and the current leg's velocity.
anthocnet::core::AntRouterLogic & logic()
The core state machine (valid after World::start()).
int id() const
This node's address (its index in the World).
Node(World &w, int id, std::uint64_t seed)
Created by World::addNode(); seed derives the node's streams.
double uniform() override
IRng: this node's own stream (independent of every other node's).
anthocnet::core::Time now() const override
IClock: the world's simulated time.
const anthocnet::core::AntRouterLogic & logic() const
The core state machine, read-only (inspection).
SplitMix64: tiny, portable, and bit-identical on every platform (integer arithmetic only; the double ...
double uniform()
Uniform double in [0, 1), from the top 53 bits.
double uniform(double lo, double hi)
Uniform double in [lo, hi).
std::uint64_t next()
Next raw 64-bit value.
SplitMix64(std::uint64_t seed)
A stream starting from seed (every seed is valid).
int uniformInt(int n)
Uniform integer in [0, n); 0 when n <= 0.
The whole simulation: nodes, radio, mobility, traffic and the event queue.
void start()
Build the nodes' core logic and arm their timers and the flows.
void addIslLink(int a, int b)
Add an inter-satellite link (ChannelKind::Isl, Mixed).
void setNodeUp(int node, bool up)
Switch node off (its held packets are dropped) or back on.
std::uint64_t seed() const
The seed this world was built from.
int urbanBlocksX() const
Street grid blocks along x (Urban).
Vec3 area() const
Field size in metres.
void setIslChannel()
Links only where addIslLink() says, delay tracking distance.
void setNodeRange(int node, double range)
Give node its own radio range in metres (#568: a device class).
void setGroundStation(int node, double minElevationDeg)
#575: make node a ground station on the satellite (Isl) channel.
bool nodeUp(int node) const
Whether node is switched on.
double batteryLeft(int node)
#575: energy left in node's battery (J), or -1 without one.
void addJammingZone(const std::vector< double > &xy, double from, double until, double vx=0, double vy=0)
#582: a jamming zone.
void setUrbanChannel(double range, int blocksX, int blocksY, double streetWidth)
Unit disk cut by the buildings of a blocksX x blocksY street grid.
void setBattery(int node, double joules)
#575: give node a battery of joules.
void setLossProbability(double p)
Independent per-reception loss probability (default 0).
static std::string formatEvent(const LogEvent &e)
One trace line per logged event (the parity format).
void setMixedChannel(double range)
#582: ground, air and space nodes in one world.
void clearLog()
Forget the logged events (the front end drains them every frame).
const std::vector< std::uint8_t > & antBytes(std::uint64_t id) const
X-ray (#637): the serialized bytes of ant transmission id – the id-th TxAnt event since start(),...
void setDiskChannel(double range)
Unit-disk links of radius range metres.
std::vector< double > zonesFlat() const
#575: the attenuation zones as [factor, n, x0, y0, ... x(n-1), y(n-1), ...].
void addAttenuationZone(const std::vector< double > &xy, double factor, double top=30)
#575: inside the polygon xy (x0, y0, x1, y1, ...) and below top metres, radio range is scaled by fact...
double range() const
Radio range in metres (Disk, Urban).
static constexpr std::size_t kXrayRing
X-ray (#637): how many ant transmissions the ring keeps.
int pendingCount(int node) const
Data packets node holds waiting for a route.
void scheduleNodeUp(int node, double t, bool up)
#582: a scripted event – switch node off (up = false) or back on at simulated time t (an aftershock,...
double nodeRange(int node) const
double now() const
Current simulated time (s).
int urbanBlocksY() const
Street grid blocks along y (Urban).
const std::vector< Flow > & flows() const
The flows and their running totals.
std::uint64_t antTransmissions() const
Ant transmissions so far (control overhead).
double streetWidth() const
Street width in metres (Urban).
void advanceTo(double t)
Process every event up to simulated time t (starts if needed).
bool setLinkMetric(const std::string &name)
#579: the link metric every node is built with, by registry name ("classic", "sinr",...
ChannelKind channel() const
The link rule in use.
int addFlow(int src, int dst, double rate, double start, double stop)
Add a CBR flow; returns its index.
anthocnet::core::Config & config()
The protocol Config every node is built with – the core defaults.
int nodeCount() const
Number of nodes.
void setMobility(int node, const Mobility &m)
node's radio range: its own, else the world range().
void setSatellite(int node)
#582: mark node as a satellite on the Mixed channel.
const Node & node(int i) const
Node i (for read-only inspection of its core state).
void setBitrate(double bps)
Transmitter bit rate (default 2 Mbit/s).
bool linkUp(int a, int b) const
Whether a and b can hear each other now.
Vec3 position(int node) const
Where node is now.
void cutIslLink(int a, int b)
Remove an inter-satellite link.
void moveNode(int node, double x, double y, double z)
Drag node to (x, y, z) and pin it there (it stops moving).
std::vector< double > jamZonesFlat() const
#582: the jamming zones active now, where they are now, as [n, x0, y0, ... x(n-1),...
const std::vector< LogEvent > & log() const
Events since the last clearLog().
World(std::uint64_t seed)
An empty world; seed derives every random stream in it.
void setArea(double x, double y, double z)
Field size in metres (z > 0 enables altitude).
int addNode(double x, double y, double z)
Add a node at (x, y, z); returns its address.
Source of simulation time (seconds).
This node's residual energy (#145): the fraction of its initial battery left, 0..1.
This node's own position and velocity (#573, ADR-0025).
Optional observer the core notifies of routing events (item 15).
Built-in teaching scenarios: one per network family, shaped like the repo's presets but scaled down t...
MobilityKind
How a node moves. Values are part of the JS API (setMobility's kind).
@ Manhattan
street grid: straight 0.5, left/right 0.25 at each corner
@ Orbit
circular orbit around the field's centre (satellites)
@ GaussMarkov
correlated speed and heading, 1 s steps, optionally 3-D
@ Static
never moves (until dragged)
@ Route
#575: a fixed route (a bus line): waypoint to waypoint, looping
@ RandomWaypoint
straight legs to uniform waypoints, optional pause
Vec3 orbitPosition(const Mobility &m, const Vec3 ¢re, double t)
Where an Orbit puts a node at time t (centre = the field's centre, z = 0).
Ev
Event kinds of the log the front end animates and the parity test diffs.
@ NodeDown
node switched off
@ RouteAdd
node; peer=next hop, a=destination
@ Drop
node; a=flow, b=seq, peer=DropReason
@ Deliver
node = destination; a=flow, b=seq, v=end-to-end delay
@ TxData
node -> peer; a=flow, b=seq, v=arrival time
@ Queue
node; a=flow, b=seq, peer=destination
@ RxAnt
node received from peer; a=AntType, b=dir
@ TxAnt
node -> peer (-1 = broadcast); a=AntType, b=dir, v=arrival time
@ TxFail
node -> peer unicast failed (out of range)
@ RouteDel
node; peer=next hop, a=destination
DropReason
Why a data packet was lost (the peer field of an Ev::Drop event).
@ HoldCap
a reconvergence hold outlived ReconvHoldCap (200 ms)
@ RepairDiscard
a local repair expired: the core's DiscardPending
@ Ttl
hop limit reached (a loop)
@ NodeOff
the holding or receiving node was switched off
@ QueueTimeout
waited QueueTimeout (3 s) for a route, or queue full
double detSin(double x)
sin / cos from arithmetic only (range reduction + Taylor series), so the native and WASM builds compu...
ChannelKind
Which link rule the teaching radio uses.
@ Disk
linked iff within range()
@ Mixed
#582: ground, air and space in one world (see setMixedChannel)
@ Urban
within range() and no building on the line of sight
@ Isl
linked iff an inter-satellite link was added (and not cut)
double Time
Simulation time, in seconds.
std::int32_t NodeAddress
Network-layer node address.
A constant-bit-rate data flow and its running totals.
double rate
packets per second
double stop
no packets after this (s)
int sent
packets originated
double start
first packet (s)
double delaySum
sum of end-to-end delays of delivered packets (s)
int delivered
packets that reached dst
One straight leg of a node's trajectory: p0 at t0 to p1 at t1.
double t1
end time (s); 1e18 = forever
Vec3 p1
position at t1 (linear in between)
One entry of the event log (see Ev for what each field means per kind).
int peer
the other node, -1 for broadcast, or a DropReason
int b
kind-specific (AntDirection, sequence number)
int node
where it happened
int a
kind-specific (AntType, flow, destination)
double v
kind-specific (arrival time, end-to-end delay)
double t
simulated time (s)
A node's mobility model and its parameters.
MobilityKind kind
which model
double orbitRate
Orbit: angular speed (rad/s)
double orbitInc
Orbit: inclination (rad)
double orbitRaan
Orbit: right ascension of the ascending node (rad)
bool threeD
Gauss-Markov: also move in z.
double gmAlpha
Gauss-Markov: memory (0 = random walk, 1 = straight line)
double speedMin
RWP / Manhattan: leg speed lower bound (m/s)
double gmMeanSpeed
Gauss-Markov: mean speed (m/s)
double pause
RWP: pause at each waypoint (s)
double speedMax
RWP / Manhattan: leg speed upper bound (m/s)
double orbitPhase
Orbit: argument of latitude at t = 0 (rad)
std::vector< Vec3 > route
Route: waypoints, driven in order at speedMin, looping.
double orbitRadius
Orbit: distance from the field's centre (m)
A position in metres (z = altitude; 0 on planar worlds).
Complete, copyable description of an ant packet.
Maps an observation to a pheromone (goodness; higher == better).
A node's position (m) and velocity (m/s) in the adapter's Cartesian frame (ADR-0025).