Пример #1
0
  def test_panda_safety_carstate(self):
    """
      Assert that panda safety matches openpilot's carState
    """
    if self.CP.dashcamOnly:
      self.skipTest("no need to check panda safety for dashcamOnly")

    CC = car.CarControl.new_message()

    # warm up pass, as initial states may be different
    for can in self.can_msgs[:300]:
      for msg in can_capnp_to_can_list(can.can, src_filter=range(64)):
        to_send = package_can_msg(msg)
        self.safety.safety_rx_hook(to_send)
        self.CI.update(CC, (can_list_to_can_capnp([msg, ]), ))

    checks = defaultdict(lambda: 0)
    for can in self.can_msgs:
      CS = self.CI.update(CC, (can.as_builder().to_bytes(), ))
      for msg in can_capnp_to_can_list(can.can, src_filter=range(64)):
        to_send = package_can_msg(msg)
        ret = self.safety.safety_rx_hook(to_send)
        self.assertEqual(1, ret, f"safety rx failed ({ret=}): {to_send}")

      # TODO: check rest of panda's carstate (steering, ACC main on, etc.)

      # TODO: make the interceptor thresholds in openpilot and panda match, then remove this exception
      gas_pressed = CS.gasPressed
      if self.CP.enableGasInterceptor and gas_pressed and not self.safety.get_gas_pressed_prev():
        # panda intentionally has a higher threshold
        if self.CP.carName == "toyota" and 15 < CS.gas < 15*1.5:
          gas_pressed = False
        if self.CP.carName == "honda":
          gas_pressed = False
      checks['gasPressed'] += gas_pressed != self.safety.get_gas_pressed_prev()

      # TODO: remove this exception once this mismatch is resolved
      brake_pressed = CS.brakePressed
      if CS.brakePressed and not self.safety.get_brake_pressed_prev():
        if self.CP.carFingerprint in (HONDA.PILOT, HONDA.PASSPORT, HONDA.RIDGELINE) and CS.brake > 0.05:
          brake_pressed = False
      checks['brakePressed'] += brake_pressed != self.safety.get_brake_pressed_prev()

      if self.CP.pcmCruise:
        checks['controlsAllowed'] += not CS.cruiseState.enabled and self.safety.get_controls_allowed()

      if self.CP.carName == "honda":
        checks['mainOn'] += CS.cruiseState.available != self.safety.get_acc_main_on()

    # TODO: add flag to toyota safety
    if self.CP.carFingerprint == TOYOTA.SIENNA and checks['brakePressed'] < 25:
      checks['brakePressed'] = 0

    # Honda Nidec uses button enable in panda, but pcm enable in openpilot
    if self.CP.carName == "honda" and self.CP.carFingerprint not in HONDA_BOSCH and checks['controlsAllowed'] < 25:
      checks['controlsAllowed'] = 0

    failed_checks = {k: v for k, v in checks.items() if v > 0}
    self.assertFalse(len(failed_checks), f"panda safety doesn't agree with openpilot: {failed_checks}")
