Commit be279f26 authored by luroth's avatar luroth
Browse files

Motion blur claculation adapted, now slider is restricted by min and max based...

Motion blur claculation adapted, now slider is restricted by min and max based on flight duration and camera trigger freq.
parent 330a26fa
...@@ -49,12 +49,13 @@ calc_depth_of_field_far <- function(f, aperture, circle_of_confusion, focus_dist ...@@ -49,12 +49,13 @@ calc_depth_of_field_far <- function(f, aperture, circle_of_confusion, focus_dist
} }
calc_shutter_speed <- function(exposure_value, aperture, iso=100) { calc_shutter_speed <- function(exposure_value, aperture, iso=100) {
return(1/((25 * aperture^2 * 2^(2-exposure_value))/(iso)))
return(as.numeric(iso)/(25.0 * 2.0^(2.0+as.numeric(exposure_value))/(as.numeric(aperture)^2.0)))
} }
calc_iso <- function(exposure_value, aperture, shutter_speed) { calc_iso <- function(exposure_value, aperture, shutter_speed) {
return((25.0 * as.numeric(aperture)^2.0 * 2.0^(2.0-as.numeric(exposure_value)))/((1/as.numeric(shutter_speed))))
return(25.0 * as.numeric(aperture)^2.0 * 2.0^(2.0-as.numeric(exposure_value))/(1.0/as.numeric(shutter_speed)))
} }
calc_spacing_exposure_station <- function(end_lap, ground_field_of_view_x) { calc_spacing_exposure_station <- function(end_lap, ground_field_of_view_x) {
...@@ -77,10 +78,19 @@ calc_flight_speed <- function(ground_sampling_distance, motion_blur, shutter_spe ...@@ -77,10 +78,19 @@ calc_flight_speed <- function(ground_sampling_distance, motion_blur, shutter_spe
return(((ground_sampling_distance)*motion_blur) / (1/shutter_speed)) return(((ground_sampling_distance)*motion_blur) / (1/shutter_speed))
} }
calc_motion_blur <- function(ground_sampling_distance, flight_speed, shutter_speed) {
return((flight_speed * (1/shutter_speed))/ground_sampling_distance)
}
calc_image_recording_speed <- function(flight_speed, spacing_exposure_station) { calc_image_recording_speed <- function(flight_speed, spacing_exposure_station) {
return(flight_speed / spacing_exposure_station) return(flight_speed / spacing_exposure_station)
} }
calc_flight_distance <- function(distance_area_x, ground_field_of_view_x, distance_area_y, ground_field_of_view_y, spacing_flight_lines) {
distance <- 1 * (distance_area_x + ceiling(ground_field_of_view_x / (2 * spacing_flight_lines))) * 2 * spacing_flight_lines + (distance_area_x/spacing_flight_lines) * (distance_area_y + ground_field_of_view_y)
return(distance)
}
calc_flight_duration <- function(distance_area_x, ground_field_of_view_x, distance_area_y, ground_field_of_view_y, spacing_flight_lines, flight_speed) { calc_flight_duration <- function(distance_area_x, ground_field_of_view_x, distance_area_y, ground_field_of_view_y, spacing_flight_lines, flight_speed) {
distance <- 1 * (distance_area_x + ceiling(ground_field_of_view_x / (2 * spacing_flight_lines))) * 2 * spacing_flight_lines + (distance_area_x/spacing_flight_lines) * (distance_area_y + ground_field_of_view_y) distance <- 1 * (distance_area_x + ceiling(ground_field_of_view_x / (2 * spacing_flight_lines))) * 2 * spacing_flight_lines + (distance_area_x/spacing_flight_lines) * (distance_area_y + ground_field_of_view_y)
duration <- (distance / flight_speed) / 60 duration <- (distance / flight_speed) / 60
......
[ [
{ {
"name": "Sony Alpha 9", "name": "Sony Alpha 9 on DJI Matrice 600 Pro",
"sensor_values": { "sensor_values": {
"d_sensor_x": 35.6, "d_sensor_x": 35.6,
"d_sensor_y": 23.8, "d_sensor_y": 23.8,
...@@ -9,12 +9,14 @@ ...@@ -9,12 +9,14 @@
"default_lens_aperture": 8, "default_lens_aperture": 8,
"focal_lenght": 55, "focal_lenght": 55,
"t_max": 32000, "t_max": 32000,
"ISO_max": 6400 "ISO_max": 6400,
"freq_max": 2,
"flight_max": 15
} }
}, },
{ {
"name": "Sony RX100 II", "name": "Sony RX100 II on Mikrokopter Quadro",
"sensor_values": { "sensor_values": {
"d_sensor_x": 13.2, "d_sensor_x": 13.2,
"d_sensor_y": 8.8, "d_sensor_y": 8.8,
...@@ -23,7 +25,9 @@ ...@@ -23,7 +25,9 @@
"default_lens_aperture": 4, "default_lens_aperture": 4,
"focal_lenght": 10.4, "focal_lenght": 10.4,
"t_max": 2000, "t_max": 2000,
"ISO_max": 12800 "ISO_max": 12800,
"freq_max": 0.5,
"flight_max": 8
} }
}, },
...@@ -37,11 +41,13 @@ ...@@ -37,11 +41,13 @@
"default_lens_aperture": 2.8, "default_lens_aperture": 2.8,
"focal_lenght": 3.6125, "focal_lenght": 3.6125,
"t_max": 8000, "t_max": 8000,
"ISO_max": 3200 "ISO_max": 3200,
"freq_max": 1,
"flight_max": 25
} }
}, },
{ {
"name": "Parrot Sequoia monochrome (4 bands)", "name": "Parrot Sequoia monochrome (4 bands) on DJI P4P",
"sensor_values": { "sensor_values": {
"d_sensor_x": 4.8, "d_sensor_x": 4.8,
"d_sensor_y": 3.6, "d_sensor_y": 3.6,
...@@ -50,12 +56,14 @@ ...@@ -50,12 +56,14 @@
"default_lens_aperture": 2.2, "default_lens_aperture": 2.2,
"focal_lenght": 3.98, "focal_lenght": 3.98,
"t_max": 5000, "t_max": 5000,
"ISO_max": 800 "ISO_max": 800,
"freq_max": 1,
"flight_max": 25
} }
}, },
{ {
"name": "Parrot Sequoia RGB", "name": "Parrot Sequoia RGB on DJI P4P",
"sensor_values": { "sensor_values": {
"d_sensor_x": 6.17472, "d_sensor_x": 6.17472,
"d_sensor_y": 4.63104, "d_sensor_y": 4.63104,
...@@ -64,10 +72,12 @@ ...@@ -64,10 +72,12 @@
"default_lens_aperture": 2.2, "default_lens_aperture": 2.2,
"focal_lenght": 4.88, "focal_lenght": 4.88,
"t_max": 5000, "t_max": 5000,
"ISO_max": 800 "ISO_max": 800,
"freq_max": 1,
"flight_max": 25
} }
} }
}
] ]
\ No newline at end of file
...@@ -102,6 +102,8 @@ server_ <- function(input, output, session) { ...@@ -102,6 +102,8 @@ server_ <- function(input, output, session) {
shinyjs::toggleState("n_pix_y", FALSE) shinyjs::toggleState("n_pix_y", FALSE)
shinyjs::toggleState("t_max", FALSE) shinyjs::toggleState("t_max", FALSE)
shinyjs::toggleState("ISO_max", FALSE) shinyjs::toggleState("ISO_max", FALSE)
shinyjs::toggleState("freq_max", FALSE)
shinyjs::toggleState("flight_max", FALSE)
# Update text on edit button # Update text on edit button
updateActionButton(session, "sensor_and_lens_edit", label="Edit settings") updateActionButton(session, "sensor_and_lens_edit", label="Edit settings")
# Set sensor selection readonly # Set sensor selection readonly
...@@ -122,7 +124,7 @@ server_ <- function(input, output, session) { ...@@ -122,7 +124,7 @@ server_ <- function(input, output, session) {
shinyjs::toggleState("sensor_and_lens_select", TRUE) shinyjs::toggleState("sensor_and_lens_select", TRUE)
} }
# update shutter speed values # update shutter speed values
updateSelectInput(session, "shutter_speed", choices = shutter_speed_values[as.numeric(shutter_speed_values)<=input$t_max] ) updateSelectInput(session, "shutter_speed", choices = shutter_speed_values[as.numeric(shutter_speed_values)<=input$t_max], selected = 8000 )
derived_values$sensor_selection_enabled <- !derived_values$sensor_selection_enabled derived_values$sensor_selection_enabled <- !derived_values$sensor_selection_enabled
}) })
...@@ -144,6 +146,8 @@ server_ <- function(input, output, session) { ...@@ -144,6 +146,8 @@ server_ <- function(input, output, session) {
updateNumericInput(session, "aperture", value = configs[['default_lens_aperture']]) updateNumericInput(session, "aperture", value = configs[['default_lens_aperture']])
updateNumericInput(session, "t_max", value = configs[['t_max']]) updateNumericInput(session, "t_max", value = configs[['t_max']])
updateNumericInput(session, "ISO_max", value = configs[['ISO_max']]) updateNumericInput(session, "ISO_max", value = configs[['ISO_max']])
updateNumericInput(session, "freq_max", value = configs[['freq_max']])
updateNumericInput(session, "flight_max", value = configs[['flight_max']])
fields_editable <- FALSE fields_editable <- FALSE
} }
shinyjs::toggleState("d_sensor_x", fields_editable) shinyjs::toggleState("d_sensor_x", fields_editable)
...@@ -152,6 +156,8 @@ server_ <- function(input, output, session) { ...@@ -152,6 +156,8 @@ server_ <- function(input, output, session) {
shinyjs::toggleState("n_pix_y", fields_editable) shinyjs::toggleState("n_pix_y", fields_editable)
shinyjs::toggleState("t_max", fields_editable) shinyjs::toggleState("t_max", fields_editable)
shinyjs::toggleState("ISO_max", fields_editable) shinyjs::toggleState("ISO_max", fields_editable)
shinyjs::toggleState("freq_max", fields_editable)
shinyjs::toggleState("flight_max", fields_editable)
}) })
# Inputs and conversions (all in px and m) # Inputs and conversions (all in px and m)
...@@ -364,29 +370,49 @@ server_ <- function(input, output, session) { ...@@ -364,29 +370,49 @@ server_ <- function(input, output, session) {
# Flight speed calculation # Flight speed calculation
observe({ observe({
req(derived_values$ground_sampling_distance, input$motion_blur, derived_values$shutter_speed) req(derived_values$ground_sampling_distance, input$motion_blur, derived_values$shutter_speed, derived_values$spacing_between_exposures,
derived_values$flight_speed <- calc_flight_speed(derived_values$ground_sampling_distance, input$motion_blur, derived_values$shutter_speed) input$mapping_area_x, derived_values$field_of_view_x, input$mapping_area_y, derived_values$field_of_view_y, derived_values$spacing_between_flight_lines)
})
# Recording speed calculation req_flight_speed <- calc_flight_speed(derived_values$ground_sampling_distance, input$motion_blur, derived_values$shutter_speed)
observe({ req_image_recording_speed <- round(calc_image_recording_speed(req_flight_speed, derived_values$spacing_between_exposures),2)
req(derived_values$spacing_between_exposures, derived_values$flight_speed) req_flight_duration <- round(calc_flight_duration(input$mapping_area_x, derived_values$field_of_view_x, input$mapping_area_y, derived_values$field_of_view_y,
derived_values$image_recording_speed <- calc_image_recording_speed(derived_values$flight_speed, derived_values$spacing_between_exposures) derived_values$spacing_between_flight_lines, req_flight_speed))
}) actual_motion_blur <- isolate(input$motion_blur)
max_flight_speed <- input$freq_max * derived_values$spacing_between_exposures
max_motion_blur <- round(calc_motion_blur(derived_values$ground_sampling_distance, max_flight_speed , derived_values$shutter_speed),2)
min_flight_speed <- calc_flight_distance(input$mapping_area_x, derived_values$field_of_view_x, input$mapping_area_y, derived_values$field_of_view_y,
derived_values$spacing_between_flight_lines) / (input$flight_max* 60)
min_motion_blur <- round(calc_motion_blur(derived_values$ground_sampling_distance, min_flight_speed, derived_values$shutter_speed),2)
updateSliderInput(session, "motion_blur", min=min_motion_blur, max=max_motion_blur)
if(max_motion_blur <= min_motion_blur) {
showModal(modalDialog(title = "Warning", paste0("No solution for motion blur found. Reduce overlaps or mapping area"), footer = modalButton("OK")))
} else if(actual_motion_blur > max_motion_blur) {
showModal(modalDialog(title = "Warning", paste0("The required image recording frequency is higher than the maximum allowed image recording frequency (", input$freq_max, "). The motion blur was value was reduced from ", actual_motion_blur, " to ", max_motion_blur), footer = modalButton("OK")))
updateSliderInput(session, "motion_blur", value=max_motion_blur)
} else if(actual_motion_blur < min_motion_blur) {
showModal(modalDialog(title = "Warning", paste("The required flight duration is higher than the maximum allowed flight duration (", input$flight_max, "). The motion blur was value was increased from ", actual_motion_blur, " to ", min_motion_blur), footer = modalButton("OK")))
updateSliderInput(session, "motion_blur", value=min_motion_blur)
}
derived_values$flight_speed <-req_flight_speed
derived_values$image_recording_speed <- req_image_recording_speed
derived_values$flight_duration <- req_flight_duration
# Flight duration calculation
observe({
req(input$mapping_area_x, derived_values$field_of_view_x, input$mapping_area_y, derived_values$field_of_view_y,
derived_values$flight_speed, derived_values$spacing_between_flight_lines)
derived_values$flight_duration <- calc_flight_duration(input$mapping_area_x, derived_values$field_of_view_x, input$mapping_area_y, derived_values$field_of_view_y,
derived_values$spacing_between_flight_lines, derived_values$flight_speed)
}) })
# Number of photos and positions calculation # Number of photos and positions calculation
observe({ observe({
req(input$mapping_area_x, input$mapping_area_y, derived_values$side_lap, derived_values$spacing_between_exposures, derived_values$spacing_between_flight_lines) req(input$mapping_area_x, input$mapping_area_y, derived_values$side_lap, derived_values$spacing_between_exposures, derived_values$spacing_between_flight_lines,
derived_values$field_of_view_y, derived_values$field_of_view_x)
req(derived_values$spacing_between_exposures>0)
# Photo positions on x axis # Photo positions on x axis
overlap_lines = ceiling(derived_values$field_of_view_x / (2 * derived_values$spacing_between_flight_lines) ) overlap_lines = ceiling(derived_values$field_of_view_x / (2 * derived_values$spacing_between_flight_lines) )
...@@ -629,6 +655,14 @@ server_ <- function(input, output, session) { ...@@ -629,6 +655,14 @@ server_ <- function(input, output, session) {
plot_mapping_area() plot_mapping_area()
}) })
# Download handler for mapping area plot
output$download_mapping_area_plot <- downloadHandler(
filename = function() { paste(input$dataset, '.pdf', sep='') },
content = function(file) {
ggsave(file, plot = plot_mapping_area(), device = "pdf")
}
)
# Calculate waypoints # Calculate waypoints
waypoints <- reactive({ waypoints <- reactive({
req(input$position_edge1_long, input$position_edge1_lat, input$position_edge2_long, input$position_edge1_lat, req(input$position_edge1_long, input$position_edge1_lat, input$position_edge2_long, input$position_edge1_lat,
...@@ -735,20 +769,55 @@ server_ <- function(input, output, session) { ...@@ -735,20 +769,55 @@ server_ <- function(input, output, session) {
return(waypoints_df) return(waypoints_df)
}) })
waypoint_edges <- reactive({ debounced_f
# Create waypoint leaflet
output$waypoint_map <- renderLeaflet({
isolate({
req(waypoints())
req(input$position_edge1_lat, input$position_edge2_lat, input$position_start_lat, input$position_edge1_long, input$position_edge2_long, input$position_start_long) req(input$position_edge1_lat, input$position_edge2_lat, input$position_start_lat, input$position_edge1_long, input$position_edge2_long, input$position_start_long)
data.frame(lat = c(input$position_edge1_lat, input$position_edge2_lat, input$position_start_lat),
waypoint_edges <- data.frame(lat = c(input$position_edge1_lat, input$position_edge2_lat, input$position_start_lat),
long = c(input$position_edge1_long, input$position_edge2_long, input$position_start_long), long = c(input$position_edge1_long, input$position_edge2_long, input$position_start_long),
desc = c("Edge 1", "Flight direction", "Start point")) desc = c("Edge 1", "Flight direction", "Start point"))
map = leaflet(data= waypoint_edges) %>%
addMarkers(data= waypoint_edges[1,], layerId= 1, ~long, ~lat, popup = ~as.character(desc), label = ~as.character(desc), options = markerOptions(draggable = TRUE)) %>%
addMarkers(data= waypoint_edges[2,], layerId= 2, ~long, ~lat, popup = ~as.character(desc), label = ~as.character(desc), options = markerOptions(draggable = TRUE)) %>%
addMarkers(data= waypoint_edges[3,], layerId= 3, ~long, ~lat, popup = ~as.character(desc), label = ~as.character(desc), options = markerOptions(draggable = TRUE)) %>%
addPolylines(layerId = 4, data=waypoints(), lat = ~latitude, lng=~longitude)
}) })
# Create waypoint leaflet providers <- c("OpenStreetMap.Mapnik", "Esri.WorldImagery")
output$waypoint_map <- renderLeaflet({ for(i in 1:length(providers)){
req(waypoints(), waypoint_edges()) map = map %>% addProviderTiles(providers[i], group = providers[i])
}
map = map %>% addLayersControl(
baseGroups = providers,
options = layersControlOptions(collapsed = FALSE))
map
})
observeEvent(input$waypoint_map_marker_mouseout, {
event <- input$waypoint_map_marker_mouseout
if(event$id == 1) {
updateNumericInput(session, "position_edge1_lat", value=event$lat)
updateNumericInput(session, "position_edge1_long", value=event$lng)
} else if(event$id == 2) {
updateNumericInput(session, "position_edge2_lat", value=event$lat)
updateNumericInput(session, "position_edge2_long", value=event$lng)
} else if(event$id == 3) {
updateNumericInput(session, "position_start_lat", value=event$lat)
updateNumericInput(session, "position_start_long", value=event$lng)
}
})
leaflet(data= waypoint_edges()) %>% addTiles() %>% observeEvent(waypoints(), {
addMarkers(~long, ~lat, popup = ~as.character(desc), label = ~as.character(desc)) %>% req(waypoints())
addPolylines(data=waypoints(), lat = ~latitude, lng=~longitude)
leafletProxy("waypoint_map", session) %>%
clearShapes() %>%
addPolylines(layerId = 4, data=waypoints(), lat = ~latitude, lng=~longitude)
}) })
# Legend to waypoint leaflet # Legend to waypoint leaflet
......
...@@ -3,7 +3,7 @@ library(leaflet) ...@@ -3,7 +3,7 @@ library(leaflet)
# Default values # Default values
default_exposure_value <- 14 default_exposure_value <- 14
default_max_motion_blur <- 0.02 default_max_motion_blur <- 0.04
default_iso <- 4000 default_iso <- 4000
default_shutter_speed <- 16000 default_shutter_speed <- 16000
default_flight_height <- 30 default_flight_height <- 30
...@@ -53,8 +53,12 @@ ui_ <- fluidPage( ...@@ -53,8 +53,12 @@ ui_ <- fluidPage(
column(6, numericInput("n_pix_y", "Number of recorded pixels in y (px)", width = "100%", value=NA, step=1)) column(6, numericInput("n_pix_y", "Number of recorded pixels in y (px)", width = "100%", value=NA, step=1))
), ),
fluidRow( fluidRow(
column(6, numericInput("t_max", "Maximal shutter speed (1/s)", width = "100%", value=NA, step=1000)), column(6, numericInput("t_max", "Max. shutter speed (1/s)", width = "100%", value=NA, step=1000)),
column(6, numericInput("ISO_max", "Maximal film speed (ISO)", width = "100%", value=NA, step=1000)) column(6, numericInput("ISO_max", "Max. film speed (ISO)", width = "100%", value=NA, step=1000))
),
fluidRow(
column(6, numericInput("freq_max", "Max. recording freqency (1/s)", width = "100%", value=NA)),
column(6, numericInput("flight_max", "Max. flight time (min)", width = "100%", value=NA))
), ),
htmlOutput("d_pix_output"), htmlOutput("d_pix_output"),
hr(), hr(),
...@@ -105,7 +109,7 @@ ui_ <- fluidPage( ...@@ -105,7 +109,7 @@ ui_ <- fluidPage(
column(6, numericInput("spacing_between_exposures", "End lap (m)", width = "100%", value=NA)) column(6, numericInput("spacing_between_exposures", "End lap (m)", width = "100%", value=NA))
), ),
fluidRow( 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,radioButtons("flip_camera", "Camera heading", choiceNames=c("Narrow side in flight direction", "Wide side in flight direction"), choiceValues = c(FALSE, TRUE), selected = default_flip_camera)),
column(6, numericInput("positioning_precision", "Positioning precision (m)", width = "100%", value = default_position_precision)) column(6, numericInput("positioning_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%") sliderInput("motion_blur", "Maximal motion blur (px)", min = 0.01, max = 1, step = 0.01, value = default_max_motion_blur, width = "100%")
...@@ -170,7 +174,10 @@ ui_ <- fluidPage( ...@@ -170,7 +174,10 @@ ui_ <- fluidPage(
column(8, column(8,
h4("Mapping area"), h4("Mapping area"),
tabsetPanel(type="pills", tabsetPanel(type="pills",
tabPanel("Schematic", plotOutput("plot_mapping_area", height = "600px")), tabPanel("Schematic",
plotOutput("plot_mapping_area", height = "600px"),
downloadButton("download_mapping_area_plot")
),
tabPanel("Map", tabPanel("Map",
leafletOutput("waypoint_map", height = "600px"), leafletOutput("waypoint_map", height = "600px"),
htmlOutput("waypoint_settings")), htmlOutput("waypoint_settings")),
......
Supports Markdown
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