def test_out_of_bounds(self): """Tests the UAS out of bounds method.""" (zone_details, uas_details) = TESTDATA_FLYZONE_EVALBOUNDS # Create FlyZone objects zones = [] for (alt_min, alt_max, wpts) in zone_details: zone = FlyZone() zone.altitude_msl_min = alt_min zone.altitude_msl_max = alt_max zone.save() for wpt_id in range(len(wpts)): (lat, lon) = wpts[wpt_id] wpt = Waypoint() wpt.order = wpt_id wpt.latitude = lat wpt.longitude = lon wpt.altitude_msl = 0 wpt.save() zone.boundary_pts.add(wpt) zone.save() zones.append(zone) # For each user, validate time out of bounds user_id = 0 epoch = timezone.now().replace(year=1970, month=1, day=1, hour=0, minute=0, second=0, microsecond=0) for exp_violations, exp_out_of_bounds_time, log_details in uas_details: # Create the logs user = User.objects.create_user('testuser%d' % user_id, '*****@*****.**', 'testpass') user_id += 1 uas_logs = [] for (lat, lon, alt, timestamp) in log_details: log = UasTelemetry() log.user = user log.latitude = lat log.longitude = lon log.altitude_msl = alt log.uas_heading = 0 log.save() log.timestamp = epoch + datetime.timedelta(seconds=timestamp) log.save() uas_logs.append(log) # Assert out of bounds time matches expected num_violations, out_of_bounds_time = \ FlyZone.out_of_bounds(zones, uas_logs) self.assertEqual(num_violations, exp_violations) self.assertAlmostEqual(out_of_bounds_time.total_seconds(), exp_out_of_bounds_time)
def test_out_of_bounds(self): """Tests the UAS out of bounds method.""" (zone_details, uas_details) = TESTDATA_FLYZONE_EVALBOUNDS # Create FlyZone objects zones = [] for (alt_min, alt_max, wpts) in zone_details: zone = FlyZone() zone.altitude_msl_min = alt_min zone.altitude_msl_max = alt_max zone.save() for wpt_id in xrange(len(wpts)): (lat, lon) = wpts[wpt_id] gpos = GpsPosition() gpos.latitude = lat gpos.longitude = lon gpos.save() apos = AerialPosition() apos.gps_position = gpos apos.altitude_msl = 0 apos.save() wpt = Waypoint() wpt.order = wpt_id wpt.position = apos wpt.save() zone.boundary_pts.add(wpt) zone.save() zones.append(zone) # For each user, validate time out of bounds user_id = 0 epoch = timezone.now().replace(year=1970, month=1, day=1, hour=0, minute=0, second=0, microsecond=0) for exp_violations, exp_out_of_bounds_time, log_details in uas_details: # Create the logs user = User.objects.create_user('testuser%d' % user_id, '*****@*****.**', 'testpass') user_id += 1 uas_logs = [] for (lat, lon, alt, timestamp) in log_details: gpos = GpsPosition() gpos.latitude = lat gpos.longitude = lon gpos.save() apos = AerialPosition() apos.gps_position = gpos apos.altitude_msl = alt apos.save() log = UasTelemetry() log.user = user log.uas_position = apos log.uas_heading = 0 log.save() log.timestamp = epoch + datetime.timedelta(seconds=timestamp) log.save() uas_logs.append(log) # Assert out of bounds time matches expected num_violations, out_of_bounds_time = \ FlyZone.out_of_bounds(zones, uas_logs) self.assertEqual(num_violations, exp_violations) self.assertAlmostEqual(out_of_bounds_time, exp_out_of_bounds_time)
def generate_feedback(mission_config, user, team_eval): """Generates mission feedback for the given team and mission. Args: mission_config: The mission to evaluate the team against. user: The team user object for which to evaluate and provide feedback. team_eval: The team evaluation to fill. """ feedback = team_eval.feedback # Calculate the total mission clock time. missions = MissionClockEvent.missions(user) mission_clock_time = datetime.timedelta(seconds=0) for mission in missions: duration = mission.duration() if duration is None: team_eval.warnings.append('Infinite mission clock.') else: mission_clock_time += duration feedback.mission_clock_time_sec = mission_clock_time.total_seconds() # Calculate total time in air. flight_periods = TakeoffOrLandingEvent.flights(user) if flight_periods: flight_time = reduce(lambda x, y: x + y, [p.duration() for p in flight_periods]) feedback.flight_time_sec = flight_time.total_seconds() else: feedback.flight_time_sec = 0 # Find the user's flights. for period in flight_periods: if period.duration() is None: team_eval.warnings.append('Infinite flight period.') uas_period_logs = [ UasTelemetry.dedupe(logs) for logs in UasTelemetry.by_time_period(user, flight_periods) ] uas_logs = list(itertools.chain.from_iterable(uas_period_logs)) if not uas_logs: team_eval.warnings.append('No UAS telemetry logs.') # Determine interop telemetry rates. telem_max, telem_avg = UasTelemetry.rates(user, flight_periods, time_period_logs=uas_period_logs) if telem_max: feedback.uas_telemetry_time_max_sec = telem_max if telem_avg: feedback.uas_telemetry_time_avg_sec = telem_avg # Determine if the uas went out of bounds. This must be done for # each period individually so time between periods isn't counted as # out of bounds time. Note that this calculates reported time out # of bounds, not actual or possible time spent out of bounds. out_of_bounds = datetime.timedelta(seconds=0) feedback.boundary_violations = 0 for logs in uas_period_logs: bv, bt = FlyZone.out_of_bounds(mission_config.fly_zones.all(), logs) feedback.boundary_violations += bv out_of_bounds += bt feedback.out_of_bounds_time_sec = out_of_bounds.total_seconds() # Determine if the uas hit the waypoints. feedback.waypoints.extend( UasTelemetry.satisfied_waypoints( mission_config.home_pos, mission_config.mission_waypoints.order_by('order'), uas_logs)) # Evaluate the object detections. user_odlcs = Odlc.objects.filter(user=user).all() evaluator = OdlcEvaluator(user_odlcs, mission_config.odlcs.all()) feedback.odlc.CopyFrom(evaluator.evaluate()) # Determine collisions with stationary and moving obstacles. for obst in mission_config.stationary_obstacles.all(): obst_eval = feedback.stationary_obstacles.add() obst_eval.id = obst.pk obst_eval.hit = obst.evaluate_collision_with_uas(uas_logs) for obst in mission_config.moving_obstacles.all(): obst_eval = feedback.moving_obstacles.add() obst_eval.id = obst.pk obst_eval.hit = obst.evaluate_collision_with_uas(uas_logs) # Add judge feedback. try: judge_feedback = MissionJudgeFeedback.objects.get( mission=mission_config.pk, user=user.pk) feedback.judge.CopyFrom(judge_feedback.proto()) except MissionJudgeFeedback.DoesNotExist: team_eval.warnings.append('No MissionJudgeFeedback for team.') # Sanity check mission time. judge_mission_clock = (feedback.judge.flight_time_sec + feedback.judge.post_process_time_sec) if abs(feedback.mission_clock_time_sec - judge_mission_clock) > 30: team_eval.warnings.append( 'Mission clock differs between interop and judge.')
def generate_feedback(mission_config, user, team_eval): """Generates mission feedback for the given team and mission. Args: mission_config: The mission to evaluate the team against. user: The team user object for which to evaluate and provide feedback. team_eval: The team evaluation to fill. """ feedback = team_eval.feedback # Calculate the total mission clock time. missions = MissionClockEvent.missions(user) mission_clock_time = datetime.timedelta(seconds=0) for mission in missions: duration = mission.duration() if duration is None: team_eval.warnings.append('Infinite mission clock.') else: mission_clock_time += duration feedback.mission_clock_time_sec = mission_clock_time.total_seconds() # Calculate total time in air. flight_periods = TakeoffOrLandingEvent.flights(user) if flight_periods: flight_time = reduce(lambda x, y: x + y, [p.duration() for p in flight_periods]) feedback.flight_time_sec = flight_time.total_seconds() else: feedback.flight_time_sec = 0 # Find the user's flights. for period in flight_periods: if period.duration() is None: team_eval.warnings.append('Infinite flight period.') uas_period_logs = [ UasTelemetry.dedupe(logs) for logs in UasTelemetry.by_time_period(user, flight_periods) ] uas_logs = list(itertools.chain.from_iterable(uas_period_logs)) if not uas_logs: team_eval.warnings.append('No UAS telemetry logs.') # Determine interop telemetry rates. telem_max, telem_avg = UasTelemetry.rates(user, flight_periods, time_period_logs=uas_period_logs) if telem_max: feedback.uas_telemetry_time_max_sec = telem_max if telem_avg: feedback.uas_telemetry_time_avg_sec = telem_avg # Determine if the uas went out of bounds. This must be done for # each period individually so time between periods isn't counted as # out of bounds time. Note that this calculates reported time out # of bounds, not actual or possible time spent out of bounds. out_of_bounds = datetime.timedelta(seconds=0) feedback.boundary_violations = 0 for logs in uas_period_logs: bv, bt = FlyZone.out_of_bounds(mission_config.fly_zones.all(), logs) feedback.boundary_violations += bv out_of_bounds += bt feedback.out_of_bounds_time_sec = out_of_bounds.total_seconds() # Determine if the uas hit the waypoints. feedback.waypoints.extend(UasTelemetry.satisfied_waypoints( mission_config.home_pos, mission_config.mission_waypoints.order_by( 'order'), uas_logs)) # Evaluate the targets. user_targets = Target.objects.filter(user=user).all() evaluator = TargetEvaluator(user_targets, mission_config.targets.all()) feedback.target.CopyFrom(evaluator.evaluate()) # Determine collisions with stationary and moving obstacles. for obst in mission_config.stationary_obstacles.all(): obst_eval = feedback.stationary_obstacles.add() obst_eval.id = obst.pk obst_eval.hit = obst.evaluate_collision_with_uas(uas_logs) for obst in mission_config.moving_obstacles.all(): obst_eval = feedback.moving_obstacles.add() obst_eval.id = obst.pk obst_eval.hit = obst.evaluate_collision_with_uas(uas_logs) # Add judge feedback. try: judge_feedback = MissionJudgeFeedback.objects.get( mission=mission_config.pk, user=user.pk) feedback.judge.CopyFrom(judge_feedback.proto()) except MissionJudgeFeedback.DoesNotExist: team_eval.warnings.append('No MissionJudgeFeedback for team.') # Sanity check mission time. judge_mission_clock = ( feedback.judge.flight_time_sec + feedback.judge.post_process_time_sec) if abs(feedback.mission_clock_time_sec - judge_mission_clock) > 30: team_eval.warnings.append( 'Mission clock differs between interop and judge.')