Degradation Modelling
This rover shows how degradation modelling can be performed to model the resilience of an engineered system over its entire lifecycle.
[1]:
import fmdtools.analyze as an
import fmdtools.sim.propagate as prop
import numpy as np
import matplotlib.pyplot as plt
import multiprocessing as mp
[2]:
from examples.rover.rover_degradation import DriveDegradation, PSFDegradationLong, PSFDegradationShort
Degradation models are defined independently of the fault model, but have attributes (e.g., functions) which may correspond to it directly.
Because degradation may only occur in specific functions/flows (and may not have inter-functional dependencies), it is not necessary for the degradation model to have the same
[3]:
deg_mdl = DriveDegradation()
deg_mdl
[3]:
drivedegradation DriveDegradation
- DriveDegradationStates(wear=0.0, corrosion=0.0, friction=0.0, drift=0.0)
[4]:
deg_mdl_hum_long = PSFDegradationLong()
deg_mdl_hum_long
[4]:
psfdegradationlong PSFDegradationLong
- PSFDegradationLongStates(experience=0.0)
[5]:
deg_mdl_hum_short = PSFDegradationShort()
deg_mdl_hum_short
[5]:
psfdegradationshort PSFDegradationShort
- PSFDegradationShortStates(fatigue=0.0, stress=0.0, experience=1.0)
[6]:
from examples.rover.rover_model import Rover, plot_map
fault_mdl = Rover(p={'ground':{'linetype': 'turn'}})
graph = fault_mdl.as_modelgraph()
fig, ax = graph.draw()

[7]:
fig.savefig("func_model.pdf", format="pdf", bbox_inches = 'tight', pad_inches = 0)
[8]:
endresults, mdlhist = prop.nominal(fault_mdl)
fig, ax = plot_map(fault_mdl, mdlhist)

[9]:
fig.savefig("sine_rover_environment.pdf", format="pdf", bbox_inches = 'tight', pad_inches = 0)
As shown, there are two degradation models here:
one which focusses solely on faults in the drive system, and
one which focusses on the human degradation of fatigue Below we simulate these to model to the degradation behaviors being modelled in this drive system.
Drive Degradation
[10]:
deg_mdl = DriveDegradation()
endresults, mdlhist = prop.nominal(deg_mdl)
fig, ax = mdlhist.plot_line('s.wear', 's.corrosion', 's.friction', 's.drift', 'r.s.corrode_rate', 'r.s.wear_rate', 'r.s.yaw_load')

The major behaviors are:
wear
corrosion
friction
drift
These behaviors result from the accumulation of the following rates over each time-step:
yaw_load
corrode_rate
wear_rate
These degradation behaviors have additionally been defined to simulate stochastically if desired:
[11]:
deg_mdl = DriveDegradation()
endresults, mdlhist = prop.nominal(deg_mdl, run_stochastic=True)
fig, ax = mdlhist.plot_line('s.wear', 's.corrosion', 's.friction', 's.drift', 'r.s.corrode_rate', 'r.s.wear_rate', 'r.s.yaw_load')

To get averages/percentages over a number of scenarios, we can view these behaviors over a given number of random seeds:
[12]:
from fmdtools.sim.sample import ParameterSample
ps = ParameterSample()
ps.add_variable_replicates([], replicates=100, seed_comb='independent')
endclasses_deg, mdlhists_deg = prop.parameter_sample(deg_mdl, ps, run_stochastic=True)
SCENARIOS COMPLETE: 100%|██████████| 100/100 [00:00<00:00, 163.40it/s]
[13]:
fig, ax = mdlhists_deg.plot_line('s.wear', 's.corrosion', 's.friction', 's.drift',
'r.s.corrode_rate', 'r.s.wear_rate', 'r.s.yaw_load',
title="", xlabel='lifecycle time (months)', aggregation = 'mean_bound')

[14]:
fig.savefig("drive_degradations.pdf", format="pdf", bbox_inches = 'tight', pad_inches = 0)
As shown, while wear and friction proceed monotonically, drift can go one way or another, meaning that whether the rover drifts left or right is basically up to chance. We can further look at slices of these distributions:
[15]:
fig, axs = mdlhists_deg.plot_metric_dist([1, 10, 20, 25], 's.wear', 's.corrosion', 's.friction', 's.drift', bins=10, alpha=0.5)

[16]:
from IPython.display import HTML
ani = mdlhists_deg.animate('plot_metric_dist_from',
plot_values=( 's.wear', 's.corrosion', 's.friction', 's.drift'),
bins=10, alpha=0.5)
HTML(ani.to_jshtml())
[16]:

Given the parameter information (friction and drift) that the degradation model produced, we can now simulate the model with this information over time in the nominal scenarios.
[17]:
from fmdtools.sim.sample import ParameterDomain, ParameterHistSample
from examples.rover.rover_model import RoverParam
We can do this using a ParameterHistSample
to sample the histories of the various scenarios at different times.
First, by defining a ParameterDomain
:
[18]:
rpd = ParameterDomain(RoverParam)
rpd.add_variables('degradation.friction', 'degradation.drift')
rpd(1, 10).degradation
[18]:
DegParam(friction=1.0, drift=10.0)
And then by defining the class:
[19]:
phs = ParameterHistSample(mdlhists_deg, 's.friction', 's.drift', paramdomain=rpd)
phs._get_repname('default', 1)
phs.add_hist_groups(reps= 10, ts = [1, 2, 5, 10])
len(phs.scenarios())
[19]:
40
Simulating the nominal scenario for these parameters:
[20]:
behave_endclasses, behave_mdlhists = prop.parameter_sample(fault_mdl, phs)
SCENARIOS COMPLETE: 100%|██████████| 40/40 [00:05<00:00, 7.44it/s]
[21]:
mdl=Rover(p={'degradation': {'friction': 1.0, 'drift': 0.1}})
mdl.fxns['drive'].m.get_faults()
[21]:
{'custom': Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(), units='sim'),
'elec_open': Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.transfer', 0.0),), units='sim'),
'stuck': Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.friction', 11.0),), units='sim'),
'stuck_left': Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.friction', 4.0), ('s.drift', -0.1)), units='sim'),
'stuck_right': Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.friction', 4.0), ('s.drift', 0.30000000000000004)), units='sim')}
[22]:
fig, ax = plot_map(fault_mdl, behave_mdlhists)

