This README is generated by codex.
This utility adds straight, parallel rows of OBJ mesh instances to an existing MAVS scene JSON. The first row is defined by two XY points, and every additional row is generated by shifting that first row sideways at a fixed row spacing.
create_rows.py: editable script where paths and row parameters are set.row_placement.py: reusable implementation for mesh discovery, row geometry, object placement, and scene writing.
Edit the constants near the top of create_rows.py, then run:
python3 create_rows.pyThe script writes a new MAVS scene JSON to OUTPUT_FILE.
The input scene must be a MAVS scene JSON with an "Objects" list:
{
"Objects": []
}Other MAVS scene fields can already exist in the file. This utility only adds
or appends entries in "Objects".
SCENE_FILE: path to the base MAVS scene JSON.MESH_DIR: folder searched recursively for.objfiles.MESHES_ROOT: root folder used to write mesh paths relative to MAVS'smeshesdirectory.OUTPUT_FILE: path where the generated scene JSON is written.FIRST_ROW_START:[x, y]start point of the first row.FIRST_ROW_END:[x, y]end point of the first row.PLANT_SPACING: distance between objects along each row.ROW_SPACING: distance between parallel rows.NUM_ROWS: number of rows to create.ROW_SIDE: either1or-1; flip this value if rows are generated on the wrong side of the first row.SCALE:[x, y, z]scale applied to every placed mesh.Z_VALUE: Z coordinate used for every placed mesh position.POSITION_NOISE_STD: standard deviation for small Gaussian noise added to each object's XY position.LABEL_BY_GROUP: value written to MAVS"Label By Group"for new mesh entries.SEED: optional random seed for repeatable mesh selection, XY noise, and orientation.
MESH_DIR controls where the script searches for OBJ files. MESHES_ROOT
controls how those files are written into the scene JSON.
For example:
MESH_DIR = "/home/kodai/mavs_latest/data/scenes/meshes/cotton/objective1_related"
MESHES_ROOT = "/home/kodai/mavs_latest/data/scenes/meshes"If the script finds:
/home/kodai/mavs_latest/data/scenes/meshes/cotton/objective1_related/plant.obj
it writes this mesh path into the scene:
cotton/objective1_related/plant.obj
The first row is the line segment from FIRST_ROW_START to FIRST_ROW_END.
The implementation computes:
row_vector = first_row_end - first_row_start
row_direction = row_vector / row_length
side_direction = [-row_direction_y, row_direction_x] * ROW_SIDEEach additional row is shifted from the first row by:
side_direction * ROW_SPACING * row_indexThis keeps all rows straight, parallel, and evenly spaced. ROW_SIDE only
chooses which side of the first row receives the additional rows.
For each sampled row point, the utility:
- Randomly selects one mesh path from the discovered OBJ files.
- Adds small Gaussian noise to the XY position.
- Sets the Z position to
Z_VALUE. - Samples a random
YawPitchRollorientation. - Adds the object instance to the scene.
If a selected mesh already exists in the scene's "Objects" list, the new
instance is appended to that mesh entry. Otherwise, a new mesh entry is created.
New mesh entries have this structure:
{
"Mesh": "relative/path/to/mesh.obj",
"Smooth Normals": false,
"Label By Group": true,
"Rotate Y to Z": false,
"Instances": [
{
"YawPitchRoll": [0.0, 0.0, 0.0],
"Position": [0.0, 0.0, 0.0],
"Scale": [1.0, 1.0, 1.0]
}
]
}