apaladugu3 commited on
Commit
ee0867c
·
1 Parent(s): 2ae9693

Added some more content and instructions

Browse files
Files changed (1) hide show
  1. app.py +20 -19
app.py CHANGED
@@ -83,6 +83,18 @@ def parse_all_data(path):
83
 
84
  # Create the layout for the app
85
  app.layout = html.Div([
 
 
 
 
 
 
 
 
 
 
 
 
86
  html.Div([
87
  # html.Div([
88
  # html.Div("Select the desired input conditions, then click 'Simulate!':", id='text1'),
@@ -117,18 +129,6 @@ app.layout = html.Div([
117
  # html.Br(),
118
  # html.Button('Simulate!', id='button', n_clicks=0),
119
  # ], style={'width': '50%', 'border': '1px solid gray'}),
120
-
121
- html.Div([
122
- html.B("This is an interactive demonstration of the What's Next Diagram for evaluating the ability of an operator to coordinate with envisioned automated systems, given a particular system design."),
123
- html.Br(),
124
- dcc.Markdown("More information can be found in the associated proceedings paper: Post, A., Nijveldt, R., Woods, D.D., IJtsma, M. (2024). Determining What's Next: Visual Analytics for Evaluating Human-Automation Coordination. Proceedings of the 2024 Human Factor and Ergonomics Annual Meeting, Phoenix, AZ. This work is partially funded by NSF Early Career Award #2238402 to Dr. Martijn IJtsma. This interactive demo also builds on earlier work under NASA grant 80NSSC23CA121.", id="explanation")
125
- ], style={'width': '100%', 'border': '1px solid gray'}),
126
- html.Div([
127
- dcc.Markdown("The example highlights a coordination problem in the operations of Unmanned Aerial Vehicle (UAV), which is the loss of a command and control (C2) link to the ground operator when the UAV *GCCRaven* is in busy airspace (i.e., there is surrounding traffic). The C2 link is used to receive data in real-time about the state/activity of GCCRaven, onboard automation, and to (re-)direct the automation to change GCCRaven's behavior. We use the What's Next Diagram to identify how the pilot of a second aircraft, *SNLBlaze* can coordinate with *GCCRaven*.", id="explanation")
128
- ], style={'width': '100%', 'border': '1px solid gray'}),
129
- html.Div([
130
- dcc.Markdown("It is envisioned that in future operatoins, each UAV is programmed with one or more contingency procedures that are to be executed in the case of a lost link. For this example, we assume the contingency procedure is to divert to and land at the nearest vertiport. However, even with contingency procedures onboard, there is potential for ambiguity in what GCCRaven will do next, depending on the logic that GCCRaven uses for determining what the nearest vertiport is, feedback it provides (Woods & Balkin, 2018), and--quite possibly--any related or additional failures onboard the UAV. The operator of *SNLBlaze* must therefore determine in real-time if what they think is the controlling contingency procedure is in fact being followed.", id="explanation2")
131
- ], style={'width': '100%', 'border': '1px solid gray'}),
132
  html.Div([
133
  # html.Div("Next, input the relative path to your results folder, then click 'Submit'. This will load the data:", id='text2'),
134
  # dcc.Input(
@@ -140,7 +140,7 @@ app.layout = html.Div([
140
  # ),
141
  # html.Button('Submit', id='submit-button', n_clicks=0),
142
  # Create a dropdown menu with the subfolders as options
143
- html.Div("Once all subfolders are loaded (representing the different conditions you ran in WMC), you can select which one to plot:", id='text2'),
144
  dcc.Dropdown(
145
  id='subfolder-dropdown',
146
  value=None #subfolders[0] # Default value
@@ -225,16 +225,17 @@ def run_wmc(workAllocation, selected_time, ConAircraftResponse, OtherAircraftRes
225
  @app.callback(
226
  dash.dependencies.Output('subfolder-dropdown', 'options'),
227
  dash.dependencies.Output('variable-dropdown', 'options'),
228
- # dash.dependencies.Output('submit-button', 'n_clicks'), # Add this output to reset submit button clicks
229
- [dash.dependencies.Input('interval-component', 'n_intervals')],
 
230
  # [dash.dependencies.Input('path-input', 'value')],
231
  )
232
- def load_data(n_intervals):
233
  selected_path = "Results"
234
  print("selected path is",selected_path)
235
  global data_store
236
 
237
- if n_intervals > 0:
238
  if selected_path is None or not os.path.isdir(selected_path):
239
  return [], []
240
  subfolder_labels, data = parse_all_data(selected_path)
@@ -244,9 +245,9 @@ def load_data(n_intervals):
244
  # Store data in the global dictionary
245
  data_store = data
246
  labels = list(data[list(data.keys())[0]]['aircraft_data'][list(data[list(data.keys())[0]]['aircraft_data'].keys())[0]].columns.tolist()) # Extracting column names for the first aircraft-specific dataframe
247
- return subfolder_labels, labels
248
  else:
249
- return [], []
250
 
251
  # Define the callback to update the graphs based on the slider value
252
  @app.callback(
 
83
 
84
  # Create the layout for the app
85
  app.layout = html.Div([
86
+ html.Div([
87
+ html.B("This is an interactive demonstration of case study results to showcase the ability of modeling and simulation to help envision distributed work systems"),
88
+ html.Br(),
89
+ dcc.Markdown("This interactive demo was performed under NASA contract number 80NSSC23CA121.", id="explanation")
90
+ ], style={'width': '100%', 'border': '1px solid gray'}),
91
+ html.Div([
92
+ dcc.Markdown("It is envisioned that in future operatoins, each UAV is going to be controlled using a command and control (C2) link that allows communication with the remote pilot. This architecture can have potentially dangerous implications in the case of a failure of the command and control link. The UAV's are envisioned to be programmed with one or more contingency procedures that are to be executed in the case of a lost link. For example, to divert to and land at the nearest vertiport or continue along its preapproved route. This brings the question of how will the rest of the system need to react to the change in the aircraft trajectory. Is a system like this robust to an event like loss of link? ", id="explanation2")
93
+ ], style={'width': '100%', 'border': '1px solid gray'}),
94
+ html.Div([
95
+ dcc.Markdown("If the dropdown menu is empty please wait a few seconds to allow the data to load. If the data doesnt load then click the submit button to force reload the dropdown. The files that contain data will take a few seconds to load so please be patient.", id="explanation"),
96
+ html.Button('Submit', id='submit-button', n_clicks=0)
97
+ ], style={'width': '100%', 'border': '1px solid gray'}),
98
  html.Div([
99
  # html.Div([
100
  # html.Div("Select the desired input conditions, then click 'Simulate!':", id='text1'),
 
129
  # html.Br(),
130
  # html.Button('Simulate!', id='button', n_clicks=0),
131
  # ], style={'width': '50%', 'border': '1px solid gray'}),
 
 
 
 
 
 
 
 
 
 
 
 
132
  html.Div([
133
  # html.Div("Next, input the relative path to your results folder, then click 'Submit'. This will load the data:", id='text2'),
134
  # dcc.Input(
 
140
  # ),
141
  # html.Button('Submit', id='submit-button', n_clicks=0),
142
  # Create a dropdown menu with the subfolders as options
143
+ html.Div("Select which condition to load in the interactive graphs:", id='text2'),
144
  dcc.Dropdown(
145
  id='subfolder-dropdown',
146
  value=None #subfolders[0] # Default value
 
225
  @app.callback(
226
  dash.dependencies.Output('subfolder-dropdown', 'options'),
227
  dash.dependencies.Output('variable-dropdown', 'options'),
228
+ dash.dependencies.Output('submit-button', 'n_clicks'), # Add this output to reset submit button clicks
229
+ [dash.dependencies.Input('interval-component', 'n_intervals'),
230
+ dash.dependencies.Input('submit-button', 'n_clicks')],
231
  # [dash.dependencies.Input('path-input', 'value')],
232
  )
233
+ def load_data(n_intervals, n_clicks):
234
  selected_path = "Results"
235
  print("selected path is",selected_path)
236
  global data_store
237
 
238
+ if n_intervals > 0 or n_clicks > 0:
239
  if selected_path is None or not os.path.isdir(selected_path):
240
  return [], []
241
  subfolder_labels, data = parse_all_data(selected_path)
 
245
  # Store data in the global dictionary
246
  data_store = data
247
  labels = list(data[list(data.keys())[0]]['aircraft_data'][list(data[list(data.keys())[0]]['aircraft_data'].keys())[0]].columns.tolist()) # Extracting column names for the first aircraft-specific dataframe
248
+ return subfolder_labels, labels, 0
249
  else:
250
+ return [], [], 0
251
 
252
  # Define the callback to update the graphs based on the slider value
253
  @app.callback(