[23]:
behave_endclasses.state_probabilities('prob')
[23]:
{'nominal mission': 20.0, 'incomplete mission': 20.0}
[24]:
from fmdtools.analyze.tabulate import NominalEnvelope
[25]:
ne = NominalEnvelope(phs, behave_endclasses, 'classification',
'p.degradation.friction', 'p.degradation.drift',
func = lambda x: x == 'nominal mission')
ne.plot_scatter()
[25]:
(<Figure size 600x400 with 1 Axes>,
<Axes: xlabel='p.degradation.friction', ylabel='p.degradation.drift'>)

[26]:
ne = NominalEnvelope(phs, behave_endclasses, 'classification',
'inputparams.t', 'inputparams.rep',
func = lambda x: x == 'nominal mission')
ne.plot_scatter()
[26]:
(<Figure size 600x400 with 1 Axes>,
<Axes: xlabel='inputparams.t', ylabel='inputparams.rep'>)

[27]:
fig.savefig("drive_deg_envelope.pdf", format="pdf", bbox_inches = 'tight', pad_inches = 0)
As shown, as the time (and thus degradation) increases, the rover becomes more likely to be unable to complete the mission. In this case, it results in the rover not completing the mission in time.
[28]:
from fmdtools.sim.sample import SampleApproach
sa = SampleApproach(mdl)
sa.add_faultdomain('drive_faults', 'all_fxnclass_modes', 'Drive')
sa.add_faultsample('drive_faults', 'fault_phases', 'drive_faults',"start")
# sa.scenarios()
Note that faultdomains generated as a part of this model have fault parameters updated from the model parameters:
[35]:
sa.faultdomains['drive_faults'].faults
[35]:
{('drive',
'custom'): Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(), units='sim'),
('drive',
'elec_open'): Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.transfer', 0.0),), units='sim'),
('drive',
'stuck'): Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.friction', 11.0),), units='sim'),
('drive',
'stuck_left'): Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.friction', 4.0), ('s.drift', -0.1)), units='sim'),
('drive',
'stuck_right'): Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.friction', 4.0), ('s.drift', 0.30000000000000004)), units='sim')}
[29]:
sa.scenarios()
[29]:
[SingleFaultScenario(sequence={15.0: Injection(faults={'drive': ['custom']}, disturbances={})}, times=(15.0,), function='drive', fault='custom', rate=1.0, name='drive_custom_t15p0', time=15.0, phase='start'),
SingleFaultScenario(sequence={15.0: Injection(faults={'drive': ['elec_open']}, disturbances={})}, times=(15.0,), function='drive', fault='elec_open', rate=1.0, name='drive_elec_open_t15p0', time=15.0, phase='start'),
SingleFaultScenario(sequence={15.0: Injection(faults={'drive': ['stuck']}, disturbances={})}, times=(15.0,), function='drive', fault='stuck', rate=1.0, name='drive_stuck_t15p0', time=15.0, phase='start'),
SingleFaultScenario(sequence={15.0: Injection(faults={'drive': ['stuck_left']}, disturbances={})}, times=(15.0,), function='drive', fault='stuck_left', rate=1.0, name='drive_stuck_left_t15p0', time=15.0, phase='start'),
SingleFaultScenario(sequence={15.0: Injection(faults={'drive': ['stuck_right']}, disturbances={})}, times=(15.0,), function='drive', fault='stuck_right', rate=1.0, name='drive_stuck_right_t15p0', time=15.0, phase='start')]
[30]:
sa.mdl.fxns['drive'].m.get_fault_disturbances("elec_open")
[30]:
{'s.transfer': 0.0}
[61]:
fd = {'drive_faults': (('faults', ('drive', 'elec_open'), ('drive', 'stuck'), ('drive', 'stuck_left'), ('drive', 'stuck_right')), {})}
fs = {'drive_faults': (('fault_phases', 'drive_faults', "start"), {})}
ec_nest, hist_nest, app_nest = prop.nested_sample(mdl, phs, faultdomains=fd, faultsamples=fs, pool=mp.Pool(5))
NESTED SCENARIOS COMPLETE: 100%|██████████| 40/40 [00:15<00:00, 2.54it/s]
[62]:
app_nest
[62]:
{'hist_0': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_1': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_2': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_3': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_4': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_5': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_6': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_7': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_8': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_9': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_10': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_11': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_12': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_13': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_14': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_15': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_16': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_17': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_18': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_19': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_20': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_21': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_22': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_23': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_24': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_25': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_26': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_27': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_28': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_29': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_30': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_31': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_32': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_33': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_34': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_35': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_36': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_37': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_38': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults,
'hist_39': SampleApproach for rover with:
faultdomains: drive_faults
faultsamples: drive_faults}
[63]:
app_nest['hist_39'].faultdomains['drive_faults'].faults
[63]:
{('drive',
'elec_open'): Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.transfer', 0.0),), units='sim'),
('drive',
'stuck'): Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.friction', 10.314723549541055),), units='sim'),
('drive',
'stuck_left'): Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.friction', 3.314723549541055), ('s.drift', -0.024019195505379037)), units='sim'),
('drive',
'stuck_right'): Fault(prob=1.0, cost=0.0, phases=(('drive', 1.0), ('start', 1.0)), disturbances=(('s.friction', 3.314723549541055), ('s.drift', 0.375980804494621)), units='sim')}
Finally, we can also visualize simulate and then view the effect of the degradation on average resilience…
[64]:
ec_nest.hist_10.drive_elec_open_t15p0.endclass
[64]:
rate: 1.0
cost: 0
prob: 1.0
expected_cost: 0
in_bound: False
at_finish: False
line_dist: 1
num_modes: 0
end_dist: 26.748066406201854
tot_deviation: 0.22031574443307664
faults: array(0)
classification: incomplete mission
end_x: 2.227560704655789
end_y: 1.0445529960149111
endpt: array(2)
[65]:
from fmdtools.analyze.tabulate import NestedComparison
nc = NestedComparison(ec_nest, phs, ['inputparams.t'], app_nest, ['fault'], metrics=['tot_deviation', 'end_dist'], default_stat=np.mean, ci_metrics=['end_dist', 'tot_deviation'])
[66]:
nc
[66]:
{'tot_deviation': {(1, 'elec_open'): 0.14095288214845345, (1, 'stuck_right'): 0.21412236809395907, (1, 'stuck_left'): 0.24267070394544285, (1, 'stuck'): 0.14095288214845345, (2, 'elec_open'): 0.1789512655705427, (2, 'stuck_right'): 0.2164895946503275, (2, 'stuck_left'): 0.24219580711130817, (2, 'stuck'): 0.1789512655705427, (10, 'elec_open'): 0.2345818957647395, (10, 'stuck_right'): 0.2345818957647395, (10, 'stuck_left'): 0.2345818957647395, (10, 'stuck'): 0.2345818957647395, (5, 'elec_open'): 0.21370443638965603, (5, 'stuck_right'): 0.22176767329181826, (5, 'stuck_left'): 0.22756909629052907, (5, 'stuck'): 0.21370443638965603}, 'end_dist': {(1, 'elec_open'): 25.99258102674076, (1, 'stuck_right'): 25.401248415116143, (1, 'stuck_left'): 24.508968239389553, (1, 'stuck'): 25.894844300501422, (2, 'elec_open'): 26.579125060673107, (2, 'stuck_right'): 25.982815397051162, (2, 'stuck_left'): 25.666115791181152, (2, 'stuck'): 26.51946959448286, (10, 'elec_open'): 28.32999456168659, (10, 'stuck_right'): 28.32999456168659, (10, 'stuck_left'): 28.32999456168659, (10, 'stuck'): 28.32999456168659, (5, 'elec_open'): 27.765739000351545, (5, 'stuck_right'): 27.685194971663652, (5, 'stuck_left'): 27.62375881811696, (5, 'stuck'): 27.75571318554493}, 'end_dist_lb': {(1, 'elec_open'): 25.936438634818703, (1, 'stuck_right'): 25.254943052100828, (1, 'stuck_left'): 24.38938203679043, (1, 'stuck'): 25.83708224911041, (2, 'elec_open'): 26.147283665150567, (2, 'stuck_right'): 24.757027461774307, (2, 'stuck_left'): 24.798435012378256, (2, 'stuck'): 26.046147431443355, (10, 'elec_open'): 28.028364344332168, (10, 'stuck_right'): 28.014049376443094, (10, 'stuck_left'): 28.031778804122343, (10, 'stuck'): 28.02699801186488, (5, 'elec_open'): 27.110073725582897, (5, 'stuck_right'): 26.716755619622173, (5, 'stuck_left'): 26.404980763257367, (5, 'stuck'): 27.076255426378474}, 'tot_deviation_lb': {(1, 'elec_open'): 0.1263871921456202, (1, 'stuck_right'): 0.21246573729821355, (1, 'stuck_left'): 0.23533773928014048, (1, 'stuck'): 0.12563064818803316, (2, 'elec_open'): 0.15086276239048038, (2, 'stuck_right'): 0.21122378838030287, (2, 'stuck_left'): 0.22960596501013267, (2, 'stuck'): 0.15212593923911394, (10, 'elec_open'): 0.22275630286546264, (10, 'stuck_right'): 0.222761523378992, (10, 'stuck_left'): 0.22255719861849954, (10, 'stuck'): 0.22258003037258187, (5, 'elec_open'): 0.18120224994567014, (5, 'stuck_right'): 0.21410048311056565, (5, 'stuck_left'): 0.21797694266072767, (5, 'stuck'): 0.1831596714231249}, 'end_dist_ub': {(1, 'elec_open'): 26.03088543271915, (1, 'stuck_right'): 25.557557168831995, (1, 'stuck_left'): 24.581467483543815, (1, 'stuck'): 25.93346086311252, (2, 'elec_open'): 27.293884528449887, (2, 'stuck_right'): 26.8520724496678, (2, 'stuck_left'): 26.79405281470931, (2, 'stuck'): 27.24761038002429, (10, 'elec_open'): 28.481525833697667, (10, 'stuck_right'): 28.482065923476107, (10, 'stuck_left'): 28.481133267763333, (10, 'stuck'): 28.480553891027494, (5, 'elec_open'): 28.147889583099158, (5, 'stuck_right'): 28.129836553785875, (5, 'stuck_left'): 28.11509635463659, (5, 'stuck'): 28.149520226029118}, 'tot_deviation_ub': {(1, 'elec_open'): 0.1579244749844601, (1, 'stuck_right'): 0.21686991108571613, (1, 'stuck_left'): 0.2529354032432877, (1, 'stuck'): 0.15753179787010116, (2, 'elec_open'): 0.20302071136975047, (2, 'stuck_right'): 0.22140263561186613, (2, 'stuck_left'): 0.25631719298352273, (2, 'stuck'): 0.2034079213740488, (10, 'elec_open'): 0.2470127349616676, (10, 'stuck_right'): 0.24692538919086365, (10, 'stuck_left'): 0.24663813998207218, (10, 'stuck'): 0.24670290331070513, (5, 'elec_open'): 0.22726719698278505, (5, 'stuck_right'): 0.232244775423006, (5, 'stuck_left'): 0.24038501613817276, (5, 'stuck'): 0.22777593987146047}}
[67]:
nc.sort_by_factor("fault")
nc.sort_by_factor("inputparams.t")
fig, ax = nc.as_plots('end_dist', 'tot_deviation', figsize=(8,4))

