Skip to content

Add an Implement#

This page gives the procedure to add an implement for the Maxxum, from the source asset to the tests and the documentation. Read Implement Mechanics and the Implement Catalog first.

Before You Start#

  • Build the game and the editor. Refer to Build the Game.
  • Install Blender 5.2.2. The source assets are Blender files.
  • Download the source asset package with Git LFS:

    git lfs pull --include="Acres/Raw/farm-equipment/**"
    
  • Read the Coding and Naming Conventions.

An implement has an identifier in lower case with underscores, for example disc_harrow. All files of the implement use this identifier. The procedure has six parts. Each part has a check, and you must not continue while a check fails.

Part Result Location
Source asset Blender file, FBX file, textures and mechanics.json Acres/Raw/farm-equipment/<id>/
Import Skeletal mesh, materials and rig map /Game/FarmEquipment/<id>/, Acres/Content/Simulation/rigs/<id>.json
Model Mechanics of the implement Acres/Source/Acres/AcresImplementModel.h and .cpp
Data file Parameters of the implement Acres/Content/Simulation/implements/<id>.json
Game Selection, keys, HUD, session log AcresVehicle.cpp, AcresHud.cpp, AcresSession.cpp
Tests and documentation Checks and pages Tools/ImplementModel/, Documentation/

The Source Asset Package#

The folder Acres/Raw/farm-equipment contains the source assets of the vehicles and the implements.

Item Function
<id>/<id>.blend The Blender file with the mesh, the rig and the packed textures. It is the authoritative source of the rig.
<id>/<id>.fbx The skeletal mesh for the import.
<id>/textures/ The colour textures.
<id>/mechanics.json The mechanics data: mass, mount, bones, controls, hydraulic cylinders, sockets and rigid bodies.
<id>/validation.json, <id>/preview.png The validation report and a render.
catalog.json The list of all assets. scripts/build_catalog.py writes it from the mechanics.json files.
scripts/assetlib.py Shared functions of the Blender scripts.
scripts/validate_equipment.py Examines each Blender file: skinning, controls, cylinder pins and joints.
scripts/mechanics.py, scripts/test_mechanics.py An offline mechanics library and its tests. The game does not use the library.
scripts/coupled_dynamics.py The offline solver of the demonstration scenes in motion/.
scripts/import_unreal.py An optional import script of the package. Do not use it. The project tools replace it.

A Blender file must obey these rules. The export tool depends on them.

  • The armature has the name <id>_RIG. The frame is FLU in metres: X forward, Y left, Z up.
  • The origin of a mounted implement is on the ground below the lower hitch pins.
  • Each mesh vertex has one bone with the weight 1. The parts are rigid.
  • Each moving part has a control. A control is a custom property of the armature, for example boom_deg.
  • Scripted drivers connect the controls to the bones. Names that end in _deg are degrees, and names that end in _m are metres.
  • A hydraulic cylinder uses the constraints Copy Location and Damped Track to stay on its two pins.

Add the Source Asset#

  1. Make the folder Acres/Raw/farm-equipment/<id>/ with the Blender file, the FBX file and the textures.

  2. Write mechanics.json. Use the file of a similar implement as the template.

    The file must contain id, title, mass_kg, mount, bones, controls, hydraulics, sockets_flu_m and rigid_bodies. The values of mount are category_II_three_point, custom_loader_subframe, custom_rigid_subframe and drawbar_trailed.

  3. Examine the asset in Blender.

    cd Acres/Raw/farm-equipment
    blender -b --factory-startup --python-exit-code 1 --python scripts/validate_equipment.py -- <id>
    

    Expected Result

    The script writes <id>/validation.json with "passed": true.

  4. Write the catalog again.

    python3 scripts/build_catalog.py
    

    Expected Result

    catalog.json contains an entry with the identifier of the new asset.

  5. Run the tests of the offline mechanics library.

    python3 scripts/test_mechanics.py
    

    Expected Result

    Ran 8 tests in 0.004s
    
    OK
    

Import the Asset into Unreal#

Two tools in Tools/ACRE/Vehicles do the import. FBX does not contain the drivers and the constraints of Blender. export_rig_map.py thus reads them from the Blender file and writes a rig map. The game evaluates the rig map at run time.

Tool Program Output
export_rig_map.py Blender Rig map Acres/Content/Simulation/rigs/<id>.json, a centimetre copy of the FBX file and a material list in Acres/Saved/FarmEquipment/<id>/
import_farm_equipment.py Unreal Editor command Skeletal mesh /Game/FarmEquipment/<id>/SK_<id>, its skeleton, textures and material instances
prep_npc_cars.py Blender Not for implements. It prepares the car models of the farm traffic.

The tools read the list of assets from catalog.json. The set NOT_IN_GAME in the two tools excludes assets, for example the combine harvester. The centimetre copy is necessary. Unreal converts the units of an FBX file with a scale of 100 on the root bone, and that scale breaks attached parts.

