예제 #1
0
def fingerprint(logcan, sendcan, has_relay):

    if has_relay:
        # Vin query only reliably works thorugh OBDII
        vin = get_vin(logcan, sendcan, 1)
    else:
        vin = VIN_UNKNOWN

    cloudlog.warning("VIN %s", vin)
    Params().put("CarVin", vin)

    finger = gen_empty_fingerprint()
    candidate_cars = {i: all_known_cars()
                      for i in [0, 1]
                      }  # attempt fingerprint on both bus 0 and 1
    frame = 0
    frame_fingerprint = 10  # 0.1s
    car_fingerprint = None
    done = False

    while not done:
        a = messaging.get_one_can(logcan)

        for can in a.can:
            # need to independently try to fingerprint both bus 0 and 1 to work
            # for the combo black_panda and honda_bosch. Ignore extended messages
            # and VIN query response.
            # Include bus 2 for toyotas to disambiguate cars using camera messages
            # (ideally should be done for all cars but we can't for Honda Bosch)
            if can.src in range(0, 4):
                finger[can.src][can.address] = len(can.dat)
            for b in candidate_cars:
                if (can.src == b or (only_toyota_left(candidate_cars[b]) and can.src == 2)) and \
                   can.address < 0x800 and can.address not in [0x7df, 0x7e0, 0x7e8]:
                    candidate_cars[b] = eliminate_incompatible_cars(
                        can, candidate_cars[b])

        # if we only have one car choice and the time since we got our first
        # message has elapsed, exit
        for b in candidate_cars:
            # Toyota needs higher time to fingerprint, since DSU does not broadcast immediately
            if only_toyota_left(candidate_cars[b]):
                frame_fingerprint = 100  # 1s
            if len(candidate_cars[b]) == 1:
                if frame > frame_fingerprint:
                    # fingerprint done
                    car_fingerprint = candidate_cars[b][0]

        # bail if no cars left or we've been waiting for more than 2s
        failed = all(len(cc) == 0
                     for cc in candidate_cars.values()) or frame > 200
        succeeded = car_fingerprint is not None
        done = failed or succeeded

        frame += 1

    cloudlog.warning("fingerprinted %s", car_fingerprint)
    return car_fingerprint, finger, vin
예제 #2
0
def get_vin(logcan, sendcan, bus, query_time=1.):
    vin_query = VinQuery(bus)
    frame = 0

    # 1s max of VIN query time
    while frame < query_time * 100:
        a = messaging.get_one_can(logcan)

        for can in a.can:
            vin_query.check_response(can)

        vin_query.send_query(sendcan)
        frame += 1

    return vin_query.get_vin()