[68]:
nc
[68]:
{'tot_deviation': {(1, 'elec_open'): 0.14095288214845345, (1, 'stuck'): 0.14095288214845345, (1, 'stuck_left'): 0.24267070394544285, (1, 'stuck_right'): 0.21412236809395907, (2, 'elec_open'): 0.1789512655705427, (2, 'stuck'): 0.1789512655705427, (2, 'stuck_left'): 0.24219580711130817, (2, 'stuck_right'): 0.2164895946503275, (5, 'elec_open'): 0.21370443638965603, (5, 'stuck'): 0.21370443638965603, (5, 'stuck_left'): 0.22756909629052907, (5, 'stuck_right'): 0.22176767329181826, (10, 'elec_open'): 0.2345818957647395, (10, 'stuck'): 0.2345818957647395, (10, 'stuck_left'): 0.2345818957647395, (10, 'stuck_right'): 0.2345818957647395}, 'end_dist': {(1, 'elec_open'): 25.99258102674076, (1, 'stuck'): 25.894844300501422, (1, 'stuck_left'): 24.508968239389553, (1, 'stuck_right'): 25.401248415116143, (2, 'elec_open'): 26.579125060673107, (2, 'stuck'): 26.51946959448286, (2, 'stuck_left'): 25.666115791181152, (2, 'stuck_right'): 25.982815397051162, (5, 'elec_open'): 27.765739000351545, (5, 'stuck'): 27.75571318554493, (5, 'stuck_left'): 27.62375881811696, (5, 'stuck_right'): 27.685194971663652, (10, 'elec_open'): 28.32999456168659, (10, 'stuck'): 28.32999456168659, (10, 'stuck_left'): 28.32999456168659, (10, 'stuck_right'): 28.32999456168659}, 'end_dist_lb': {(1, 'elec_open'): 25.936438634818703, (1, 'stuck'): 25.83708224911041, (1, 'stuck_left'): 24.38938203679043, (1, 'stuck_right'): 25.254943052100828, (2, 'elec_open'): 26.147283665150567, (2, 'stuck'): 26.046147431443355, (2, 'stuck_left'): 24.798435012378256, (2, 'stuck_right'): 24.757027461774307, (5, 'elec_open'): 27.110073725582897, (5, 'stuck'): 27.076255426378474, (5, 'stuck_left'): 26.404980763257367, (5, 'stuck_right'): 26.716755619622173, (10, 'elec_open'): 28.028364344332168, (10, 'stuck'): 28.02699801186488, (10, 'stuck_left'): 28.031778804122343, (10, 'stuck_right'): 28.014049376443094}, 'tot_deviation_lb': {(1, 'elec_open'): 0.1263871921456202, (1, 'stuck'): 0.12563064818803316, (1, 'stuck_left'): 0.23533773928014048, (1, 'stuck_right'): 0.21246573729821355, (2, 'elec_open'): 0.15086276239048038, (2, 'stuck'): 0.15212593923911394, (2, 'stuck_left'): 0.22960596501013267, (2, 'stuck_right'): 0.21122378838030287, (5, 'elec_open'): 0.18120224994567014, (5, 'stuck'): 0.1831596714231249, (5, 'stuck_left'): 0.21797694266072767, (5, 'stuck_right'): 0.21410048311056565, (10, 'elec_open'): 0.22275630286546264, (10, 'stuck'): 0.22258003037258187, (10, 'stuck_left'): 0.22255719861849954, (10, 'stuck_right'): 0.222761523378992}, 'end_dist_ub': {(1, 'elec_open'): 26.03088543271915, (1, 'stuck'): 25.93346086311252, (1, 'stuck_left'): 24.581467483543815, (1, 'stuck_right'): 25.557557168831995, (2, 'elec_open'): 27.293884528449887, (2, 'stuck'): 27.24761038002429, (2, 'stuck_left'): 26.79405281470931, (2, 'stuck_right'): 26.8520724496678, (5, 'elec_open'): 28.147889583099158, (5, 'stuck'): 28.149520226029118, (5, 'stuck_left'): 28.11509635463659, (5, 'stuck_right'): 28.129836553785875, (10, 'elec_open'): 28.481525833697667, (10, 'stuck'): 28.480553891027494, (10, 'stuck_left'): 28.481133267763333, (10, 'stuck_right'): 28.482065923476107}, 'tot_deviation_ub': {(1, 'elec_open'): 0.1579244749844601, (1, 'stuck'): 0.15753179787010116, (1, 'stuck_left'): 0.2529354032432877, (1, 'stuck_right'): 0.21686991108571613, (2, 'elec_open'): 0.20302071136975047, (2, 'stuck'): 0.2034079213740488, (2, 'stuck_left'): 0.25631719298352273, (2, 'stuck_right'): 0.22140263561186613, (5, 'elec_open'): 0.22726719698278505, (5, 'stuck'): 0.22777593987146047, (5, 'stuck_left'): 0.24038501613817276, (5, 'stuck_right'): 0.232244775423006, (10, 'elec_open'): 0.2470127349616676, (10, 'stuck'): 0.24670290331070513, (10, 'stuck_left'): 0.24663813998207218, (10, 'stuck_right'): 0.24692538919086365}}
[ ]:
# fig.savefig("drive_resilience_degradation.pdf", format="pdf", bbox_inches = 'tight', pad_inches = 0)
As shown, while there is some resilience early in the lifecycle (resulting in a small proportion of faults being recovered), this resilience goes away with degradation.
Human Degradation
We can also perform this assessment for the human error model, which is split up into two parts:
long term “degradation” of experience over months
short term “degradation” of stress and fatigue over a day
[69]:
psf_long = PSFDegradationLong()
endresults, hist_psf_long = prop.nominal(psf_long)
[70]:
hist_psf_long.plot_line('s.experience')
[70]:
(<Figure size 300x200 with 1 Axes>,
[<Axes: title={'center': 's.experience'}, xlabel='time'>])