CAUTION

Close the editor before you run the import. An open editor can corrupt the assets that the import saves.

  1. Write the rig map with Blender.

    blender -b --factory-startup --python Tools/ACRE/Vehicles/export_rig_map.py -- <id>
    

    Expected Result

    The file Acres/Content/Simulation/rigs/<id>.json exists. It contains the controls, the bones, the sockets and the test poses.

  2. Import the mesh with the editor command.

    ACRES_ONLY=<id> "$UE/Engine/Binaries/Linux/UnrealEditor-Cmd" "$PWD/Acres/Acres.uproject" \
        -run=pythonscript -script="$PWD/Tools/ACRE/Vehicles/import_farm_equipment.py" \
        -unattended -nosplash -nullrhi
    

    Expected Result

    The log contains ACRES_FARM_IMPORT <id> passed=True and ACRES_FARM_IMPORT_DONE. The file Acres/Saved/FarmEquipment/import_report.json contains the measured errors.

The import examines the result. It compares the bone names with the catalog and the rig map. It compares the bone positions and the bounds with the Blender data after the conversion to Unreal coordinates. The conversion is \(100\,(x, -y, z)\) in centimetres. A rotation about the axis \(\mathbf{n}\) becomes a rotation about \((-n_x, n_y, -n_z)\). The folder /Game/FarmEquipment is in DirectoriesToAlwaysCook of Acres/Config/DefaultGame.ini, thus the packaged game contains the new mesh.

The Equipment Rig and the Rig Self-Test#

UAcresRigComponent in AcresRig.h loads a rig map and its mesh. The implement model sends control values, and the component moves the bones. A rig map contains these items.

Key Content
controls Name, unit, range and default of each control.
bones Parent, rest frame, driver channels and pin constraint of each bone.
channels The driver expression of one bone channel and its variables.
sockets_m Named attachment points, for example lower_left and top_link.
hydraulics, linkages The pins and lengths of cylinders and connecting rods.
test_poses Control values and the bone matrices that Blender computed for them.
mesh The Unreal path of the skeletal mesh.

The option -RigSelfTest evaluates each test pose of each rig map and compares the result with the Blender matrices. A rig passes when the largest position error is below 0.1 mm and the largest angle error is below 0.01°.

  1. Package the game again. Refer to Build the Game.

  2. Run the rig self-test.

    Packaged/Linux/Acres.sh -VehicleDemo -RigSelfTest -RenderOffscreen
    

    Expected Result

    The log contains one line for each rig map and a summary. This is the output for the shipped rigs:

    ACRES_RIG_SELFTEST chisel_plow PASS poses=7 bones=10 max_position_error_mm=0.00011 max_angle_error_deg=0.000004
    ACRES_RIG_SELFTEST square_baler PASS poses=10 bones=13 max_position_error_mm=0.00058 max_angle_error_deg=0.000168
    ACRES_RIG_SELFTEST_DONE passed=10 of 10
    

A driver expression can use the arithmetic operators, the constants pi and e, and the functions of the table below. The rig map does not load when an expression uses a different function.

Group Functions
Limits min, max, abs, floor, ceil
Trigonometry sin, cos, tan, asin, acos, atan, atan2, radians, degrees
Powers sqrt, exp, log, pow

Extend the Model Code#

The implement model is an engine-free model. Do not use Unreal types in AcresImplementModel.h, AcresImplementCoupling.h and AcresFieldWorkModel.h. Cite the publication of each force model in a comment, and use SI units in the names.

  1. Add a value to EImplementKind before Count. Add the identifier in ImplementKindId.

  2. Add a parameter structure if the implement has a new mechanism. Add it to FImplementParameters.

  3. Set the mass, the centre of mass, the inertia and the tool layout in MakeImplementParameters.

  4. Register each parameter in ImplScalarKeys, ImplIntKeys or ImplBoolKeys with its file unit and its limits.

  5. Add the controls of the operator to FImplementControls and the states to FImplementState.

  6. Write the step function. StepImplement selects it by the kind.

    A mounted implement with tines, discs, rollers or drill rows needs no new step function. ImplStepThreePoint computes these tools from their counts. A different machine needs its own function, for example ImplStepBaler.

  7. Fill all applicable fields of FImplementOutput: the wrench, the PTO, the hydraulics, the mass and the flags.

  8. Add the rig controls in ImplementRigControls. Use the control names of mechanics.json.

  9. Set the initial state in ResetImplement and the default controls in ImplementDefaultControls.

  10. If the implement has a depth setting, extend ImplementDepthRangeM and ImplementControlsForDepth.

Obey these rules of the model.

  • The step function must not allocate memory. The size of each array is a constant, for example MaxImplementTines.
  • A soil failure force must use the fade factor of the speed. A static bearing force must not.
  • ExternalForceN contains no weight. The pawn adds the mass to the chassis body.
  • A new payload must change MassKg, ComM and PayloadKg in the same step.