예제 #3
0
def controlsd_thread(sm=None, pm=None, can_sock=None):
    gc.disable()

    # start the loop
    set_realtime_priority(3)

    params = Params()

    is_metric = params.get("IsMetric", encoding='utf8') == "1"
    passive = params.get("Passive", encoding='utf8') == "1"
    openpilot_enabled_toggle = params.get("OpenpilotEnabledToggle",
                                          encoding='utf8') == "1"

    passive = passive or not openpilot_enabled_toggle

    # Pub/Sub Sockets
    if pm is None:
        pm = messaging.PubMaster([
            'sendcan', 'controlsState', 'carState', 'carControl', 'carEvents',
            'carParams'
        ])

    if sm is None:
        sm = messaging.SubMaster(['thermal', 'health', 'liveCalibration', 'driverMonitoring', 'plan', 'pathPlan', \
                                  'gpsLocation'], ignore_alive=['gpsLocation'])

    if can_sock is None:
        can_timeout = None if os.environ.get('NO_CAN_TIMEOUT', False) else 100
        can_sock = messaging.sub_sock('can', timeout=can_timeout)

    # wait for health and CAN packets
    hw_type = messaging.recv_one(sm.sock['health']).health.hwType
    has_relay = hw_type in [HwType.blackPanda, HwType.uno]
    print("Waiting for CAN messages...")
    messaging.get_one_can(can_sock)

    CI, CP = get_car(can_sock, pm.sock['sendcan'], has_relay)

    car_recognized = CP.carName != 'mock'
    # If stock camera is disconnected, we loaded car controls and it's not chffrplus
    controller_available = CP.enableCamera and CI.CC is not None and not passive
    read_only = not car_recognized or not controller_available or CP.dashcamOnly
    if read_only:
        CP.safetyModel = car.CarParams.SafetyModel.noOutput

    # Write CarParams for radard and boardd safety mode
    params.put("CarParams", CP.to_bytes())
    params.put("LongitudinalControl",
               "1" if CP.openpilotLongitudinalControl else "0")

    CC = car.CarControl.new_message()
    AM = AlertManager()

    startup_alert = get_startup_alert(car_recognized, controller_available)
    AM.add(sm.frame, startup_alert, False)

    LoC = LongControl(CP, CI.compute_gb)
    VM = VehicleModel(CP)

    if CP.lateralTuning.which() == 'pid':
        LaC = LatControlPID(CP)
    elif CP.lateralTuning.which() == 'indi':
        LaC = LatControlINDI(CP)
    elif CP.lateralTuning.which() == 'lqr':
        LaC = LatControlLQR(CP)

    driver_status = DriverStatus()
    is_rhd = params.get("IsRHD")
    if is_rhd is not None:
        driver_status.is_rhd = bool(int(is_rhd))

    state = State.disabled
    soft_disable_timer = 0
    v_cruise_kph = 255
    v_cruise_kph_last = 0
    overtemp = False
    free_space = False
    cal_status = Calibration.INVALID
    cal_perc = 0
    mismatch_counter = 0
    low_battery = False
    events_prev = []

    sm['pathPlan'].sensorValid = True
    sm['pathPlan'].posenetValid = True

    # detect sound card presence
    sounds_available = not os.path.isfile('/EON') or (
        os.path.isdir('/proc/asound/card0')
        and open('/proc/asound/card0/state').read().strip() == 'ONLINE')

    # controlsd is driven by can recv, expected at 100Hz
    rk = Ratekeeper(100, print_delay_threshold=None)

    internet_needed = params.get("Offroad_ConnectivityNeeded",
                                 encoding='utf8') is not None

    prof = Profiler(False)  # off by default

    while True:
        start_time = sec_since_boot()
        prof.checkpoint("Ratekeeper", ignore=True)

        # Sample data and compute car events
        CS, events, cal_status, cal_perc, overtemp, free_space, low_battery, mismatch_counter =\
          data_sample(CI, CC, sm, can_sock, cal_status, cal_perc, overtemp, free_space, low_battery,
                      driver_status, state, mismatch_counter, params)
        prof.checkpoint("Sample")

        # Create alerts
        if not sm.all_alive_and_valid():
            events.append(
                create_event('commIssue', [ET.NO_ENTRY, ET.SOFT_DISABLE]))
        if not sm['pathPlan'].mpcSolutionValid:
            events.append(
                create_event('plannerError',
                             [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE]))
        if not sm['pathPlan'].sensorValid:
            events.append(
                create_event('sensorDataInvalid', [ET.NO_ENTRY, ET.PERMANENT]))
        if not sm['pathPlan'].paramsValid:
            events.append(create_event('vehicleModelInvalid', [ET.WARNING]))
        if not sm['pathPlan'].posenetValid:
            events.append(
                create_event('posenetInvalid', [ET.NO_ENTRY, ET.SOFT_DISABLE]))
        if not sm['plan'].radarValid:
            events.append(
                create_event('radarFault', [ET.NO_ENTRY, ET.SOFT_DISABLE]))
        if sm['plan'].radarCanError:
            events.append(
                create_event('radarCanError', [ET.NO_ENTRY, ET.SOFT_DISABLE]))
        if not CS.canValid:
            events.append(
                create_event('canError', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE]))
        if not sounds_available:
            events.append(
                create_event('soundsUnavailable', [ET.NO_ENTRY, ET.PERMANENT]))
        if internet_needed:
            events.append(
                create_event('internetConnectivityNeeded',
                             [ET.NO_ENTRY, ET.PERMANENT]))

        # Only allow engagement with brake pressed when stopped behind another stopped car
        if CS.brakePressed and sm[
                'plan'].vTargetFuture >= STARTING_TARGET_SPEED and not CP.radarOffCan and CS.vEgo < 0.3:
            events.append(
                create_event('noTarget', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE]))

        if not read_only:
            # update control state
            state, soft_disable_timer, v_cruise_kph, v_cruise_kph_last = \
              state_transition(sm.frame, CS, CP, state, events, soft_disable_timer, v_cruise_kph, AM)
            prof.checkpoint("State transition")

        # Compute actuators (runs PID loops and lateral MPC)
        actuators, v_cruise_kph, driver_status, v_acc, a_acc, lac_log = \
          state_control(sm.frame, sm.rcv_frame, sm['plan'], sm['pathPlan'], CS, CP, state, events, v_cruise_kph, v_cruise_kph_last, AM, rk,
                        driver_status, LaC, LoC, read_only, is_metric, cal_perc)

        prof.checkpoint("State Control")

        # Publish data
        CC, events_prev = data_send(sm, pm, CS, CI, CP, VM, state, events,
                                    actuators, v_cruise_kph, rk, AM,
                                    driver_status, LaC, LoC, read_only,
                                    start_time, v_acc, a_acc, lac_log,
                                    events_prev)
        prof.checkpoint("Sent")

        rk.monitor_time()
        prof.display()