[71]:
hist_psf_long.plot_line('s.experience')
[71]:
(<Figure size 300x200 with 1 Axes>,
[<Axes: title={'center': 's.experience'}, xlabel='time'>])

[72]:
from examples.rover.rover_degradation import LongParams
pd_hl = ParameterDomain(LongParams)
pd_hl.add_variable("experience_param", var_lim=())
pd_hl
[72]:
ParameterDomain with:
- variables: {'experience_param': ()}
- constants: {}
- parameter_initializer: LongParams
[73]:
pd_hl(10)
[73]:
LongParams(experience_param=10.0, training_frequency=8.0, experience_scale_max=10.0)
[74]:
ps_hl = ParameterSample(pd_hl)
xs = np.random.default_rng(seed=101).gamma(1,1.9,101)
# round so that dist is 0-10
xs = [min(x, 9.9) for x in xs]
weight = 1/len(xs)
for x in xs:
ps_hl.add_variable_scenario(x, weight=weight)
ps_hl
[74]:
ParameterSample of scenarios:
- var_0
- var_1
- var_2
- var_3
- var_4
- var_5
- var_6
- var_7
- var_8
- var_9
- ... (101 total)
[75]:
ec_psf_long, hist_psf_long= prop.parameter_sample(psf_long, ps_hl, run_stochastic=True)
SCENARIOS COMPLETE: 100%|██████████| 101/101 [00:00<00:00, 391.74it/s]
[76]:
hist_psf_long.plot_line('s.experience')
[76]:
(<Figure size 300x200 with 1 Axes>,
[<Axes: title={'center': 's.experience'}, xlabel='time'>])

[77]:
fig, axs = hist_psf_long.plot_metric_dist([0, 40, 50, 60, 100], 's.experience', bins=20, alpha=0.5, figsize=(8,4))

[ ]:
# fig.savefig("experience_degradation.pdf", format="pdf", bbox_inches = 'tight', pad_inches = 0)
Short-term degradation
[78]:
psf_short = PSFDegradationShort()
er, hist_short = prop.nominal(psf_short)
fig, axs = hist_short.plot_line('s.fatigue', 's.stress')

