Commit 4617525d authored by luroth's avatar luroth
Browse files

Initial commit

parents
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="R Skeletons" level="application" />
<orderEntry type="library" name="R User Library" level="project" />
</component>
<component name="TestRunnerService">
<option name="projectConfiguration" value="py.test" />
<option name="PROJECT_TEST_RUNNER" value="py.test" />
</component>
</module>
\ No newline at end of file
<component name="libraryTable">
<library name="R User Library">
<CLASSES />
<SOURCES />
</library>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6 (UAS_dpt)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/PhenoFlyPlanningTool.iml" filepath="$PROJECT_DIR$/.idea/PhenoFlyPlanningTool.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
library(shiny)
source("./ui.R")
source("./server.R")
ui <- ui_
server <- server_
app <- shinyApp(ui = ui, server = server)
\ No newline at end of file
calc_sensor_ratio <- function(sensor_size_x, sensor_size_y) {
ratio <- sensor_size_x / sensor_size_y
return(ratio)
}
calc_lens_angle_of_view <- function(sensor_size, lens_focal_length) {
angle_of_view <- 2 * atan(sensor_size / (2 * lens_focal_length))
return(angle_of_view)
}
calc_IFOV <- function(flight_height, size, sensor_recorded_pixels, focal_length) {
return((size/sensor_recorded_pixels) * flight_height / focal_length)
}
calc_IFOV_mm <- function(flight_height, size, sensor_recorded_pixels, focal_length) {
return(1000 *calc_IFOV(flight_height, size, sensor_recorded_pixels, focal_length))
}
calc_FOV <- function(flight_height, size, focal_length) {
return((size) * flight_height / focal_length)
}
calc_flight_height <- function(ifov, size, sensor_recorded_pixels, focal_length) {
return(ifov / (size/sensor_recorded_pixels) *focal_length)
}
calc_hyperfocal_distance <- function(focal_length, aperture, circle_of_confusion) {
return((focal_length^2)/(aperture*circle_of_confusion) + focal_length)
}
calc_focal_dist <- function(focal_length, aperture, circle_of_confusion, flight_height) {
hyperfocal_distance <- calc_hyperfocal_distance(focal_length, aperture, circle_of_confusion)
focus_dist <- (hyperfocal_distance * sqrt(flight_height))/(sqrt(hyperfocal_distance + flight_height))
focus_dist <- (-hyperfocal_distance^2 + sqrt(hyperfocal_distance^4 + 4 * hyperfocal_distance^2 * flight_height^2))/(2 * flight_height)
focus_dist <- ifelse(focus_dist > hyperfocal_distance, hyperfocal_distance, focus_dist)
return(focus_dist)
}
calc_depth_of_field_near <- function(focal_length, aperture, circle_of_confusion, object_distance) {
hyperfocal_distance <- calc_hyperfocal_distance(focal_length, aperture, circle_of_confusion)
return(object_distance / ( (object_distance - focal_length) / (hyperfocal_distance - focal_length) + 1))
}
calc_depth_of_field_far <- function(focal_length, aperture, circle_of_confusion, object_distance) {
hyperfocal_distance <- calc_hyperfocal_distance(focal_length, aperture, circle_of_confusion)
if(object_distance <= hyperfocal_distance) {return(object_distance / ( (focal_length - object_distance) / (hyperfocal_distance - focal_length) + 1))}
else {return(Inf)}
}
calc_exposure_value <- function(aperture, shutter_speed, iso=100) {
return(log2((100/iso)*(aperture^2)/(1/shutter_speed)))
}
calc_aperture <- function(exposure_value, shutter_speed, iso=100) {
return((1/10) * sqrt(iso) * sqrt(1/shutter_speed) * sqrt(2^exposure_value))
}
calc_shutter_speed <- function(exposure_value, aperture, iso=100) {
return(1/((25 * aperture^2 * 2^(2-exposure_value))/(iso)))
}
calc_iso <- function(exposure_value, aperture, shutter_speed) {
return((25 * aperture^2 * 2^(2-exposure_value))/(1/shutter_speed))
}
calc_flight_speed <- function(IFOV, blur, shutter_speed) {
return(((IFOV)*blur) / (1/shutter_speed))
}
calc_distance_exposure_station <- function(end_lap, FOV_x) {
return(FOV_x - ((end_lap/100) * FOV_x))
}
calc_spacing_flight_lines <- function(side_lap, FOV_y) {
return(FOV_y - (side_lap/100) * FOV_y)
}
calc_percent_exposure_station <- function(end_lap_size, FOV_x) {
return(100 - (end_lap_size/ FOV_x)*100)
}
calc_percent_flight_lines <- function(side_lap_size, FOV_y) {
return(100 - (side_lap_size/ FOV_y)*100)
}
calc_image_recording_speed <- function(flight_speed, distance_exposure_stations) {
return(flight_speed / distance_exposure_stations)
}
calc_flight_duration <- function(distance_area_x, FOV_x, distance_area_y, FOV_y, spacing_flight_lines, flight_speed) {
distance <- 1 * (distance_area_x + ceiling(FOV_x / (2 * spacing_flight_lines))) * 2 * spacing_flight_lines + (distance_area_x/spacing_flight_lines) * (distance_area_y+ FOV_y)
duration <- (distance / flight_speed) / 60
return(duration)
}
calc_min_flight_height_coded_gcp <- function(diameter_coded, size_x, sensor_recorded_pixels_x, focal_length) {
ifov <- diameter_coded / 80
height <- calc_flight_height(ifov, size_x, sensor_recorded_pixels_x, focal_length)
return(height)
}
calc_max_flight_height_coded_gcp <- function(diameter_coded, size_x, sensor_recorded_pixels_x, focal_length) {
ifov <- diameter_coded / 15
height <- calc_flight_height(ifov, size_x, sensor_recorded_pixels_x, focal_length)
return(height)
}
calc_min_flight_height_noncoded_gcp <- function(diameter_coded, size_x, sensor_recorded_pixels_x, focal_length) {
ifov <- diameter_coded / 110
height <- calc_flight_height(ifov, size_x, sensor_recorded_pixels_x, focal_length)
return(height)
}
calc_max_flight_height_noncoded_gcp <- function(diameter_coded, size_x, sensor_recorded_pixels_x, focal_length) {
ifov <- diameter_coded / 24
height <- calc_flight_height(ifov, size_x, sensor_recorded_pixels_x, focal_length)
return(height)
}
calc_pixel_freq <- function(plot_size, spacing, no_of_lanes, position_precision_sd, sensor_res, gsd, use_uniform=FALSE) {
pixels <- 1:sensor_res
# Positions of plots, pixel position as index, TRUE as value if plot present, else FALSE
plot_positions <- ifelse(seq(1, sensor_res + no_of_lanes*spacing/gsd) %% round(plot_size/gsd) + round(plot_size/(gsd*2)) == round(plot_size/(gsd)), TRUE, FALSE)
# Get camera views on plots
sensor_views <- rollapply(data=plot_positions, width=sensor_res, by=round(spacing/gsd), FUN = function(x) x)
# Calculate frequency of plots at specific sensor position
sensor_position_freq <- apply(sensor_views, MARGIN=c(2), sum)
# Normalize
sensor_position_freq <- sensor_position_freq / sum(sensor_position_freq)
# Normal distribution for each sensor pixel
if(!use_uniform) {
pixel_distribution <- mapply(pixels, FUN=function(z) {dnorm(x=pixels, sd=position_precision_sd/gsd, mean=z)})
} else {
pixel_distribution <- mapply(pixels, FUN=function(z) {dunif(x=pixels, min=z-(position_precision_sd/gsd), max=z+(position_precision_sd/gsd))})
}
# Sweep over columns and multiply with occurance frequency of sensor at this position
pixel_distribution_sens <- sweep(pixel_distribution, MARGIN=2, sensor_position_freq, '*')
# Sum up result
pixel_frequency <- rowSums(pixel_distribution_sens)
# Normalize
pixel_frequency <- pixel_frequency / sum(pixel_frequency)
pixel_frequency_data <- data.frame(x=1:sensor_res, freq=pixel_frequency)
return(pixel_frequency_data)
}
calc_pixel_freq_xy <- function(plot_size_x, plot_size_y, spacing_x, spacing_y, no_of_lanes_x, no_of_lanes_y, sensor_res_x, sensor_res_y, position_precision_sd, gsd) {
pixel_frequency_data_x <- calc_pixel_freq(plot_size_x, spacing_x, no_of_lanes_x, position_precision_sd, sensor_res_x, gsd)
pixel_frequency_data_y <- calc_pixel_freq(plot_size_y, spacing_y, no_of_lanes_y, position_precision_sd, sensor_res_y, gsd, use_uniform = TRUE)
pixel_frequency_data_xy <- unlist(pixel_frequency_data_y[,'freq']) %o% unlist(pixel_frequency_data_x[,'freq'])
pixel_frequency_data_xy <- (pixel_frequency_data_xy / max(pixel_frequency_data_xy))
return(list(pixel_frequency_data_xy, pixel_frequency_data_x, pixel_frequency_data_y))
}
long2UTM <- function(long) {
(floor((long + 180)/6) %% 60) + 1
}
[
{
"name": "Sony Alpha 9",
"sensor_values": {
"sensor_size_x": 35.6,
"sensor_size_y": 23.8,
"sensor_recorded_pixels_x": 6000,
"sensor_recorded_pixels_y": 4000,
"default_lens_aperture": 8,
"circle_of_confusion": 0.010,
"lens_focal_length": 55,
"max_shutter_speed": 30000
}
},
{
"name": "Sony RX100 II",
"sensor_values": {
"sensor_size_x": 13.2,
"sensor_size_y": 8.8,
"sensor_recorded_pixels_x": 5472,
"sensor_recorded_pixels_y": 3648,
"default_lens_aperture": 4,
"circle_of_confusion": 0.012,
"lens_focal_length": 10.4,
"max_shutter_speed": 1000
}
},
{
"name": "DJI Phantom 4",
"sensor_values": {
"sensor_size_x": 6.2,
"sensor_size_y": 4.65,
"sensor_recorded_pixels_x": 4000,
"sensor_recorded_pixels_y": 3000,
"default_lens_aperture": 2.8,
"circle_of_confusion": 0.012,
"lens_focal_length": 3.6125,
"max_shutter_speed": 8000
}
}
]
\ No newline at end of file
This diff is collapsed.
library(shinycssloaders)
library(leaflet)
# Default values
default_sensor_size_x = 35.6
default_sensor_size_y = 23.8
default_sensor_effective_Mpixels = 24.2
default_sensor_recorded_pixels_x = 6000
default_sensor_recorded_pixels_y = 4000
default_exposure_value = 14
default_max_motion_blur = 0.02
default_lens_aperture = 6
default_circle_of_confusion = 0.010
default_iso = 4000
default_lens_focal_length = 55
default_max_shutter_speed = 30000
default_shutter_speed = 16000
default_gcp_diameter_coded = 0.15
default_gcp_diameter_noncoded = 0.2
default_flight_height = 28
default_distance_area_x = 36
default_distance_area_y = 40
default_side_lap = 75.24
default_end_lap = 94.48
default_no_gcp_x = 6
default_no_gcp_y = 3
default_flip_camera = TRUE
default_plot_size_x = 1.5
default_plot_size_y = 2
default_position_precision = 3
default_position_edge1_lat = 47.450812627526901
default_position_edge1_long = 8.682496912397921
default_position_edge2_lat = 47.451039942926123
default_position_edge2_long = 8.682089627868457
default_starting_point_lat = 47.450163
default_starting_point_long = 8.682736
ui_ = fluidPage(
shinyjs::useShinyjs(),
titlePanel(windowTitle="PheonyFly Planning Tool",
title=div(img(src="CSLogo_black_40.png"), HTML("Pheno<b>Fly Planning Tool</b>"))),
sidebarLayout(
sidebarPanel(
tabsetPanel(id="config_tab",
tabPanel("Sensor/Lens",
h4("Sensor"),
fluidRow(
column(8, selectInput("sensor_configs", label=NA, choices=NA)),
column(4, actionButton("sensor_edit", "Change sensor"))
),
fluidRow(
column(6, textInput("sensor_size_x", "Sensor size, width (mm)", width = "100%", value = default_sensor_size_x)),
column(6, textInput("sensor_size_y", "Sensor size, height (mm)", width = "100%", value = default_sensor_size_y))
),
fluidRow(
column(6, textInput("sensor_recorded_pixels_x", "Number of recorded pixels in x (px)", width = "100%", value = default_sensor_recorded_pixels_x)),
column(6, textInput("sensor_recorded_pixels_y", "Number of recorded pixels in y (px)", width = "100%", value = default_sensor_recorded_pixels_y))
),
htmlOutput("pixel_size"),
hr(),
h4("Lens"),
fluidRow(
column(6, textInput("lens_focal_length", "Focal length (mm)", width = "100%", value = default_lens_focal_length)),
column(6, textInput("lens_aperture", "Aperture (f-number)", width = "100%", value = default_lens_aperture))
)
),
tabPanel("Imaging",
h4("Resolution"),
sliderInput("flight_height", "Flight height (m)", width = "100%", value = default_flight_height, min=2, max=150),
textInput("ground_resolution_nadir", "Ground sampling distance nadir (mm)", width = "100%"),
htmlOutput("field_of_view"),
hr(),
h4("Exposure"),
sliderInput("exposure_value", "Exposure value (EV)", min = 1, max = 21, step = 1, value = default_exposure_value),
hr(),
fluidRow(
column(6, textInput("shutter_speed", "Shutter speed (1/s)", value = default_shutter_speed, width = "100%")),
column(6, textInput("sensor_iso", "Film speed (ISO)", width = "100%", value = default_iso))
)
),
tabPanel("Mapping",
h4("Mapping area"),
fluidRow(
column(6,textInput("distance_area_x", "Mapping area width (m)", width = "100%", value = default_distance_area_x)),
column(6, textInput("distance_area_y","Mapping area depth (m)", width = "100%", value = default_distance_area_y))
),
fluidRow(
column(6,textInput("plot_size_x", "Plot size width (m)", width = "100%", value = default_plot_size_x)),
column(6, textInput("plot_size_y","Plot size depth (m)", width = "100%", value = default_plot_size_y))
),
hr(),
h4("Flight path"),
fluidRow(
column(6, textInput("spacing_between_flight_lines", "Percent side lap (%)", width = "100%", value = default_side_lap)),
column(6, textInput("spacing_between_exposures", "Percent end lap (%)", width = "100%", value = default_end_lap))
),
fluidRow(
column(6, textInput("spacing_between_flight_lines_size", "Spacing between flight lines (m)", width = "100%")),
column(6, textInput("spacing_between_exposures_size", "Spacing between exposure (m)", width = "100%"))
),
fluidRow(
column(6,radioButtons("flip_camera", "Camera heading", choiceNames=c("Wide side in flight direction", "Narrow side in flight direction"), choiceValues = c(FALSE, TRUE), selected = default_flip_camera)),
column(6, textInput("position_precision", "Positioning precision (m)", width = "100%", value = default_position_precision))
),
sliderInput("motion_blur", "Maximal motion blur (px)", min = 0.01, max = 1, step = 0.01, value = default_max_motion_blur, width = "100%")
),
tabPanel("GCPs",
h4("Arrangement"),
fluidRow(
column(6, textInput("gcp_n_in_x", "Number of GCP along mapping area width", width = "100%", value = default_no_gcp_x)),
column(6, textInput("gcp_n_in_y", "Number of GCP along mapping area depth", width = "100%", value = default_no_gcp_y))
),
radioButtons(inline=TRUE, "gcp_design", "Arrangement pattern",
choiceNames = list(
p("Squared", width="100px"),
p("Crosswise", width="100px")),
choiceValues = list(
"quad", "skip"
)),
fluidRow(
column(4, plotOutput("gcp_design_quad", height = "50px", width = "100px")),
column(4, plotOutput("gcp_design_skip", height = "50px", width = "100px"))
),
hr(),
h4("Coded GCP"),
fluidRow(
column(6, textInput("gcp_diameter_coded", "Size coded GCP (diameter inner circle) (m)", width = "100%", value = default_gcp_diameter_coded)),
column(6, textInput("gcp_diameter_noncoded", "Size non-coded GCP (total size) (m)", width = "100%", value = default_gcp_diameter_noncoded))
)
),
tabPanel("Location",
h4("Mapping area"),
fluidRow(
column(6,textInput("position_edge1_lat", "Field edge (Latitude)", width = "100%", value = default_position_edge1_lat)),
column(6, textInput("position_edge1_long","Field edge (Longitude)", width = "100%", value = default_position_edge1_long))
),
fluidRow(
column(6,textInput("position_edge2_lat", "Flight direction (Latitude)", width = "100%", value = default_position_edge2_lat)),
column(6, textInput("position_edge2_long","Flight direction (Longitude)", width = "100%", value = default_position_edge2_long))
),
hr(),
fluidRow(
column(6,textInput("position_start_lat", "Starting point (Latitude)", width = "100%", value = default_starting_point_lat)),
column(6, textInput("position_start_long","Starting point (Longitude)", width = "100%", value = default_starting_point_long))
)
)
),
hr(),
img(src="ETHLogo_black_20.png"),
div(HTML("<br />Group of crop science<br />Lukas Roth (lukas.roth@usys.ethz.ch)<br />(c) 2018"))
),
mainPanel(
tabsetPanel(id="results",
tabPanel("Photographic properties",
fluidRow(
column(8, h4("Flight height dependency"), plotOutput("flight_height_v_IFOV", height = "600px"), htmlOutput("optics_legend")),
column(4, htmlOutput("lens_angle_of_view"))
)
),
tabPanel("Mapping properties",
fluidRow(
column(8,
h4("Mapping area"),
tabsetPanel(type="pills",
tabPanel("Schematic", plotOutput("plot_field", height = "600px")),
tabPanel("Map", leafletOutput("waypoint_map", height = "600px"),
htmlOutput("waypoint_settings")),
tabPanel("GCP recovery frequency", plotOutput("plot_hits_gcp", height = "600px"))
)
),
column(4, htmlOutput("campaign_summary"),
h4("GCP detection"),
htmlOutput("gcp_flight_heights"))
)
),
tabPanel("Viewing geometry",
fluidRow(
column(6, h4("Sensor viewing geometry"),
tabsetPanel(type="pills",
tabPanel("Plot center recovery frequency", plotOutput("plot_recovery_frequency", height = "500px"))
)),
column(6, h4("Plot center viewing geometry"),
tabsetPanel(type="pills",
tabPanel("Zenith angle", plotOutput("plot_viewing_geometry", height = "500px")),
tabPanel("Sensor X axis", plotOutput("plot_viewing_geometry_x", height = "500px")),
tabPanel("Sensor Y axis", plotOutput("plot_viewing_geometry_y", height = "500px"))
))
),
actionButton("calc_viewing_geometry", label="(Re)calculate viewing geometry")
),
tabPanel("Mission briefing",
fluidRow(
column(5,
h4("Camera settings"),
htmlOutput("camera_settings"),
h4("Flight/campaign settings"),
htmlOutput("campaign_settings"),
h4("Restrictions"),
htmlOutput("restrictions")
),
column(7, leafletOutput("mission_waypoint_map", height=400),
div(downloadButton("download_waypoints", "Download waypoints as CSV"), HTML("(e.g. to import in Litchi)")),
div(downloadButton("download_kml", "Download mapping area as KML"), HTML("(e.g. to import in DJI GS Pro)"))
)
)
)
)
)
)
)
\ No newline at end of file
www/copter.png

866 Bytes

Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment