class SystemFailure(Tree): tin_bot_failure = F('Tin Bot failure\n') tin_bot_failure << (VictimLost.failure | IgnoreVictim.failure | NoEscort.failure | Victim404.failure) all_bad = F('all Tin Bots fail') all_bad << (tin_bot_failure & tin_bot_failure.as_leaf()) failure = T('system failure\n(victim remains in maze)') failure << all_bad
class Uncooperative(Tree): with F('sender failure') as sender: sender << (software_bug() | hw.Bluetooth.sender()) with F('receiver failure') as receiver: receiver << (software_bug() | hw.Bluetooth.receiver()) design = P('protocol design failure (T2T)', failure_rate=0) failure = T('uncooperative behavior\n(explores cells twice, ...)') failure << (sender | receiver | hw.Bluetooth.medium() | design)
class Battery(Tree): defect = P('primary battery defect', failure_rate=1e-8) not_charged = S('battery not charged') switch = P('primary power switch failure', failure_rate=0.5) # Q: Why don't we include 'wiring'? # A: Because that's already handled in things such as 'controller board' etc. failure = F('power failure') failure << (defect | not_charged | switch) failure_no_switch = F('power failure') failure_no_switch << (defect() | not_charged())
class Victim(Tree): ir_led = P('primary IR LED failure', failure_rate=1e-5) controller = P('primary microcontroller\nfailure', failure_rate=1e-12) with F('circuit failure') as circuit: transistor = P('primary transistor defect', failure_rate=1e-12) resistor = P('primary resistor defect', failure_rate=1e-9) circuit << (transistor | resistor) failure = F('victim failure') # Copy Battery.failure as it's a different battery failure << (ir_led | controller | circuit | Battery.failure_no_switch)
class Raspberry(Tree): board = P('primary hardware failure', failure_rate=1e-6) os = P('operating system failure', failure_rate=2.94e-5) external_module_bug = P('bug in\nexternal module', failure_rate=0) internal_module_bug = P('bug in LPS software\n(blob recognition, ...)', failure_rate=0) software_failure = F('software failure') software_failure << (os | external_module_bug | internal_module_bug) failure = F('raspberry pi failure') failure << (board | Power.failure | software_failure)
class StandingStill(Tree): with F('no initial position from LPS') as no_initial_lps: user = S('user did not\nenable LPS') no_initial_lps << (proto.LPS.failure | user) with F('wheels do not turn') as wheel_fault: blocked = S('wheels blocked') wheel_fault << (hw.Motor.failure | blocked) bad_setup = S('bad setup') software = software_bug() failure = T('standing still') failure << (no_initial_lps | bad_setup | software | wheel_fault | hw.EPuck.failure | RunIntoWall.failure | Escort.hang)
class IgnoreVictim(Tree): conflict = F('conflicting data\nabout victim') conflict << (hw.EPuck.memory_fault() | S('user moved\nvictim') | Uncooperative.failure.as_leaf()) late = P('too high min-distance\nfor sensing again', failure_rate=1e-4) no_triang = F('triangulation fails') no_triang << (late | software_bug()) overwrite = F('information gets overwritten\nbefore E-Puck picks it up') overwrite << Uncooperative.design() failure = T('not using information\nabout victim') failure << (hw.ExtBoard.failure.as_leaf() | conflict | no_triang | overwrite)
class LPS(Tree): medium = hw.Bluetooth.medium sender = hw.Raspberry.failure receiver = hw.Bluetooth.receiver with F('LPP link down') as link_down: service_outage = S('simulated LPS\nservice outage (NR1)') # Raspberry board failure includes Bluetooth sender failure link_down << (service_outage | medium | receiver) with F('LPS sends no data') as no_data: no_data << (CBP.failure | sender) failure = F('LPP failure') failure << (link_down | no_data)
class VictimLost(Tree): with F('victim dropped / unable to grab') as dropped: magnet_weak = P('primary magnet failure\n(e.g., too weak)', 1e-5) belt_weak = P('primary belt failure\n(magnet slips out of the belt)', 1e-1) # Your magnet is weak, your belt is weak, your bloodline is # weak, and you will *not* survive winter! dropped << (belt_weak | magnet_weak) pulled_away = F('pulled away by\nanother Tin Bot') pulled_away << (Escort.unintentional | Uncooperative.failure.as_leaf()) failure = T('victim lost while escorting') failure << (pulled_away | dropped)
class Power(Tree): supply = P('faulty power supply', failure_rate=1e-6) grid = P('electricity grid outage', failure_rate=2.25e-5) wiring = S('power not\nconnected') failure = F('power supply failure') failure << (supply | grid | wiring)
class CBP(Tree): medium = S( 'environment failure (not enough light,\nno clear line of sight, ...)') sender = S('missing color blob') receiver = hw.Camera.failure failure = F('color blob\nprotocol failure') failure << (medium | sender | receiver)
class Bluetooth(Tree): sender = P('bluetooth module failure\n(sender)', failure_rate=1e-5) receiver = P('bluetooth module failure\n(receiver)', failure_rate=1e-5) medium = P('medium failure\n(noise, interference, ...)', failure_rate=1e-3) failure = F('bluetooth communication failure') failure << (medium | sender | receiver)
class EscortNoLED(Tree): led = P('primary indicator LED failure', failure_rate=1e-5) with F('not aware of escorting') as not_aware: not_aware << (hw.EPuck.memory_fault() | Escort.unintentional) failure = T('escorting, but\nno LED indication') failure << (led | not_aware | software_bug())
class NoEscort(Tree): indirect = F('taking a detour during escort') indirect << (Uncooperative.failure.as_leaf() | hw.Motor.failure() | hw.EPuck.memory_fault()) failure = T( 'not moving the victim out;\nat least not on shortest known path') failure << (StandingStill.failure | Escort.unintentional.as_leaf() | indirect)
class Victim404(Tree): not_placed_in = S('user did not place\nthe victim in the maze') unsolvable = S('unsolvable maze') rhr_hangs = F('right-hand follower\ndrives in circles') rhr_hangs << (P('right-hand follower\ncan drive in circles', failure_rate=inf) & P('path-pruning fails', failure_rate=0) & S('maze is not\n1-outerplanar')) drift = F('lost orientation') drift << (proto.LPS.failure & P('approximation algorithm\nis way off', failure_rate=1e-3) & P('drift from real orientation\ndoes not stabilize', failure_rate=1e-5)) failure = T('victim cannot be found') failure << (VictimSilent.failure | proto.SOS.receiver() | rhr_hangs | drift | not_placed_in | unsolvable)
class SpuriousMovements(Tree): turn = F('does not\nstop turning\nwhile sensing\nangle to victim') turn << (VictimSilent.failure.as_leaf() | hw.ExtBoard.failure) badcolor = S("Tin Bot's physical color\nis not hardcoded color") failure = T('spurious movements\n(e.g., spin around, drive circles, ...)') failure << (proto.LPS.failure.as_leaf() | software_bug() | badcolor | Proximity.failure() | Uncooperative.failure.as_leaf() | turn)
class ExtBoard(Tree): board = P('primary circuit failure', failure_rate=1e-10) controller = P('primary microcontroller\nfailure', failure_rate=1e-12) ir_sensor = P('primary IR\nsensor defect', failure_rate=1e-5) i2c = P('primary I2C\nbus failure', failure_rate=1e-5) failure = F('extension board failure') failure << (i2c | board | controller | ir_sensor)
class EPuck(Tree): board = P('primary controller board failure', failure_rate=1e-10) controller = P('primary controller failure', failure_rate=1e-12) not_turned_on = S('user did not turn\non the E-Puck') memory_fault = P('memory fault', failure_rate=1e-11) failure = F('E-Puck failure') failure << (board | controller | Battery.failure | not_turned_on | memory_fault)
class SOS(Tree): medium = P('primary medium failure\n(interference, ...)', failure_rate=1e-4) sender = hw.Victim.failure.as_leaf() # extension board failure includes WAU failure receiver = hw.ExtBoard.failure.as_leaf() failure = F('SOS failure') failure << (medium | sender | receiver)
class Escort: rec_sw = P('recognition method fails', 1e-3) recognition = F('escort recognition fails') recognition << (rec_sw | proto.SOS.failure) magnet_trigger_acc = P('magnets unintentionally\nmade contact', failure_rate=1e-5) hang = F( 'picked up victim\nthrough the wall\n(paper does not shield magnetic fields)' ) hang << (magnet_trigger_acc & Proximity.sparse_walls()) open_space = F('picked up victim\nwith physical contact') open_space << (Proximity.false_negative & recognition & magnet_trigger_acc()) unintentional = F('picking up the victim\nwas accidental') # hang is best instantiated for "standing still" unintentional << (hang.as_leaf() | open_space)
class Proximity: failure = P('primary proximity\nsensor fault', failure_rate=1e-1) sparse_walls = S('walls do not\nmeet requirements') software = P('software failure\n(overzealous escort-ignoring)', failure_rate=1e-3) false_negative = F('obstacle\nnot detected') false_negative << (failure | sparse_walls | software) crash_rhr = P('RHR crashes\ninto wall', failure_rate=1e-1) crash_path = P('path follower crashes\ninto wall', failure_rate=1e-2) crash_some = F('some component crashes\ninto wall') crash_some << (crash_rhr | crash_path) avoid_dog = P('avoidance watchdog fails', failure_rate=0) avoid_sys = F('avoidance system fails') avoid_sys << (avoid_dog & crash_some) collision = F('collision with obstacle') collision << (avoid_sys | false_negative)