short-term degradation (over no external params)
[79]:
ps_psf_short = ParameterSample()
ps_psf_short.add_variable_replicates([], replicates=25)
ps_psf_short.scenarios()
[79]:
[ParameterScenario(sequence={}, times=(), p={}, r={'seed': 3841784089}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep0_var_0'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 3990088182}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep1_var_1'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 2037256057}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep2_var_2'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 1496335244}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep3_var_3'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 3135252741}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep4_var_4'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 2072519789}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep5_var_5'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 1089731268}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep6_var_6'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 3586110195}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep7_var_7'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 553433369}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep8_var_8'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 1797091704}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep9_var_9'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 3845142631}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep10_var_10'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 2511351340}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep11_var_11'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 1038217732}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep12_var_12'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 2636313351}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep13_var_13'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 1124707710}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep14_var_14'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 2557170247}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep15_var_15'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 3395567489}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep16_var_16'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 2551447729}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep17_var_17'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 1586590726}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep18_var_18'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 1902271262}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep19_var_19'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 1166228582}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep20_var_20'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 3638465723}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep21_var_21'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 4141846376}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep22_var_22'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 3846510153}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep23_var_23'),
ParameterScenario(sequence={}, times=(), p={}, r={'seed': 3944289532}, sp={}, prob=0.04, inputparams={}, rangeid='', name='rep24_var_24')]
[80]:
ec_psf_short, hist_psf_short = prop.parameter_sample(psf_short, ps_psf_short, run_stochastic=True)
fig, axs = hist_psf_short.plot_line('s.fatigue', 's.stress', 'r.s.fatigue_param', aggregation="percentile")
SCENARIOS COMPLETE: 100%|██████████| 25/25 [00:00<00:00, 782.86it/s]

