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:
-
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
_degare degrees, and names that end in_mare metres. - A hydraulic cylinder uses the constraints Copy Location and Damped Track to stay on its two pins.
Add the Source Asset#
-
Make the folder
Acres/Raw/farm-equipment/<id>/with the Blender file, the FBX file and the textures. -
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_mandrigid_bodies. The values ofmountarecategory_II_three_point,custom_loader_subframe,custom_rigid_subframeanddrawbar_trailed. -
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.jsonwith"passed": true. -
Write the catalog again.
Expected Result
catalog.jsoncontains an entry with the identifier of the new asset. -
Run the tests of the offline mechanics library.
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.
-
Write the rig map with Blender.
Expected Result
The file
Acres/Content/Simulation/rigs/<id>.jsonexists. It contains the controls, the bones, the sockets and the test poses. -
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 -nullrhiExpected Result
The log contains
ACRES_FARM_IMPORT <id> passed=TrueandACRES_FARM_IMPORT_DONE. The fileAcres/Saved/FarmEquipment/import_report.jsoncontains 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°.
-
Package the game again. Refer to Build the Game.
-
Run the rig self-test.
Expected Result
The log contains one line for each rig map and a summary. This is the output for the shipped rigs:
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.
-
Add a value to
EImplementKindbeforeCount. Add the identifier inImplementKindId. -
Add a parameter structure if the implement has a new mechanism. Add it to
FImplementParameters. -
Set the mass, the centre of mass, the inertia and the tool layout in
MakeImplementParameters. -
Register each parameter in
ImplScalarKeys,ImplIntKeysorImplBoolKeyswith its file unit and its limits. -
Add the controls of the operator to
FImplementControlsand the states toFImplementState. -
Write the step function.
StepImplementselects it by the kind.A mounted implement with tines, discs, rollers or drill rows needs no new step function.
ImplStepThreePointcomputes these tools from their counts. A different machine needs its own function, for exampleImplStepBaler. -
Fill all applicable fields of
FImplementOutput: the wrench, the PTO, the hydraulics, the mass and the flags. -
Add the rig controls in
ImplementRigControls. Use the control names ofmechanics.json. -
Set the initial state in
ResetImplementand the default controls inImplementDefaultControls. -
If the implement has a depth setting, extend
ImplementDepthRangeMandImplementControlsForDepth.
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.
ExternalForceNcontains no weight. The pawn adds the mass to the chassis body.- A new payload must change
MassKg,ComMandPayloadKgin 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.
-
Add the block of the new implement to
Relevantand a source note toSourceNoteinTools/ImplementModel/implement_data.cpp. -
Build the tool.
-
Write the data files.
"${TMPDIR:-/tmp}/acres-implement-model/implement_tool" write-json Acres/Content/Simulation/implementsExpected 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 |
-
Add the identifier to the message in
LoadImplementConfigurationand to the choice list inAcresSession.cpp. -
Add the label in
ImplementLabel. -
If the implement uses the PTO, set
PtoRatioinSetupImplement. -
Set the tool zone
ToolXMinSetupImplement. The pawn reads the ground and the soil there. -
Add the keys in
ReadImplementKeysand the key help inDrawHelpBox. -
Add the drive script keys of the new controls in
StepImplementPhysics. -
Add the rows of the implement card in
DrawWorkPanels. -
If the mount is not the three-point hitch, add the position of the rig in
UpdateRigs. -
If the implement changes the field, mark the work in
StepImplementPhysicswithFAcresFarmRuntime::Work. -
Add new telemetry fields to
FAcresImplementTelemetryand 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.
-
Add checks for the new implement in
Tools/ImplementModel/implement_tests.cpp.Test function Add for a new implement TestWrenchBalanceThe tractor wrench is equal to the external wrench plus the weight. TestInterlocksRaise, transport and PTO interlocks. TestConservationMass balance of each payload. TestTimestepEqual results at 1/60 s, 1/120 s and 1/240 s. TestRigThe names and the ranges of the rig controls from mechanics.json.TestHydraulicsPressure, flow and stall of each ram. TestParametersNo change. The test examines all kinds. -
Build the tool and run the checks.
-
Compile the model with the clang of the engine as a portability check.
Expected Result
The output contains
Unreal clang check passed. -
If the implement has an ASABE row, add it to
PrintAsabeTableand compare. -
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 containACRES_IMPLEMENT_RIG_MISSINGorACRES_IMPLEMENT_WRENCH_LIMITED.
Tests and Regression Checklist lists the other tests of the repository.
Update the Documentation#
-
Add a section to the Implement Catalog: function, mechanics, controls, parameters, options and rig controls.
-
Add the shared equations of a new force model to Implement Mechanics.
-
Add a procedure to Attach and Operate Implements.
-
Add new options to the Command-Line Options and new columns to the Session Log.
-
Add the change to the Changelog.
-
Do the checks of Write Documentation.