예제 #4
0
def steer_thread():
    poller = messaging.Poller()

    logcan = messaging.sub_sock('can')
    health = messaging.sub_sock('health')
    joystick_sock = messaging.sub_sock('testJoystick',
                                       conflate=True,
                                       poller=poller)

    carstate = messaging.pub_sock('carState')
    carcontrol = messaging.pub_sock('carControl')
    sendcan = messaging.pub_sock('sendcan')

    button_1_last = 0
    enabled = False

    # wait for health and CAN packets
    hw_type = messaging.recv_one(health).health.hwType
    has_relay = hw_type in [HwType.blackPanda, HwType.uno]
    print("Waiting for CAN messages...")
    messaging.get_one_can(logcan)

    CI, CP = get_car(logcan, sendcan, has_relay)
    Params().put("CarParams", CP.to_bytes())

    CC = car.CarControl.new_message()

    while True:

        # send
        joystick = messaging.recv_one(joystick_sock)
        can_strs = messaging.drain_sock_raw(logcan, wait_for_one=True)
        CS = CI.update(CC, can_strs)

        # Usually axis run in pairs, up/down for one, and left/right for
        # the other.
        actuators = car.CarControl.Actuators.new_message()

        if joystick is not None:
            axis_3 = clip(-joystick.testJoystick.axes[3] * 1.05, -1.,
                          1.)  # -1 to 1
            actuators.steer = axis_3
            actuators.steerAngle = axis_3 * 43.  # deg
            axis_1 = clip(-joystick.testJoystick.axes[1] * 1.05, -1.,
                          1.)  # -1 to 1
            actuators.gas = max(axis_1, 0.)
            actuators.brake = max(-axis_1, 0.)

            pcm_cancel_cmd = joystick.testJoystick.buttons[0]
            button_1 = joystick.testJoystick.buttons[1]
            if button_1 and not button_1_last:
                enabled = not enabled

            button_1_last = button_1

            #print "enable", enabled, "steer", actuators.steer, "accel", actuators.gas - actuators.brake

            hud_alert = 0
            audible_alert = 0
            if joystick.testJoystick.buttons[2]:
                audible_alert = "beepSingle"
            if joystick.testJoystick.buttons[3]:
                audible_alert = "chimeRepeated"
                hud_alert = "steerRequired"

        CC.actuators.gas = actuators.gas
        CC.actuators.brake = actuators.brake
        CC.actuators.steer = actuators.steer
        CC.actuators.steerAngle = actuators.steerAngle
        CC.hudControl.visualAlert = hud_alert
        CC.hudControl.setSpeed = 20
        CC.cruiseControl.cancel = pcm_cancel_cmd
        CC.enabled = enabled
        can_sends = CI.apply(CC)
        sendcan.send(can_list_to_can_capnp(can_sends, msgtype='sendcan'))

        # broadcast carState
        cs_send = messaging.new_message()
        cs_send.init('carState')
        cs_send.carState = copy(CS)
        carstate.send(cs_send.to_bytes())

        # broadcast carControl
        cc_send = messaging.new_message()
        cc_send.init('carControl')
        cc_send.carControl = copy(CC)
        carcontrol.send(cc_send.to_bytes())