short-term degradation over long-term params
[81]:
from examples.rover.rover_degradation import PSFShortParams
pd_short_long = ParameterDomain(PSFShortParams)
pd_short_long.add_variable("experience")
ps_short_long = ParameterHistSample(hist_psf_long, 's.experience', paramdomain=pd_short_long)
ps_short_long.add_hist_groups(reps= 10, ts = [0, 40, 50, 60, 100])
# note - need to add a way to combine replicates (seeds) over replicates (input times/groups/)
[82]:
pd_short_long(10)
[82]:
PSFShortParams(experience=10.0, stress_param=0.0, fatigue_param=1.0)
[83]:
ps_short_long.scenarios()
[83]:
[ParameterScenario(sequence={}, times=(), p={'experience': 0.0147852093576427}, r={'seed': 2421052720}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_0', 't': 0}, rangeid='', name='hist_0'),
ParameterScenario(sequence={}, times=(), p={'experience': 4.355521540650882}, r={'seed': 2421052720}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_0', 't': 40}, rangeid='', name='hist_1'),
ParameterScenario(sequence={}, times=(), p={'experience': 7.926159730949486}, r={'seed': 2421052720}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_0', 't': 50}, rangeid='', name='hist_2'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.498252713597697}, r={'seed': 2421052720}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_0', 't': 60}, rangeid='', name='hist_3'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.999122355752638}, r={'seed': 2421052720}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_0', 't': 100}, rangeid='', name='hist_4'),
ParameterScenario(sequence={}, times=(), p={'experience': 0.003707397123126116}, r={'seed': 1307049715}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_1', 't': 0}, rangeid='', name='hist_5'),
ParameterScenario(sequence={}, times=(), p={'experience': 1.6197044104299785}, r={'seed': 1307049715}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_1', 't': 40}, rangeid='', name='hist_6'),
ParameterScenario(sequence={}, times=(), p={'experience': 4.890918517769909}, r={'seed': 1307049715}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_1', 't': 50}, rangeid='', name='hist_7'),
ParameterScenario(sequence={}, times=(), p={'experience': 8.258304854924205}, r={'seed': 1307049715}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_1', 't': 60}, rangeid='', name='hist_8'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.996496965739947}, r={'seed': 1307049715}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_1', 't': 100}, rangeid='', name='hist_9'),
ParameterScenario(sequence={}, times=(), p={'experience': 0.0040328347821078905}, r={'seed': 1348862178}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_2', 't': 0}, rangeid='', name='hist_10'),
ParameterScenario(sequence={}, times=(), p={'experience': 1.7372307652324728}, r={'seed': 1348862178}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_2', 't': 40}, rangeid='', name='hist_11'),
ParameterScenario(sequence={}, times=(), p={'experience': 5.1013174827709795}, r={'seed': 1348862178}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_2', 't': 50}, rangeid='', name='hist_12'),
ParameterScenario(sequence={}, times=(), p={'experience': 8.376073873906922}, r={'seed': 1348862178}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_2', 't': 60}, rangeid='', name='hist_13'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.996779663860996}, r={'seed': 1348862178}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_2', 't': 100}, rangeid='', name='hist_14'),
ParameterScenario(sequence={}, times=(), p={'experience': 0.004105645810848513}, r={'seed': 353223147}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_3', 't': 0}, rangeid='', name='hist_15'),
ParameterScenario(sequence={}, times=(), p={'experience': 1.7630764252943243}, r={'seed': 353223147}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_3', 't': 40}, rangeid='', name='hist_16'),
ParameterScenario(sequence={}, times=(), p={'experience': 5.1460417740129625}, r={'seed': 353223147}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_3', 't': 50}, rangeid='', name='hist_17'),
ParameterScenario(sequence={}, times=(), p={'experience': 8.40027584188355}, r={'seed': 353223147}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_3', 't': 60}, rangeid='', name='hist_18'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.996836779451714}, r={'seed': 353223147}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_3', 't': 100}, rangeid='', name='hist_19'),
ParameterScenario(sequence={}, times=(), p={'experience': 0.0037569908838189204}, r={'seed': 3496035439}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_4', 't': 0}, rangeid='', name='hist_20'),
ParameterScenario(sequence={}, times=(), p={'experience': 1.6378293230060559}, r={'seed': 3496035439}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_4', 't': 40}, rangeid='', name='hist_21'),
ParameterScenario(sequence={}, times=(), p={'experience': 4.924140166096661}, r={'seed': 3496035439}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_4', 't': 50}, rangeid='', name='hist_22'),
ParameterScenario(sequence={}, times=(), p={'experience': 8.277342402550868}, r={'seed': 3496035439}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_4', 't': 60}, rangeid='', name='hist_23'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.996543208332358}, r={'seed': 3496035439}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_4', 't': 100}, rangeid='', name='hist_24'),
ParameterScenario(sequence={}, times=(), p={'experience': 0.0035576861892378416}, r={'seed': 1762629579}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_5', 't': 0}, rangeid='', name='hist_25'),
ParameterScenario(sequence={}, times=(), p={'experience': 1.5645112885019485}, r={'seed': 1762629579}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_5', 't': 40}, rangeid='', name='hist_26'),
ParameterScenario(sequence={}, times=(), p={'experience': 4.7879419002260555}, r={'seed': 1762629579}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_5', 't': 50}, rangeid='', name='hist_27'),
ParameterScenario(sequence={}, times=(), p={'experience': 8.198196150411718}, r={'seed': 1762629579}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_5', 't': 60}, rangeid='', name='hist_28'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.996349553773157}, r={'seed': 1762629579}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_5', 't': 100}, rangeid='', name='hist_29'),
ParameterScenario(sequence={}, times=(), p={'experience': 0.006841983111062025}, r={'seed': 2413961462}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_6', 't': 0}, rangeid='', name='hist_30'),
ParameterScenario(sequence={}, times=(), p={'experience': 2.629719998704038}, r={'seed': 2413961462}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_6', 't': 40}, rangeid='', name='hist_31'),
ParameterScenario(sequence={}, times=(), p={'experience': 6.386297198063246}, r={'seed': 2413961462}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_6', 't': 50}, rangeid='', name='hist_32'),
ParameterScenario(sequence={}, times=(), p={'experience': 8.974697629346908}, r={'seed': 2413961462}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_6', 't': 60}, rangeid='', name='hist_33'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.99810213629282}, r={'seed': 2413961462}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_6', 't': 100}, rangeid='', name='hist_34'),
ParameterScenario(sequence={}, times=(), p={'experience': 0.003743727872745982}, r={'seed': 2346178977}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_7', 't': 0}, rangeid='', name='hist_35'),
ParameterScenario(sequence={}, times=(), p={'experience': 1.632989788946346}, r={'seed': 2346178977}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_7', 't': 40}, rangeid='', name='hist_36'),
ParameterScenario(sequence={}, times=(), p={'experience': 4.915297962215212}, r={'seed': 2346178977}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_7', 't': 50}, rangeid='', name='hist_37'),
ParameterScenario(sequence={}, times=(), p={'experience': 8.272292001415185}, r={'seed': 2346178977}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_7', 't': 60}, rangeid='', name='hist_38'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.996530961505558}, r={'seed': 2346178977}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_7', 't': 100}, rangeid='', name='hist_39'),
ParameterScenario(sequence={}, times=(), p={'experience': 0.014556312791561945}, r={'seed': 43528966}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_8', 't': 0}, rangeid='', name='hist_40'),
ParameterScenario(sequence={}, times=(), p={'experience': 4.317146303403044}, r={'seed': 43528966}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_8', 't': 40}, rangeid='', name='hist_41'),
ParameterScenario(sequence={}, times=(), p={'experience': 7.900357779757452}, r={'seed': 43528966}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_8', 't': 50}, rangeid='', name='hist_42'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.490753491558548}, r={'seed': 43528966}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_8', 't': 60}, rangeid='', name='hist_43'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.99910853568146}, r={'seed': 43528966}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_8', 't': 100}, rangeid='', name='hist_44'),
ParameterScenario(sequence={}, times=(), p={'experience': 0.003917700316414757}, r={'seed': 549718256}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_9', 't': 0}, rangeid='', name='hist_45'),
ParameterScenario(sequence={}, times=(), p={'experience': 1.6960297046671722}, r={'seed': 549718256}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_9', 't': 40}, rangeid='', name='hist_46'),
ParameterScenario(sequence={}, times=(), p={'experience': 5.028890434716651}, r={'seed': 549718256}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_9', 't': 50}, rangeid='', name='hist_47'),
ParameterScenario(sequence={}, times=(), p={'experience': 8.336273464537053}, r={'seed': 549718256}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_9', 't': 60}, rangeid='', name='hist_48'),
ParameterScenario(sequence={}, times=(), p={'experience': 9.996685016931059}, r={'seed': 549718256}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'var_9', 't': 100}, rangeid='', name='hist_49')]
[84]:
ec, hist_short_long = prop.parameter_sample(psf_short, ps_short_long, run_stochastic=True)
SCENARIOS COMPLETE: 100%|██████████| 50/50 [00:00<00:00, 837.18it/s]
[85]:
fig, axs = hist_short_long.plot_line('s.fatigue', 's.stress', 'r.s.fatigue_param', aggregation="percentile")

[ ]:
# fig.savefig("stress_degradation.pdf", format="pdf", bbox_inches = 'tight', pad_inches = 0)
Now sample in the model:
[86]:
from examples.rover.rover_model_human import RoverHuman, RoverHumanParam
pd_comb_mdl = ParameterDomain(RoverHumanParam)
# pd_comb_mdl.add_constant('drive_modes', {"mode_options": "manual"})
pd_comb_mdl.add_variable("psfs.fatigue")
pd_comb_mdl.add_variables("psfs.stress")
pd_comb_mdl(1,1)
[86]:
RoverHumanParam(ground=GroundParam(linetype='sine', amp=1.0, period=6.283185307179586, radius=20.0, x_start=10.0, y_end=10.0, x_min=0.0, x_max=30.0, x_res=0.1, path_buffer_on=0.2, path_buffer_poor=0.3, path_buffer_near=0.4, dest_buffer_on=1.0, dest_buffer_near=2.0), correction=ResCorrection(ub_f=10.0, lb_f=-1.0, ub_t=10.0, lb_t=0.0, ub_d=2.0, lb_d=-2.0, cor_d=0.0, cor_t=0.0, cor_f=0.0), degradation=DegParam(friction=0.0, drift=0.0), drive_modes={'mode_options': 'set'}, psfs=PSFParam(fatigue=1.0, stress=1.0))
[87]:
ps_comb_mdl = ParameterHistSample(hist_short_long, "s.fatigue", "s.stress", paramdomain=pd_comb_mdl)
ps_comb_mdl.add_hist_groups(reps= 10, ts = [0, 1, 3, 5, 6, 8])
ps_comb_mdl.scenarios()
[87]:
[ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 2.9102389673993363, 'stress': 0.0}}, r={'seed': 1090260601}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_0', 't': 0}, rangeid='', name='hist_0'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.583299529039254, 'stress': 1.0}}, r={'seed': 1090260601}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_0', 't': 1}, rangeid='', name='hist_1'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 8.570396934483995, 'stress': 100.0}}, r={'seed': 1090260601}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_0', 't': 3}, rangeid='', name='hist_2'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 100.0}}, r={'seed': 1090260601}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_0', 't': 5}, rangeid='', name='hist_3'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 100.0}}, r={'seed': 1090260601}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_0', 't': 6}, rangeid='', name='hist_4'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 100.0}}, r={'seed': 1090260601}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_0', 't': 8}, rangeid='', name='hist_5'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 2.9102389673993363, 'stress': 0.0}}, r={'seed': 1243589115}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_1', 't': 0}, rangeid='', name='hist_6'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.583299529039254, 'stress': 1.0}}, r={'seed': 1243589115}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_1', 't': 1}, rangeid='', name='hist_7'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 8.570396934483995, 'stress': 3.0}}, r={'seed': 1243589115}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_1', 't': 3}, rangeid='', name='hist_8'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 6.0}}, r={'seed': 1243589115}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_1', 't': 5}, rangeid='', name='hist_9'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 8.0}}, r={'seed': 1243589115}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_1', 't': 6}, rangeid='', name='hist_10'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 15.0}}, r={'seed': 1243589115}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_1', 't': 8}, rangeid='', name='hist_11'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 2.9102389673993363, 'stress': 0.0}}, r={'seed': 2741282842}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_2', 't': 0}, rangeid='', name='hist_12'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.583299529039254, 'stress': 1.0}}, r={'seed': 2741282842}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_2', 't': 1}, rangeid='', name='hist_13'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 8.570396934483995, 'stress': 3.0}}, r={'seed': 2741282842}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_2', 't': 3}, rangeid='', name='hist_14'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 5.0}}, r={'seed': 2741282842}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_2', 't': 5}, rangeid='', name='hist_15'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 6.0}}, r={'seed': 2741282842}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_2', 't': 6}, rangeid='', name='hist_16'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 10.0}}, r={'seed': 2741282842}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_2', 't': 8}, rangeid='', name='hist_17'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 2.9102389673993363, 'stress': 0.0}}, r={'seed': 4115176561}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_3', 't': 0}, rangeid='', name='hist_18'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.583299529039254, 'stress': 1.0}}, r={'seed': 4115176561}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_3', 't': 1}, rangeid='', name='hist_19'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 8.570396934483995, 'stress': 3.0}}, r={'seed': 4115176561}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_3', 't': 3}, rangeid='', name='hist_20'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 5.0}}, r={'seed': 4115176561}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_3', 't': 5}, rangeid='', name='hist_21'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 6.0}}, r={'seed': 4115176561}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_3', 't': 6}, rangeid='', name='hist_22'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 9.0}}, r={'seed': 4115176561}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_3', 't': 8}, rangeid='', name='hist_23'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 2.9102389673993363, 'stress': 0.0}}, r={'seed': 2429806230}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_4', 't': 0}, rangeid='', name='hist_24'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.583299529039254, 'stress': 1.0}}, r={'seed': 2429806230}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_4', 't': 1}, rangeid='', name='hist_25'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 8.570396934483995, 'stress': 3.0}}, r={'seed': 2429806230}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_4', 't': 3}, rangeid='', name='hist_26'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 5.0}}, r={'seed': 2429806230}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_4', 't': 5}, rangeid='', name='hist_27'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 6.0}}, r={'seed': 2429806230}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_4', 't': 6}, rangeid='', name='hist_28'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 8.0}}, r={'seed': 2429806230}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_4', 't': 8}, rangeid='', name='hist_29'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.456026884573247, 'stress': 0.0}}, r={'seed': 1815897288}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_5', 't': 0}, rangeid='', name='hist_30'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 5.366448258922811, 'stress': 1.0}}, r={'seed': 1815897288}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_5', 't': 1}, rangeid='', name='hist_31'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 6.190654561590499, 'stress': 100.0}}, r={'seed': 1815897288}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_5', 't': 3}, rangeid='', name='hist_32'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 100.0}}, r={'seed': 1815897288}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_5', 't': 5}, rangeid='', name='hist_33'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 100.0}}, r={'seed': 1815897288}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_5', 't': 6}, rangeid='', name='hist_34'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 100.0}}, r={'seed': 1815897288}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_5', 't': 8}, rangeid='', name='hist_35'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.456026884573247, 'stress': 0.0}}, r={'seed': 2344098998}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_6', 't': 0}, rangeid='', name='hist_36'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 5.366448258922811, 'stress': 1.0}}, r={'seed': 2344098998}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_6', 't': 1}, rangeid='', name='hist_37'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 6.190654561590499, 'stress': 4.0}}, r={'seed': 2344098998}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_6', 't': 3}, rangeid='', name='hist_38'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 14.0}}, r={'seed': 2344098998}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_6', 't': 5}, rangeid='', name='hist_39'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 25.0}}, r={'seed': 2344098998}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_6', 't': 6}, rangeid='', name='hist_40'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 70.0}}, r={'seed': 2344098998}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_6', 't': 8}, rangeid='', name='hist_41'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.456026884573247, 'stress': 0.0}}, r={'seed': 2126485062}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_7', 't': 0}, rangeid='', name='hist_42'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 5.366448258922811, 'stress': 1.0}}, r={'seed': 2126485062}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_7', 't': 1}, rangeid='', name='hist_43'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 6.190654561590499, 'stress': 3.0}}, r={'seed': 2126485062}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_7', 't': 3}, rangeid='', name='hist_44'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 6.0}}, r={'seed': 2126485062}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_7', 't': 5}, rangeid='', name='hist_45'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 8.0}}, r={'seed': 2126485062}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_7', 't': 6}, rangeid='', name='hist_46'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 14.0}}, r={'seed': 2126485062}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_7', 't': 8}, rangeid='', name='hist_47'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.456026884573247, 'stress': 0.0}}, r={'seed': 402795975}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_8', 't': 0}, rangeid='', name='hist_48'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 5.366448258922811, 'stress': 1.0}}, r={'seed': 402795975}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_8', 't': 1}, rangeid='', name='hist_49'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 6.190654561590499, 'stress': 3.0}}, r={'seed': 402795975}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_8', 't': 3}, rangeid='', name='hist_50'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 5.0}}, r={'seed': 402795975}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_8', 't': 5}, rangeid='', name='hist_51'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 6.0}}, r={'seed': 402795975}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_8', 't': 6}, rangeid='', name='hist_52'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 9.0}}, r={'seed': 402795975}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_8', 't': 8}, rangeid='', name='hist_53'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 4.456026884573247, 'stress': 0.0}}, r={'seed': 683621307}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_9', 't': 0}, rangeid='', name='hist_54'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 5.366448258922811, 'stress': 1.0}}, r={'seed': 683621307}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_9', 't': 1}, rangeid='', name='hist_55'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 6.190654561590499, 'stress': 3.0}}, r={'seed': 683621307}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_9', 't': 3}, rangeid='', name='hist_56'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 5.0}}, r={'seed': 683621307}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_9', 't': 5}, rangeid='', name='hist_57'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 6.0}}, r={'seed': 683621307}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_9', 't': 6}, rangeid='', name='hist_58'),
ParameterScenario(sequence={}, times=(), p={'psfs': {'fatigue': 10.0, 'stress': 8.0}}, r={'seed': 683621307}, sp={}, prob=1.0, inputparams={'comp_group': 'default', 'rep': 'hist_9', 't': 8}, rangeid='', name='hist_59')]
[88]:
mdl_hum = RoverHuman()
[89]:
ec, hist = prop.nominal(mdl_hum)
plot_map(mdl_hum, hist)
ec
[89]:
endclass:
--rate: 1.0
--cost: 0
--prob: 1.0
--expected_cost: 0
--in_bound: True
--at_finish: True
--line_dist: 1
--num_modes: 0
--end_dist: 0.0
--tot_deviation: 0.11859644458085598
--faults: array(0)
--classification: nominal mission
--end_x: 29.254775331608617
--end_y: -0.7827640334587979
--endpt: array(2)