The Data File#

Each implement has a file Acres/Content/Simulation/implements/<id>.json. The game reads it in SetupImplement and applies the keys on top of the code defaults. The tool writes the files from the code defaults, thus the data and the code agree.

  1. Add the block of the new implement to Relevant and a source note to SourceNote in Tools/ImplementModel/implement_data.cpp.

  2. Build the tool.

    Tools/ImplementModel/build.sh
    
  3. Write the data files.

    "${TMPDIR:-/tmp}/acres-implement-model/implement_tool" write-json Acres/Content/Simulation/implements
    

    Expected Result

    The folder contains <id>.json. The files of the other implements do not change.

The game stops with the message rejected <key> = <value> when a file has an unknown key or a value out of its limits.

Connect the Implement to the Game#

The pawn AAcresVehiclePawn owns the implement. Most of the connection is generic, but some lists name each implement.

Item File Function or Location
Message of the identifier check AcresVehicle.cpp LoadImplementConfiguration
Name on the HUD AcresVehicle.cpp ImplementLabel
PTO standard and tool zone AcresVehicle.cpp SetupImplement
Keys AcresVehicle.cpp ReadImplementKeys
Drive script keys AcresVehicle.cpp StepImplementPhysics
Field marks and telemetry AcresVehicle.cpp StepImplementPhysics
Position of the rig on the Maxxum AcresVehicle.cpp UpdateRigs
Telemetry fields AcresVehicle.h FAcresImplementTelemetry
Implement card and key help AcresHud.cpp DrawWorkPanels, DrawHelpBox
Menu choice and checks AcresSession.cpp Row trac:implement_model.id, ValidateImplementModel
Columns of the session log AcresSessionLog.cpp Header and row of tractor.csv
Commands of the vehicle bridge AcresVehicle.cpp ApplyImplementCommand
  1. Add the identifier to the message in LoadImplementConfiguration and to the choice list in AcresSession.cpp.

  2. Add the label in ImplementLabel.

  3. If the implement uses the PTO, set PtoRatio in SetupImplement.

  4. Set the tool zone ToolXM in SetupImplement. The pawn reads the ground and the soil there.

  5. Add the keys in ReadImplementKeys and the key help in DrawHelpBox.

  6. Add the drive script keys of the new controls in StepImplementPhysics.

  7. Add the rows of the implement card in DrawWorkPanels.

  8. If the mount is not the three-point hitch, add the position of the rig in UpdateRigs.

  9. If the implement changes the field, mark the work in StepImplementPhysics with FAcresFarmRuntime::Work.

  10. Add new telemetry fields to FAcresImplementTelemetry and new columns to the session log.

Note

A change of the session log columns or the bridge messages changes a public interface. Update the reference pages and the changelog.

Tests#

Tools/ImplementModel compiles the model without Unreal and runs the checks. The data files are an input of the checks.

  1. Add checks for the new implement in Tools/ImplementModel/implement_tests.cpp.

    Test function Add for a new implement
    TestWrenchBalance The tractor wrench is equal to the external wrench plus the weight.
    TestInterlocks Raise, transport and PTO interlocks.
    TestConservation Mass balance of each payload.
    TestTimestep Equal results at 1/60 s, 1/120 s and 1/240 s.
    TestRig The names and the ranges of the rig controls from mechanics.json.
    TestHydraulics Pressure, flow and stall of each ram.
    TestParameters No change. The test examines all kinds.
  2. Build the tool and run the checks.

    Tools/ImplementModel/build.sh
    

    Expected Result

    built /tmp/acres-implement-model/implement_tool
    244 checks, 0 failed
    

    The number of checks increases with the new checks.

  3. Compile the model with the clang of the engine as a portability check.

    UE_CLANG=<path to clang++ of the engine> Tools/ImplementModel/build.sh
    

    Expected Result

    The output contains Unreal clang check passed.

  4. If the implement has an ASABE row, add it to PrintAsabeTable and compare.

    "${TMPDIR:-/tmp}/acres-implement-model/implement_tool" asabe
    
  5. Package the game and run the implement on a field. Refer to Attach and Operate Implements.

    Expected Result

    The log contains ACRES_IMPLEMENT_READY id=<id>. The log does not contain ACRES_IMPLEMENT_RIG_MISSING or ACRES_IMPLEMENT_WRENCH_LIMITED.

Tests and Regression Checklist lists the other tests of the repository.

Update the Documentation#

  1. Add a section to the Implement Catalog: function, mechanics, controls, parameters, options and rig controls.

  2. Add the shared equations of a new force model to Implement Mechanics.

  3. Add a procedure to Attach and Operate Implements.

  4. Add new options to the Command-Line Options and new columns to the Session Log.

  5. Add the change to the Changelog.

  6. Do the checks of Write Documentation.