Skip to content

j1939.hpp#

ROS/acres_sim/include/acres_sim/j1939.hpp Generated

SAE J1939 / ISO 11783 (ISOBUS) encoding of the game's CAN protocol (AcresRlBridge.h, -RlCan= / -RlCanUdp=): the C++ port of the Python module acres_sim.j1939 (installed with this package), function for function and bit for bit (test/test_j1939.cpp round trips, test/test_j1939_golden.py compares both on the same inputs).

29-bit identifier = priority << 26 | PGN << 8 | source address; for PDU1 PGNs (PF byte < 0xF0) the low byte of the PGN field (PS) carries the destination address. Multi-byte fields are little-endian; 0xFF bytes mean "not available". Controller (source 0x2A) -> tractor, 10 Hz: Guidance System Command (0xAC00), TSC1 (0), XBR (0x0400), Proprietary A (0xEF00). Tractor -> controller every 0.1 s of simulation time: EEC1 (0xF004), WBSD (0xFE48), Guidance Machine Status (0xAD00), Proprietary B 0xFF10..0xFF18 and "observation complete" 0xFF1F (sent last).

Header only, no ROS: controllers written in C++ can include it on their own.

Name Type Unit Default Description
kPgnLockstepBarrier constexpr uint32_t 0xFF1E Lockstep barrier (simulator only, not a tractor message): from 0x80 at priority 7 (id 0x1CFF1E80) after every frame of a step request; data = the world step reached, uint64 little-endian (the step reply's "barrier").
kImplements constexpr const char* Implement kinds of the 0xFF18 frame (AcresSim::EImplementKind); 0xFF = none.

pgn_name#

Name of a PGN ("GSC", "EEC1", ..., or "PGNxxxxx").

inline std::string pgn_name(uint32_t pgn) ;

make_id#

29-bit identifier. For PDU1 PGNs (PF < 0xF0) destination goes in the PS byte.

Argument Description
priority 0..7.
pgn Parameter group number.
source Source address.
destination Destination address (PDU1 only).

Returns: The identifier.

inline uint32_t make_id(uint32_t priority, uint32_t pgn, uint32_t source, uint32_t destination = kGlobal) ;

parse_id#

Splits an identifier; the destination is 0xFF for PDU2 (broadcast) PGNs.

Argument Description
can_id 29-bit identifier.

Returns: Priority, PGN, source, destination.

inline Id parse_id(uint32_t can_id) ;

py_round#

int(round(v)) of Python: round half to even (nearbyint in the default rounding mode); NaN gives 0.

inline int64_t py_round(double v) ;

py_mod#

Python's float modulo (the result takes the sign of the divisor).

inline double py_mod(double a, double b) ;

na#

Eight "not available" bytes.

inline std::array<uint8_t, 8> na() ;

steer_to_curvature_km#

Bicycle model: curvature (1/km, positive left) of a steering angle (rad, positive left).

inline double steer_to_curvature_km(double steer_rad, double wheelbase_m) ;

curvature_km_to_steer#

Steering angle (rad) of a curvature (1/km).

inline double curvature_km_to_steer(double curv_km, double wheelbase_m) ;

encode_gsc#

Guidance System Command to the tractor 0x80.

Argument Description
curvature_km Commanded curvature, 1/km, positive left.
steer Steering command status "intended to steer" (otherwise the wheels are centred).

Returns: The frame.

inline Frame encode_gsc(double curvature_km, bool steer = true) ;

decode_curvature#

Curvature (1/km) of a GSC or GMS frame.

inline double decode_curvature(const uint8_t* data) ;

encode_tsc1_torque#

TSC1 to the engine 0x00 in torque-control mode: requested torque % = throttle x 100 (0 = no override).

Argument Description
throttle Pedal 0..1.

Returns: The frame.

inline Frame encode_tsc1_torque(double throttle) ;

encode_xbr#

XBR to the brakes 0x0B: brake pedal 0..1 as a deceleration demand (full brake = -4 m/s2).

Argument Description
brake Pedal 0..1.

Returns: The frame.

inline Frame encode_xbr(double brake) ;

decode_xbr#

Decodes an XBR frame.

inline Xbr decode_xbr(const uint8_t* data) ;

encode_control#

Proprietary A 0x01: diff lock 0/1/2 (0xFF keep), harvester 0/1 (0xFF keep), reset to the staged pose, place the staged workers (their count; nothing leaves them), and with the reset clear the field under the pose.

Argument Description
difflock 0 off, 1 rear, 2 all, 0xFF keep.
harvester 0 off, 1 on, 0xFF keep.
reset Reset to the pose staged by encode_reset_pose.
place_workers Workers to place (staged by encode_worker), or nothing.
restore_field With the reset, clear the field under the pose.

Returns: The frame.

inline Frame encode_control(int difflock = 0xFF, int harvester = 0xFF, bool reset = false, std::optional<int> place_workers = std::nullopt, bool restore_field = false) ;

encode_reset_pose#

Proprietary A 0x10, 0x11, 0x12: the pose (world m, Unreal yaw deg) and start speed (m/s) of the next reset.

Argument Description
x World X, m (east).
y World Y, m (south).
yaw_deg Unreal yaw, deg.
speed Start speed, m/s.

Returns: Three frames.

inline std::vector<Frame> encode_reset_pose(double x, double y, double yaw_deg, double speed) ;

encode_worker#

Proprietary A 0x21: stage worker index (0-7) at world (x, y) m.

inline Frame encode_worker(int index, double x, double y) ;

encode_hud#

Proprietary A 0x30: return shown on the HUD, success rate % (nothing = not shown).

inline Frame encode_hud(double reward, std::optional<double> success_pct = std::nullopt) ;

decode_prop_a#

Decodes a Proprietary A payload (8 bytes).

inline PropA decode_prop_a(const uint8_t* data) ;

encode_action#

The command frames of one action.

Argument Description
steer_rad Steering angle, rad, positive left.
pedal -1..1 (> 0 throttle, < 0 brake).
difflock 0/1/2.
wheelbase_m Wheelbase for the curvature, m.

Returns: GSC, TSC1, XBR and the control frame.

inline std::vector<Frame> encode_action(double steer_rad, double pedal, int difflock, double wheelbase_m) ;

encode_observation#

The frames the game sends every 0.1 s for an observation (mirrors FAcresRlBridge::SendCan).

Argument Description
o The observation.
wheelbase_m For the estimated curvature.
sequence Observation counter.
distance_m WBSD distance, m.

Returns: EEC1, WBSD, GMS, the Proprietary B frames and ObsDone, in that order.

inline std::vector<Frame> encode_observation(const Observation& o, double wheelbase_m, int sequence = 0, double distance_m = 0.0) ;

describe#

One decoded line, e.g. "0CAC802A [8] 7C 7D FD FF FF FF FF FF GSC 2A->80 curvature=+1.00/km (+0.2 deg) steer".

Argument Description
can_id 29-bit identifier.
data Data bytes.
wheelbase_m For the steering angle of a curvature.

Returns: The text (the same as the Python module's describe()).

inline std::string describe(uint32_t can_id, const std::vector<uint8_t>& data, double wheelbase_m = 2.6416) ;

Frame#

struct Frame

One frame: 29-bit identifier (without the EFF flag) and 8 data bytes.

Id#

struct Id

Fields of an identifier.

Xbr#

struct Xbr

XBR fields.

PropA#

struct PropA

A decoded Proprietary A payload.

PropA::type_name#

Python's decode_prop_a "type" string.

std::string type_name() const ;

Type#

enum class Type

Message selected by byte 0.

Value Description
kControl
kResetX
kResetY
kResetYawSpeed
kWorker
kHud
kUnknown

Observation#

struct Observation

The tractor's observation (keys and units of the JSON protocol, AcresRlBridge.h).

ObservationAssembler#

class ObservationAssembler

Collects the tractor's frames into an observation: feed() returns it when the "observation complete" frame (0xFF1F) arrives and the frames of every required part (pose, motion, slip, soil, LiDAR, state, engine speed) have been seen.

ObservationAssembler::ObservationAssembler#

Argument Description
wheelbase_m Wheelbase, m (kept for describe-style conversions).
explicit ObservationAssembler(double wheelbase_m = 2.6416) : wheelbase_m_(wheelbase_m) ;

ObservationAssembler::feed#

Feeds one frame.

Argument Description
can_id 29-bit identifier.
data 8 data bytes.

Returns: The complete observation, or nothing.

std::optional<Observation> feed(uint32_t can_id, const uint8_t* data) ;

ObservationAssembler::wheelbase_m#

The wheelbase given at construction, m.

double wheelbase_m() const ;