[90]:
ec_comb, hist_comb = prop.parameter_sample(mdl_hum, ps_comb_mdl)
SCENARIOS COMPLETE: 100%|██████████| 60/60 [00:14<00:00, 4.07it/s]
[91]:
fig, ax = plot_map(mdl_hum, hist_comb)

[92]:
hist_comb.plot_line('flows.psfs.s.attention', 'flows.motor_control.s.rpower', 'flows.motor_control.s.lpower')
[92]:
(<Figure size 600x400 with 4 Axes>,
array([<Axes: title={'center': 'flows.psfs.s.attention'}, xlabel=' '>,
<Axes: title={'center': 'flows.motor_control.s.rpower'}, xlabel='time'>,
<Axes: title={'center': 'flows.motor_control.s.lpower'}, xlabel='time'>,
<Axes: >], dtype=object))

[93]:
ne = NominalEnvelope(ps_comb_mdl, ec_comb, 'at_finish',
'p.psfs.fatigue', 'p.psfs.stress',
func=lambda x: x == True)
ne.plot_scatter()
[93]:
(<Figure size 600x400 with 1 Axes>,
<Axes: xlabel='p.psfs.fatigue', ylabel='p.psfs.stress'>)

(note, this is different in the turn case because of the long straightaway)
[94]:
mdl_hum = RoverHuman(p={'ground': {'linetype': 'turn'}})
ec, hist = prop.nominal(mdl_hum)
plot_map(mdl_hum, hist)
ec
[94]:
endclass:
--rate: 1.0
--cost: 0
--prob: 1.0
--expected_cost: 0
--in_bound: True
--at_finish: True
--line_dist: 1
--num_modes: 0
--end_dist: 0.0
--tot_deviation: 0.005246344989065292
--faults: array(0)
--classification: nominal mission
--end_x: 29.813614084369863
--end_y: 17.26588133276667
--endpt: array(2)

