-
Notifications
You must be signed in to change notification settings - Fork 54
pyhelios π The util subpackage
The util subpackage of pyhelios contains a number of utility scripts.
The xmlchecker is a tool to validate XML files against XML style definitions (XSDs) before executing a survey. It is only a Python wrapper around the standard command line call and does not use the Python bindings.
If no errors are found in the XML configurations, the specified survey is executed as usual. Other wise, the XML errors are reported to the user and HELIOS++ is not run.
The script takes the same arguments as the HELIOS++ command line call (Optional arguments).
The example below shows how to execute the same survey with the standard command line call, and with the python script and XML validation.
Command line:
helios data/surveys/toyblocks/als_toyblocks.xml --lasOutputPython:
python python/pyhelios/util/xmlchecker.py data/surveys/toyblocksals_toyblocks.xml --lasOutputYou may want to share or publish your simulation, so that others can reproduce it. For this purpose, you can use the tool archive.py, which will write
- the data folder with all sceneparts, scanner-XMLs, platform XMLs, scene-XMLs and survey-XMLs for the specified survey(s)
- the assets folder
- the run folder (from your HELIOS repository or downloaded from GitHub)
- a file
version.txtcontaining the version number [To do: image of folder structure]
Usage example:
python pyhelios\util\archive.py run\helios.exe data\surveys\toyblocks\als_toyblocks.xml my_archive.zipMultiple surveys can be specified by creating an ASCII file with one survey path per line and providing this instead of the survey XML.
Such an ASCII file my_surveys.txt may look like this:
data\surveys\survey1.xml
data\surveys\survey2.xml
data\surveys\survey3.xml
To create the zip-archive, run:
python pyhelios\util\archive.py run\helios.exe my_surveys.txt archive.zipThe scene writer contains a number of functions which facilitate writing scene XMLs, which can then be executed either with pyhelios or by running HELIOS++ from the command line.
These functions include:
- adding transformation filters
- adding sceneparts
- creating the scene
Import the script
from pyhelios.util import scene_writerCreate transformation filters
filters = scene_writer.add_transformation_filters(translation=[478335.125, 5473887.89, 0.0], rotation=[0, 0, 90], on_ground=-1)Create scene parts Here, we load a digital elevation model (DEM) from a GeoTIFF file and a 3D model of a tree from an OBJ file. To our seconds scene part, the tree, we apply the transformation that was created in the previous step.
sp = scene_writer.create_scenepart_tiff(r"data/sceneparts/tiff/dem_hd.tif",
matfile=r"data/sceneparts/basic/groundplane/groundplane.mtl",
matname="None")
sp2 = scene_writer.create_scenepart_obj("data/sceneparts/arbaro/black_tupelo_low.obj", trafofilter=filters)Create the scene XML
Finally, we create a scene XML file with these scene parts.
scene = scene_writer.build_scene(scene_id="test", name="test_scene", sceneparts=[sp, sp2])
print(scene)Output:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<scene id="test" name="test_scene">
<part>
<filter type="geotiffloader">
<param type="string" key="filepath" value="data/sceneparts/tiff/dem_hd.tif" />
<param type="string" key="matfile" value="data/sceneparts/basic/groundplane/groundplane.mtl" />
<param type="string" key="matname" value="None" />
</filter>
</part>
<part>
<filter type="objloader">
<param type="string" key="filepath" value="data/sceneparts/arbaro/black_tupelo_low.obj up="z" />
</filter>
<filter type="translate">
<param type="integer" key="onGround" value="-1" />
<param type="vec3" key="offset" value="478335.125;5473887.89;0.0" />
</filter>
<filter type="rotate">
<param key="rotation" type="rotation">
<rot angle_deg="0" axis="x"/>
<rot angle_deg="0" axis="y"/>
<rot angle_deg="90" axis="z"/>
</param>
</filter>
</part>
</scene>
</document>Check out this Jupyter Notebook to see how these functions may be used in a typical workflow.
The flight planner facilitates the creation of survey files, specifically of the legs (or waypoints) of a survey.
The flight planner functionality encompasses:
- create the flight plan (i.e., the waypoints) for given parameters (flight pattern, strip spacing, bounding box of the scan area)
- create waypoints from a shapefile
- plot a flight plan
- write the legs for the survey XML file
Import the script
from pyhelios.util import flight_plannerDefine the parameters
bbox = [-200, -50, 200, 50]
strip_spacing = 45
alt = 1000
scannerSettings = "template1"
platform_speed = 5Generate waypoints
# possible flight-patterns: parallel, criss-cross (default: parallel)
waypoints, center_point, distance = flight_planner.compute_flight_lines(bbox, spacing=strip_spacing, flight_pattern="parallel")
# or to create a rotated flight plan, e.g. by 15 degrees:
waypoints, center_point, distance = flight_planner.compute_flight_lines(bbox, spacing=strip_spacing, rotate_deg=15)
print(f"Flight duration: {distance / platform_speed / 60:.2f} min")Output:
Flight duration: 4.30 minPlot the flight plan (optional)
plot = flight_planner.plot_flight_plan(waypoints)
plot.show()Output:

Write the legs for the survey XML file
print(str(flight_planner.write_legs(waypoints, altitude=alt, template_id=scannerSettings, speed=platform_speed)))Output:
<leg>
<platformSettings x="181.5383082282002" y="-95.23047120351222" z="1000" movePerSec_m="5" />
<scannerSettings template="template1" trajectoryTimeInterval_s="0.05" />
</leg>
<leg>
<platformSettings x="-204.8320222874271" y="8.297146837496072" z="1000" movePerSec_m="5" />
<scannerSettings template="template1" active="false" trajectoryTimeInterval_s="0.05" />
</leg>
<leg>
<platformSettings x="-193.18516525781365" y="51.76380902050415" z="1000" movePerSec_m="5" />
<scannerSettings template="template1" trajectoryTimeInterval_s="0.05" />
</leg>
<leg>
<platformSettings x="193.18516525781365" y="-51.76380902050415" z="1000" movePerSec_m="5" />
<scannerSettings template="template1" active="false" trajectoryTimeInterval_s="0.05" />
</leg>
<leg>
<platformSettings x="204.8320222874271" y="-8.297146837496072" z="1000" movePerSec_m="5" />
<scannerSettings template="template1" trajectoryTimeInterval_s="0.05" />
</leg>
<leg>
<platformSettings x="-181.5383082282002" y="95.23047120351222" z="1000" movePerSec_m="5" />
<scannerSettings template="template1" active="false" trajectoryTimeInterval_s="0.05" />
</leg>Check out this Jupyter Notebook to see how the flight_planner may be used in a typical workflow.