Пример #2
0
    def test_diagnostics(self):
        tester_present = common.package_can_msg(
            (0x7d0, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", 0))
        self.assertTrue(self.safety.safety_tx_hook(tester_present))

        not_tester_present = common.package_can_msg(
            (0x7d0, 0, b"\x03\xAA\xAA\x00\x00\x00\x00\x00", 0))
        self.assertFalse(self.safety.safety_tx_hook(not_tester_present))
Пример #3
0
  def test_panda_safety_rx_valid(self):
    if self.CP.dashcamOnly:
      self.skipTest("no need to check panda safety for dashcamOnly")

    start_ts = self.can_msgs[0].logMonoTime

    failed_addrs = Counter()
    for can in self.can_msgs:
      # update panda timer
      t = (can.logMonoTime - start_ts) / 1e3
      self.safety.set_timer(int(t))

      # run all msgs through the safety RX hook
      for msg in can.can:
        if msg.src >= 64:
          continue

        to_send = package_can_msg([msg.address, 0, msg.dat, msg.src])
        if self.safety.safety_rx_hook(to_send) != 1:
          failed_addrs[hex(msg.address)] += 1

      # ensure all msgs defined in the addr checks are valid
      if self.car_model not in ignore_addr_checks_valid:
        self.safety.safety_tick_current_rx_checks()
        if t > 1e6:
          self.assertTrue(self.safety.addr_checks_valid())
    self.assertFalse(len(failed_addrs), f"panda safety RX check failed: {failed_addrs}")
Пример #4
0
    def test_panda_safety_carstate(self):
        """
      Assert that panda safety matches openpilot's carState
    """
        if self.CP.dashcamOnly:
            self.skipTest("no need to check panda safety for dashcamOnly")
        if self.car_model in ignore_carstate_check:
            self.skipTest("see comments in test_models.py")

        checks = defaultdict(lambda: 0)
        CC = car.CarControl.new_message()
        for can in self.can_msgs:
            for msg in can.can:
                if msg.src >= 128:
                    continue
                to_send = package_can_msg([msg.address, 0, msg.dat, msg.src])
                ret = self.safety.safety_rx_hook(to_send)
                self.assertEqual(1, ret,
                                 f"safety rx failed ({ret=}): {to_send}")
            CS = self.CI.update(CC, (can.as_builder().to_bytes(), ))

            # TODO: check steering state
            # check that openpilot and panda safety agree on the car's state
            checks[
                'gasPressed'] += CS.gasPressed != self.safety.get_gas_pressed_prev(
                )
            checks[
                'brakePressed'] += CS.brakePressed != self.safety.get_brake_pressed_prev(
                )
            if self.CP.pcmCruise:
                checks[
                    'controlsAllowed'] += not CS.cruiseState.enabled and self.safety.get_controls_allowed(
                    )

            # TODO: extend this to all cars
            if self.CP.carName == "honda":
                checks[
                    'mainOn'] += CS.cruiseState.available != self.safety.get_acc_main_on(
                    )

        # TODO: reduce tolerance to 0
        failed_checks = {k: v for k, v in checks.items() if v > 25}

        # TODO: the panda and openpilot interceptor thresholds should match
        skip_gas_check = self.CP.carName == 'chrysler'
        if "gasPressed" in failed_checks and (self.CP.enableGasInterceptor
                                              or skip_gas_check):
            if failed_checks['gasPressed'] < 150 or skip_gas_check:
                del failed_checks['gasPressed']

        # TODO: honda nidec: do same checks in carState and panda
        if "brakePressed" in failed_checks and self.CP.carName == 'honda' and \
          (self.car_model not in HONDA_BOSCH or self.car_model in [HONDA.CRV_HYBRID, HONDA.HONDA_E]):
            if failed_checks['brakePressed'] < 150:
                del failed_checks['brakePressed']

        self.assertFalse(
            len(failed_checks),
            f"panda safety doesn't agree with CarState: {failed_checks}")
Пример #5
0
 def test_block_aeb(self):
     for controls_allowed in (True, False):
         for bad in (True, False):
             for _ in range(10):
                 self.safety.set_controls_allowed(controls_allowed)
                 dat = [random.randint(1, 255) for _ in range(7)]
                 if not bad:
                     dat = [0] * 6 + dat[-1:]
                 msg = common.package_can_msg([0x283, 0, bytes(dat), 0])
                 self.assertEqual(not bad, self._tx(msg))
Пример #6
0
    def test_panda_safety_carstate(self):
        if self.CP.dashcamOnly:
            self.skipTest("no need to check panda safety for dashcamOnly")
        if self.car_model in ignore_carstate_check:
            self.skipTest("see comments in test_models.py")

        safety = libpandasafety_py.libpandasafety
        set_status = safety.set_safety_hooks(self.CP.safetyModel.raw,
                                             self.CP.safetyParam)
        self.assertEqual(0, set_status)

        checks = defaultdict(lambda: 0)
        CC = car.CarControl.new_message()
        for can in self.can_msgs:
            for msg in can.can:
                if msg.src >= 128:
                    continue
                to_send = package_can_msg([msg.address, 0, msg.dat, msg.src])
                safety.safety_rx_hook(to_send)
            CS = self.CI.update(CC, (can.as_builder().to_bytes(), ))

            # TODO: check steering state
            # check that openpilot and panda safety agree on the car's state
            checks[
                'gasPressed'] += CS.gasPressed != safety.get_gas_pressed_prev(
                )
            checks[
                'brakePressed'] += CS.brakePressed != safety.get_brake_pressed_prev(
                )
            checks[
                'controlsAllowed'] += not CS.cruiseState.enabled and safety.get_controls_allowed(
                )

        # TODO: reduce tolerance to 0
        failed_checks = {k: v for k, v in checks.items() if v > 25}

        # TODO: the panda and openpilot interceptor thresholds should match
        if "gasPressed" in failed_checks and self.CP.enableGasInterceptor:
            if failed_checks['gasPressed'] < 150:
                del failed_checks['gasPressed']

        # TODO: honda nidec: do same checks in carState and panda
        if "brakePressed" in failed_checks and self.car_model.startswith(
            ("HONDA", "ACURA")) and self.car_model not in HONDA_BOSCH:
            if failed_checks['brakePressed'] < 150:
                del failed_checks['brakePressed']

        self.assertFalse(
            len(failed_checks),
            f"panda safety doesn't agree with CarState: {failed_checks}")
Пример #7
0
    def test_panda_safety_rx_valid(self):
        if self.CP.dashcamOnly:
            self.skipTest("no need to check panda safety for dashcamOnly")

        failed_addrs = Counter()
        for can in self.can_msgs:
            for msg in can.can:
                if msg.src >= 128:
                    continue
                to_send = package_can_msg([msg.address, 0, msg.dat, msg.src])
                if self.safety.safety_rx_hook(to_send) != 1:
                    failed_addrs[hex(msg.address)] += 1
        self.assertFalse(len(failed_addrs),
                         f"panda safety RX check failed: {failed_addrs}")
Пример #8
0
  def test_panda_safety_rx(self):
    if self.CP.dashcamOnly:
      self.skipTest("no need to check panda safety for dashcamOnly")

    safety = libpandasafety_py.libpandasafety
    set_status = safety.set_safety_hooks(self.CP.safetyModel.raw, self.CP.safetyParam)
    self.assertEqual(0, set_status)

    failed_addrs = Counter()
    for can in self.can_msgs:
      for msg in can.can:
        if msg.src >= 128:
          continue
        to_send = package_can_msg([msg.address, 0, msg.dat, msg.src])
        if not safety.safety_rx_hook(to_send):
          failed_addrs[hex(msg.address)] += 1
    self.assertFalse(len(failed_addrs), f"panda safety RX check failed: {failed_addrs}")
Пример #9
0
    def test_panda_safety_carstate(self):
        """
      Assert that panda safety matches openpilot's carState
    """
        if self.CP.dashcamOnly:
            self.skipTest("no need to check panda safety for dashcamOnly")

        CC = car.CarControl.new_message()

        # warm up pass, as initial states may be different
        for can in self.can_msgs[:300]:
            for msg in can_capnp_to_can_list(can.can, src_filter=range(64)):
                to_send = package_can_msg(msg)
                self.safety.safety_rx_hook(to_send)
                self.CI.update(CC, (can_list_to_can_capnp([
                    msg,
                ]), ))

        if not self.CP.pcmCruise:
            self.safety.set_controls_allowed(0)

        controls_allowed_prev = False
        CS_prev = car.CarState.new_message()
        checks = defaultdict(lambda: 0)
        for can in self.can_msgs:
            CS = self.CI.update(CC, (can.as_builder().to_bytes(), ))
            for msg in can_capnp_to_can_list(can.can, src_filter=range(64)):
                to_send = package_can_msg(msg)
                ret = self.safety.safety_rx_hook(to_send)
                self.assertEqual(1, ret,
                                 f"safety rx failed ({ret=}): {to_send}")

            # TODO: check rest of panda's carstate (steering, ACC main on, etc.)

            checks[
                'gasPressed'] += CS.gasPressed != self.safety.get_gas_pressed_prev(
                )

            # TODO: remove this exception once this mismatch is resolved
            brake_pressed = CS.brakePressed
            if CS.brakePressed and not self.safety.get_brake_pressed_prev():
                if self.CP.carFingerprint in (
                        HONDA.PILOT, HONDA.PASSPORT,
                        HONDA.RIDGELINE) and CS.brake > 0.05:
                    brake_pressed = False
            checks[
                'brakePressed'] += brake_pressed != self.safety.get_brake_pressed_prev(
                )

            if self.CP.pcmCruise:
                # On most pcmCruise cars, openpilot's state is always tied to the PCM's cruise state.
                # On Honda Nidec, we always engage on the rising edge of the PCM cruise state, but
                # openpilot brakes to zero even if the min ACC speed is non-zero (i.e. the PCM disengages).
                if self.CP.carName == "honda" and self.CP.carFingerprint not in HONDA_BOSCH:
                    # only the rising edges are expected to match
                    if CS.cruiseState.enabled and not CS_prev.cruiseState.enabled:
                        checks[
                            'controlsAllowed'] += not self.safety.get_controls_allowed(
                            )
                else:
                    checks[
                        'controlsAllowed'] += not CS.cruiseState.enabled and self.safety.get_controls_allowed(
                        )
            else:
                # Check for enable events on rising edge of controls allowed
                button_enable = any(evt.enable for evt in CS.events)
                mismatch = button_enable != (
                    self.safety.get_controls_allowed()
                    and not controls_allowed_prev)
                checks['controlsAllowed'] += mismatch
                controls_allowed_prev = self.safety.get_controls_allowed()
                if button_enable and not mismatch:
                    self.safety.set_controls_allowed(False)

            if self.CP.carName == "honda":
                checks[
                    'mainOn'] += CS.cruiseState.available != self.safety.get_acc_main_on(
                    )
                # TODO: fix standstill mismatches for other makes
                checks[
                    'standstill'] += CS.standstill == self.safety.get_vehicle_moving(
                    )

            CS_prev = CS

        # TODO: add flag to toyota safety
        if self.CP.carFingerprint == TOYOTA.SIENNA and checks[
                'brakePressed'] < 25:
            checks['brakePressed'] = 0

        failed_checks = {k: v for k, v in checks.items() if v > 0}
        self.assertFalse(
            len(failed_checks),
            f"panda safety doesn't agree with openpilot: {failed_checks}")