pamoja for TypeScript - v0.2.0
    Preparing search index...

    Module @pamoja/sim

    Ergonomic facade over the generated simulation binding.

    Drive a whole node with no hardware attached: a sensor that drifts, a replay of a real capture, an actuator that records what it was told, and a robot that moves only in arithmetic. A lossy link is Transport.degraded, since it wraps a transport rather than standing alone.

    @pamoja/sim

    Noisy and replay sensors, a recording actuator, a simulated robot that dead-reckons its pose, and a link that loses sends on a pattern. One capability of pamoja, one memory-safe Rust core with bindings for TypeScript, Python, and C#.

    read the guide documentation API reference

    npm install @pamoja/sim
    

    This pulls in @pamoja/native, the compiled engine. npm install pamoja is the whole framework in one package.

    The test that runs in CI, spliced here as it ran.

    From bindings/node/guides/sim.ts:

    import { Transport } from '@pamoja/core'
    import { LoopbackBroker } from '@pamoja/loopback'
    import { RecordingActuator, Replay, SimulatedRobot, SimulatedSensor } from '@pamoja/sim'

    async function main() {
    // The clear distance ahead, in meters, replayed from an earlier survey of the row, so
    // every run sees the same row.
    const ahead = new Replay([4, 3, 1.5, 0.5])
    // The drive keeps the commands it is given instead of turning a motor.
    const drive = new RecordingActuator()
    // The rover's pose comes from integrating each command over half a second.
    const dt = 0.5
    const rover = new SimulatedRobot(dt)
    // The soil probe reads around 31 percent, drying half a point a reading, with a wobble
    // drawn from a seed, so the same seed gives the same readings every run.
    const soil = new SimulatedSensor(31, -0.5, 0.3, 7)
    // The radio loses every third report on its way to the base.
    const radio = Transport.degraded(new LoopbackBroker().rung(), { dropEvery: 3 })
    await radio.connect()

    const moisture: number[] = []
    let delivered = 0
    for (;;) {
    // A replay that has handed back every reading reports that it is closed.
    let clear: number
    try {
    clear = await ahead.read()
    } catch (error) {
    console.log(`ahead ran out after ${moisture.length} readings: ${(error as Error).message}`)
    break
    }
    const [speed, turn] = clear > 1 ? [1, 0] : [0, 1]
    await drive.apply(speed)
    await rover.apply({ vx: speed, vy: 0, omega: turn })
    const wet = await soil.read()
    const elapsed = moisture.length * dt
    moisture.push(wet)
    const report = wet.toFixed(1)
    const sent = await radio.send('vineyard/row-4/soil', report).then(
    () => true,
    () => false,
    )
    if (sent) delivered += 1
    console.log(
    `${elapsed.toFixed(1)} s ${clear.toFixed(1)} m clear:` +
    ` drive ${speed.toFixed(1)}, turn ${turn.toFixed(1)}, soil ${report}`,
    )
    }

    // The drive kept every command, which is how a test says what the loop decided rather
    // than only what it ended up doing.
    const commands = await drive.commands()
    console.log(`drive recorded ${commands.map((command) => command.toFixed(1)).join(', ')}`)

    // Three half-second commands at 1 m/s reach 1.5 m along x. The last turns on the spot
    // at 1 rad/s for half a second, which moves the rover nowhere.
    const pose = await rover.pose()
    console.log(
    `rover ended at x ${pose.x.toFixed(1)} m, y ${pose.y.toFixed(1)} m,` +
    ` heading ${pose.theta.toFixed(1)} rad`,
    )

    // A second probe with the same seed reads exactly the same values.
    const twin = new SimulatedSensor(31, -0.5, 0.3, 7)
    const again: number[] = []
    for (let read = 0; read < moisture.length; read += 1) {
    again.push(await twin.read())
    }
    const same = again.every((value, index) => value === moisture[index])
    console.log(`soil a probe with the same seed read ${same ? 'the same' : 'different'} ${again.length} values`)
    console.log(`radio delivered ${delivered} of ${moisture.length} soil reports and lost the third`)

    return { commands, pose, same, delivered }
    }

    main()
    Language Package Reference
    Rust pamoja-sim reference, docs.rs, install
    TypeScript @pamoja/sim reference, install
    Python pamoja-sim reference, install
    C# Pamoja.Sim reference, install

    MIT

    RecordingActuator
    Replay
    SimulatedRobot
    SimulatedSensor
    Pose
    Twist