[95]:
ec_comb, hist_comb = prop.parameter_sample(mdl_hum, ps_comb_mdl)
SCENARIOS COMPLETE: 100%|██████████| 60/60 [00:15<00:00, 3.98it/s]
[96]:
fig, ax = plot_map(mdl_hum, hist_comb)

[97]:
hist_comb.plot_line('flows.psfs.s.attention', 'flows.motor_control.s.rpower', 'flows.motor_control.s.lpower')
[97]:
(<Figure size 600x400 with 4 Axes>,
array([<Axes: title={'center': 'flows.psfs.s.attention'}, xlabel=' '>,
<Axes: title={'center': 'flows.motor_control.s.rpower'}, xlabel='time'>,
<Axes: title={'center': 'flows.motor_control.s.lpower'}, xlabel='time'>,
<Axes: >], dtype=object))

[98]:
ne = NominalEnvelope(ps_comb_mdl, ec_comb, 'at_finish',
'p.psfs.fatigue', 'p.psfs.stress',
func=lambda x: x == True)
ne.plot_scatter()
[98]:
(<Figure size 600x400 with 1 Axes>,
<Axes: xlabel='p.psfs.fatigue', ylabel='p.psfs.stress'>)

We can thus see how degradation time effects this:
[99]:
ne = NominalEnvelope(ps_comb_mdl, ec_comb, 'at_finish',
'inputparams.t', 'inputparams.rep',
func=lambda x: x == True)
ne.plot_scatter()
[99]:
(<Figure size 600x400 with 1 Axes>,
<Axes: xlabel='inputparams.t', ylabel='inputparams.rep'>)

To re-implement:
Need to be able to jointly plot/tabulate by single-day time + multi-day time
Combining approaches?
As for the human resilience:
[101]:
ec_nest, hist_nest, app_nest = prop.nested_sample(mdl, phs, faultdomains=fd, faultsamples=fs, pool=mp.Pool(5))
NESTED SCENARIOS COMPLETE: 100%|██████████| 40/40 [00:15<00:00, 2.62it/s]
[102]:
nc = NestedComparison(ec_nest, phs, ['inputparams.t'], app_nest, ['fault'], metrics=['tot_deviation', 'end_dist'], default_stat=np.mean, ci_metrics=['end_dist', 'tot_deviation'])
[103]:
nc.sort_by_factor("fault")
nc.sort_by_factor("inputparams.t")
fig, ax = nc.as_plots('end_dist', 'tot_deviation', figsize=(8,4))

[ ]:
# fig.savefig("human_resilience_degradation.pdf", format="pdf", bbox_inches = 'tight', pad_inches = 0)
Combined Degradation
Idea: make same resilience plots as before but with degradation of resilience to drive faults at 0, 4, and 8 hours of fatigue.
Need method of doing this:
take params for one and replace with the other (kind of hacky and requires independence)
create composite of both? (how do you determine the merge between output params?)
use a combined method with both histories as input and sample over t_life and t_day (use this one)
[ ]:
Resilience assessment
[ ]: