commit
6d32dfc72a
47 changed files with 737 additions and 254 deletions
@ -1 +1 @@ |
|||||||
Subproject commit 5935572cee86f202e2524d5f388f9475f92cd649 |
Subproject commit c7d3a0acbae267ef93d30044e1941e060dac9e48 |
@ -1 +1 @@ |
|||||||
Subproject commit 226adc655e1488474468a97ab4a7705aad7e5837 |
Subproject commit be1a213a5ffa3cafe2b4f2d53f6df5d2452ad910 |
@ -1 +1 @@ |
|||||||
Subproject commit e19ba095c3ee288d629284e24ec7e0deaf645f3f |
Subproject commit 919154efe2bd07c4dd124d7e6a11a4afc8685f9d |
@ -0,0 +1,5 @@ |
|||||||
|
#!/usr/bin/bash |
||||||
|
|
||||||
|
nmcli connection modify --temporary lte ipv4.route-metric 1 |
||||||
|
nmcli connection modify --temporary lte ipv6.route-metric 1 |
||||||
|
nmcli con up lte |
Binary file not shown.
@ -1,2 +0,0 @@ |
|||||||
#!/usr/bin/bash |
|
||||||
echo "restart" > /sys/kernel/debug/msm_subsys/modem |
|
@ -1,16 +0,0 @@ |
|||||||
#!/data/data/com.termux/files/usr/bin/bash |
|
||||||
watch -n1 ' |
|
||||||
cat /sys/kernel/debug/clk/pwrcl_clk/measure |
|
||||||
cat /sys/kernel/debug/clk/perfcl_clk/measure |
|
||||||
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq |
|
||||||
cat /sys/class/kgsl/kgsl-3d0/gpuclk |
|
||||||
echo |
|
||||||
echo -n "CPU0 " ; cat /sys/devices/virtual/thermal/thermal_zone5/temp |
|
||||||
echo -n "CPU1 " ; cat /sys/devices/virtual/thermal/thermal_zone7/temp |
|
||||||
echo -n "CPU2 " ; cat /sys/devices/virtual/thermal/thermal_zone10/temp |
|
||||||
echo -n "CPU3 " ; cat /sys/devices/virtual/thermal/thermal_zone12/temp |
|
||||||
echo -n "MEM " ; cat /sys/devices/virtual/thermal/thermal_zone2/temp |
|
||||||
echo -n "GPU " ; cat /sys/devices/virtual/thermal/thermal_zone16/temp |
|
||||||
echo -n "BAT " ; cat /sys/devices/virtual/thermal/thermal_zone29/temp |
|
||||||
' |
|
||||||
|
|
Binary file not shown.
@ -1,19 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
# flake8: noqa |
|
||||||
|
|
||||||
# put 2 fingeprints and print the diffs |
|
||||||
f1 = { |
|
||||||
168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 528: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8, 1537: 8, 1538: 8, 1562: 8 |
|
||||||
} |
|
||||||
|
|
||||||
f2 = { |
|
||||||
168: 8, 257: 5, 258: 8, 264: 8, 268: 8, 270: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 291: 8, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 515: 7, 516: 7, 517: 7, 518: 7, 520: 8, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 653: 8, 654: 8, 655: 8, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 701: 8, 703: 8, 704: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 782: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 878: 8, 882: 8, 897: 8, 906: 8, 908: 8, 924: 8, 926: 3, 929: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 958: 8, 959: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1082: 8, 1083: 8, 1098: 8, 1100: 8 |
|
||||||
} |
|
||||||
|
|
||||||
for k in f1: |
|
||||||
if k not in f2 or f1[k] != f2[k]: |
|
||||||
print(k, "not in f2") |
|
||||||
|
|
||||||
for k in f2: |
|
||||||
if k not in f1 or f2[k] != f1[k]: |
|
||||||
print(k, "not in f1") |
|
@ -1,23 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
import os |
|
||||||
import sys |
|
||||||
import time |
|
||||||
|
|
||||||
print("starting at") |
|
||||||
os.system("cat /sys/kernel/debug/regulator/pm8994_s11/voltage") |
|
||||||
print("volts") |
|
||||||
|
|
||||||
os.system("echo 99e8000.cpr3-ctrl > /sys/devices/soc/spm-regulator-10/regulator/regulator.56/99e8000.cpr3-ctrl-vdd/driver/unbind") |
|
||||||
os.system("echo 1 > /sys/kernel/debug/regulator/pm8994_s11/enable") |
|
||||||
|
|
||||||
if len(sys.argv) > 1: |
|
||||||
i = int(sys.argv[1]) |
|
||||||
os.system("echo %d %d > /sys/kernel/debug/regulator/pm8994_s11/voltage" % (i,i)) |
|
||||||
os.system("cat /sys/kernel/debug/regulator/pm8994_s11/voltage") |
|
||||||
else: |
|
||||||
for i in range(900000, 465000, -10000): |
|
||||||
print("setting voltage to",i) |
|
||||||
os.system("echo %d %d > /sys/kernel/debug/regulator/pm8994_s11/voltage" % (i,i)) |
|
||||||
os.system("cat /sys/kernel/debug/regulator/pm8994_s11/voltage") |
|
||||||
time.sleep(1) |
|
||||||
|
|
@ -1,67 +0,0 @@ |
|||||||
#!/usr/bin/python3 |
|
||||||
import sys |
|
||||||
import os |
|
||||||
import stat |
|
||||||
import subprocess |
|
||||||
import json |
|
||||||
from common.text_window import TextWindow |
|
||||||
import time |
|
||||||
|
|
||||||
# Required for sensord not to bus-error on startup |
|
||||||
# commaai/cereal#22 |
|
||||||
try: |
|
||||||
os.mkdir("/dev/shm") |
|
||||||
except FileExistsError: |
|
||||||
pass |
|
||||||
except PermissionError: |
|
||||||
print("WARNING: failed to make /dev/shm") |
|
||||||
|
|
||||||
try: |
|
||||||
with open('/tmp/sensor-test-results.json') as infile: |
|
||||||
data = json.load(infile) |
|
||||||
except Exception: |
|
||||||
data = {'sensor-pass': 0, 'sensor-fail': 0} |
|
||||||
|
|
||||||
STARTUP_SCRIPT = "/data/data/com.termux/files/continue.sh" |
|
||||||
try: |
|
||||||
with open(STARTUP_SCRIPT, 'w') as startup_script: |
|
||||||
startup_script.write("#!/usr/bin/bash\n\n/data/openpilot/selfdrive/debug/internal/sensor_test_bootloop.py\n") |
|
||||||
os.chmod(STARTUP_SCRIPT, stat.S_IRWXU) |
|
||||||
except Exception: |
|
||||||
print("Failed to install new startup script -- aborting") |
|
||||||
sys.exit(-1) |
|
||||||
|
|
||||||
sensord_env = {**os.environ, 'SENSOR_TEST': '1'} |
|
||||||
process = subprocess.run("./sensord", cwd="/data/openpilot/selfdrive/sensord", env=sensord_env) # pylint: disable=subprocess-run-check |
|
||||||
|
|
||||||
if process.returncode == 40: |
|
||||||
text = "Current run: SUCCESS\n" |
|
||||||
data['sensor-pass'] += 1 |
|
||||||
else: |
|
||||||
text = "Current run: FAIL\n" |
|
||||||
data['sensor-fail'] += 1 |
|
||||||
|
|
||||||
timestr = str(int(time.time())) |
|
||||||
with open('/tmp/dmesg-' + timestr + '.log', 'w') as dmesg_out: |
|
||||||
subprocess.call('dmesg', stdout=dmesg_out, shell=False) |
|
||||||
with open("/tmp/logcat-" + timestr + '.log', 'w') as logcat_out: |
|
||||||
subprocess.call(['logcat', '-d'], stdout=logcat_out, shell=False) |
|
||||||
|
|
||||||
text += "Sensor pass history: " + str(data['sensor-pass']) + "\n" |
|
||||||
text += "Sensor fail history: " + str(data['sensor-fail']) + "\n" |
|
||||||
|
|
||||||
print(text) |
|
||||||
|
|
||||||
with open('/tmp/sensor-test-results.json', 'w') as outfile: |
|
||||||
json.dump(data, outfile, indent=4) |
|
||||||
|
|
||||||
with TextWindow(text) as status: |
|
||||||
for _ in range(100): |
|
||||||
if status.get_status() == 1: |
|
||||||
with open(STARTUP_SCRIPT, 'w') as startup_script: |
|
||||||
startup_script.write("#!/usr/bin/bash\n\ncd /data/openpilot\nexec ./launch_openpilot.sh\n") |
|
||||||
os.chmod(STARTUP_SCRIPT, stat.S_IRWXU) |
|
||||||
break |
|
||||||
time.sleep(0.1) |
|
||||||
|
|
||||||
subprocess.Popen("reboot") |
|
@ -0,0 +1,13 @@ |
|||||||
|
#!/usr/bin/bash |
||||||
|
|
||||||
|
nmcli connection modify --temporary lte gsm.auto-config yes |
||||||
|
nmcli connection modify --temporary lte gsm.home-only yes |
||||||
|
nmcli connection modify --temporary lte connection.autoconnect-retries 20 |
||||||
|
|
||||||
|
# restart modem |
||||||
|
sudo systemctl stop ModemManager |
||||||
|
/usr/comma/lte/lte.sh stop_blocking |
||||||
|
sudo systemctl restart lte |
||||||
|
|
||||||
|
#sudo systemctl restart ModemManager |
||||||
|
sudo ModemManager --debug |
@ -0,0 +1,80 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
from typing import List |
||||||
|
|
||||||
|
from cereal import log, messaging |
||||||
|
from laika import AstroDog |
||||||
|
from laika.helpers import ConstellationId |
||||||
|
from laika.raw_gnss import GNSSMeasurement, calc_pos_fix, correct_measurements, process_measurements, read_raw_ublox |
||||||
|
|
||||||
|
|
||||||
|
def correct_and_pos_fix(processed_measurements: List[GNSSMeasurement], dog: AstroDog): |
||||||
|
# pos fix needs more than 5 processed_measurements |
||||||
|
pos_fix = calc_pos_fix(processed_measurements) |
||||||
|
|
||||||
|
if len(pos_fix) == 0: |
||||||
|
return [], [] |
||||||
|
est_pos = pos_fix[0][:3] |
||||||
|
corrected = correct_measurements(processed_measurements, est_pos, dog) |
||||||
|
return calc_pos_fix(corrected), corrected |
||||||
|
|
||||||
|
|
||||||
|
def process_ublox_msg(ublox_msg, dog, ublox_mono_time: int): |
||||||
|
if ublox_msg.which == 'measurementReport': |
||||||
|
report = ublox_msg.measurementReport |
||||||
|
if len(report.measurements) == 0: |
||||||
|
return None |
||||||
|
new_meas = read_raw_ublox(report) |
||||||
|
processed_measurements = process_measurements(new_meas, dog) |
||||||
|
|
||||||
|
corrected = correct_and_pos_fix(processed_measurements, dog) |
||||||
|
pos_fix, _ = corrected |
||||||
|
# todo send corrected messages instead of processed_measurements. Need fix for when having less than 6 measurements |
||||||
|
correct_meas_msgs = [create_measurement_msg(m) for m in processed_measurements] |
||||||
|
# pos fix can be an empty list if not enough correct measurements are available |
||||||
|
if len(pos_fix) > 0: |
||||||
|
corrected_pos = pos_fix[0][:3].tolist() |
||||||
|
else: |
||||||
|
corrected_pos = [0., 0., 0.] |
||||||
|
dat = messaging.new_message('gnssMeasurements') |
||||||
|
dat.gnssMeasurements = { |
||||||
|
"position": corrected_pos, |
||||||
|
"ubloxMonoTime": ublox_mono_time, |
||||||
|
"correctedMeasurements": correct_meas_msgs |
||||||
|
} |
||||||
|
return dat |
||||||
|
|
||||||
|
|
||||||
|
def create_measurement_msg(meas: GNSSMeasurement): |
||||||
|
c = log.GnssMeasurements.CorrectedMeasurement.new_message() |
||||||
|
c.constellationId = meas.constellation_id.value |
||||||
|
c.svId = int(meas.prn[1:]) |
||||||
|
c.glonassFrequency = meas.glonass_freq if meas.constellation_id == ConstellationId.GLONASS else 0 |
||||||
|
c.pseudorange = float(meas.observables['C1C']) # todo should be observables_final when using corrected measurements |
||||||
|
c.pseudorangeStd = float(meas.observables_std['C1C']) |
||||||
|
c.pseudorangeRate = float(meas.observables['D1C']) # todo should be observables_final when using corrected measurements |
||||||
|
c.pseudorangeRateStd = float(meas.observables_std['D1C']) |
||||||
|
c.satPos = meas.sat_pos_final.tolist() |
||||||
|
c.satVel = meas.sat_vel.tolist() |
||||||
|
return c |
||||||
|
|
||||||
|
|
||||||
|
def main(): |
||||||
|
dog = AstroDog() |
||||||
|
sm = messaging.SubMaster(['ubloxGnss']) |
||||||
|
pm = messaging.PubMaster(['gnssMeasurements']) |
||||||
|
|
||||||
|
while True: |
||||||
|
sm.update() |
||||||
|
|
||||||
|
# Todo if no internet available use latest ephemeris |
||||||
|
if sm.updated['ubloxGnss']: |
||||||
|
ublox_msg = sm['ubloxGnss'] |
||||||
|
msg = process_ublox_msg(ublox_msg, dog, sm.logMonoTime['ubloxGnss']) |
||||||
|
if msg is None: |
||||||
|
msg = messaging.new_message('gnssMeasurements') |
||||||
|
pm.send('gnssMeasurements', msg) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
main() |
@ -0,0 +1,23 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
import unittest |
||||||
|
from datetime import datetime |
||||||
|
|
||||||
|
from laika.helpers import ConstellationId |
||||||
|
|
||||||
|
from laika.gps_time import GPSTime |
||||||
|
from laika.raw_gnss import GNSSMeasurement |
||||||
|
from selfdrive.locationd.laikad import create_measurement_msg |
||||||
|
|
||||||
|
|
||||||
|
class TestLaikad(unittest.TestCase): |
||||||
|
|
||||||
|
def test_create_msg_without_errors(self): |
||||||
|
gpstime = GPSTime.from_datetime(datetime.now()) |
||||||
|
meas = GNSSMeasurement(ConstellationId.GPS, 1, gpstime.week, gpstime.tow, {'C1C': 0., 'D1C': 0.}, {'C1C': 0., 'D1C': 0.}) |
||||||
|
msg = create_measurement_msg(meas) |
||||||
|
|
||||||
|
self.assertEqual(msg.constellationId, 'gps') |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
unittest.main() |
@ -0,0 +1,80 @@ |
|||||||
|
import unittest |
||||||
|
|
||||||
|
import numpy as np |
||||||
|
|
||||||
|
from laika import AstroDog |
||||||
|
from laika.helpers import ConstellationId |
||||||
|
from laika.raw_gnss import calc_pos_fix, correct_measurements, process_measurements, read_raw_ublox |
||||||
|
from selfdrive.test.openpilotci import get_url |
||||||
|
from tools.lib.logreader import LogReader |
||||||
|
|
||||||
|
|
||||||
|
def get_gnss_measurements(log_reader): |
||||||
|
gnss_measurements = [] |
||||||
|
for msg in log_reader: |
||||||
|
if msg.which() == "ubloxGnss": |
||||||
|
ublox_msg = msg.ubloxGnss |
||||||
|
if ublox_msg.which == 'measurementReport': |
||||||
|
report = ublox_msg.measurementReport |
||||||
|
if len(report.measurements) > 0: |
||||||
|
gnss_measurements.append(read_raw_ublox(report)) |
||||||
|
return gnss_measurements |
||||||
|
|
||||||
|
|
||||||
|
class TestUbloxProcessing(unittest.TestCase): |
||||||
|
NUM_TEST_PROCESS_MEAS = 10 |
||||||
|
|
||||||
|
@classmethod |
||||||
|
def setUpClass(cls): |
||||||
|
lr = LogReader(get_url("4cf7a6ad03080c90|2021-09-29--13-46-36", 0)) |
||||||
|
cls.gnss_measurements = get_gnss_measurements(lr) |
||||||
|
|
||||||
|
def test_read_ublox_raw(self): |
||||||
|
count_gps = 0 |
||||||
|
count_glonass = 0 |
||||||
|
for measurements in self.gnss_measurements: |
||||||
|
for m in measurements: |
||||||
|
if m.constellation_id == ConstellationId.GPS: |
||||||
|
count_gps += 1 |
||||||
|
elif m.constellation_id == ConstellationId.GLONASS: |
||||||
|
count_glonass += 1 |
||||||
|
|
||||||
|
self.assertEqual(count_gps, 5036) |
||||||
|
self.assertEqual(count_glonass, 3651) |
||||||
|
|
||||||
|
def test_get_fix(self): |
||||||
|
dog = AstroDog() |
||||||
|
position_fix_found = 0 |
||||||
|
count_processed_measurements = 0 |
||||||
|
count_corrected_measurements = 0 |
||||||
|
position_fix_found_after_correcting = 0 |
||||||
|
|
||||||
|
pos_ests = [] |
||||||
|
for measurements in self.gnss_measurements[:self.NUM_TEST_PROCESS_MEAS]: |
||||||
|
processed_meas = process_measurements(measurements, dog) |
||||||
|
count_processed_measurements += len(processed_meas) |
||||||
|
pos_fix = calc_pos_fix(processed_meas) |
||||||
|
if len(pos_fix) > 0 and all(pos_fix[0] != 0): |
||||||
|
position_fix_found += 1 |
||||||
|
|
||||||
|
corrected_meas = correct_measurements(processed_meas, pos_fix[0][:3], dog) |
||||||
|
count_corrected_measurements += len(corrected_meas) |
||||||
|
|
||||||
|
pos_fix = calc_pos_fix(corrected_meas) |
||||||
|
if len(pos_fix) > 0 and all(pos_fix[0] != 0): |
||||||
|
pos_ests.append(pos_fix[0]) |
||||||
|
position_fix_found_after_correcting += 1 |
||||||
|
|
||||||
|
mean_fix = np.mean(np.array(pos_ests)[:, :3], axis=0) |
||||||
|
np.testing.assert_allclose(mean_fix, [-2452306.662377, -4778343.136806, 3428550.090557], rtol=0, atol=1) |
||||||
|
|
||||||
|
# Note that can happen that there are less corrected measurements compared to processed when they are invalid. |
||||||
|
# However, not for the current segment |
||||||
|
self.assertEqual(position_fix_found, self.NUM_TEST_PROCESS_MEAS) |
||||||
|
self.assertEqual(position_fix_found_after_correcting, self.NUM_TEST_PROCESS_MEAS) |
||||||
|
self.assertEqual(count_processed_measurements, 69) |
||||||
|
self.assertEqual(count_corrected_measurements, 69) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
unittest.main() |
@ -1 +1,2 @@ |
|||||||
fakedata/ |
fakedata/ |
||||||
|
debayer_diff.txt |
||||||
|
@ -0,0 +1 @@ |
|||||||
|
14f411de8085d1cc9e467592c90bcaf95447a467 |
@ -1 +1 @@ |
|||||||
70d79fbcc2b9ab0af867a7d6f138b58bcaaa3aa8 |
10b766fa845934f0258c52cdf2103d0e1a9496c9 |
@ -0,0 +1,215 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
import os |
||||||
|
import sys |
||||||
|
import bz2 |
||||||
|
import numpy as np |
||||||
|
|
||||||
|
import pyopencl as cl # install with `PYOPENCL_CL_PRETEND_VERSION=2.0 pip install pyopencl` |
||||||
|
|
||||||
|
from selfdrive.hardware import PC, TICI |
||||||
|
from common.basedir import BASEDIR |
||||||
|
from selfdrive.test.openpilotci import BASE_URL, get_url |
||||||
|
from selfdrive.version import get_commit |
||||||
|
from tools.lib.logreader import LogReader |
||||||
|
from tools.lib.filereader import FileReader |
||||||
|
|
||||||
|
TEST_ROUTE = "8345e3b82948d454|2022-05-04--13-45-33" |
||||||
|
SEGMENT = 0 |
||||||
|
|
||||||
|
FRAME_WIDTH = 1928 |
||||||
|
FRAME_HEIGHT = 1208 |
||||||
|
FRAME_STRIDE = 2896 |
||||||
|
|
||||||
|
UV_WIDTH = FRAME_WIDTH // 2 |
||||||
|
UV_HEIGHT = FRAME_HEIGHT // 2 |
||||||
|
UV_SIZE = UV_WIDTH * UV_HEIGHT |
||||||
|
|
||||||
|
|
||||||
|
def get_frame_fn(ref_commit, test_route, tici=True): |
||||||
|
return f"{test_route}_debayer{'_tici' if tici else ''}_{ref_commit}.bz2" |
||||||
|
|
||||||
|
|
||||||
|
def bzip_frames(frames): |
||||||
|
data = bytes() |
||||||
|
for y, u, v in frames: |
||||||
|
data += y.tobytes() |
||||||
|
data += u.tobytes() |
||||||
|
data += v.tobytes() |
||||||
|
return bz2.compress(data) |
||||||
|
|
||||||
|
|
||||||
|
def unbzip_frames(url): |
||||||
|
with FileReader(url) as f: |
||||||
|
dat = f.read() |
||||||
|
|
||||||
|
data = bz2.decompress(dat) |
||||||
|
|
||||||
|
res = [] |
||||||
|
for y_start in range(0, len(data), FRAME_WIDTH * FRAME_HEIGHT + UV_SIZE * 2): |
||||||
|
u_start = y_start + FRAME_WIDTH * FRAME_HEIGHT |
||||||
|
v_start = u_start + UV_SIZE |
||||||
|
|
||||||
|
y = np.frombuffer(data[y_start: u_start], dtype=np.uint8).reshape((FRAME_HEIGHT, FRAME_WIDTH)) |
||||||
|
u = np.frombuffer(data[u_start: v_start], dtype=np.uint8).reshape((UV_HEIGHT, UV_WIDTH)) |
||||||
|
v = np.frombuffer(data[v_start: v_start + UV_SIZE], dtype=np.uint8).reshape((UV_HEIGHT, UV_WIDTH)) |
||||||
|
|
||||||
|
res.append((y, u, v)) |
||||||
|
|
||||||
|
return res |
||||||
|
|
||||||
|
|
||||||
|
def init_kernels(frame_offset=0): |
||||||
|
ctx = cl.create_some_context(interactive=False) |
||||||
|
|
||||||
|
with open(os.path.join(BASEDIR, 'selfdrive/camerad/cameras/real_debayer.cl')) as f: |
||||||
|
build_args = ' -cl-fast-relaxed-math -cl-denorms-are-zero -cl-single-precision-constant' + \ |
||||||
|
f' -DFRAME_STRIDE={FRAME_STRIDE} -DRGB_WIDTH={FRAME_WIDTH} -DRGB_HEIGHT={FRAME_HEIGHT} -DFRAME_OFFSET={frame_offset} -DCAM_NUM=0' |
||||||
|
if PC: |
||||||
|
build_args += ' -DHALF_AS_FLOAT=1 -cl-std=CL2.0' |
||||||
|
debayer_prg = cl.Program(ctx, f.read()).build(options=build_args) |
||||||
|
|
||||||
|
with open(os.path.join(BASEDIR, 'selfdrive/camerad/transforms/rgb_to_yuv.cl')) as f: |
||||||
|
build_args = f' -cl-fast-relaxed-math -cl-denorms-are-zero -DWIDTH={FRAME_WIDTH} -DHEIGHT={FRAME_HEIGHT}' + \ |
||||||
|
f' -DUV_WIDTH={UV_WIDTH} -DUV_HEIGHT={UV_HEIGHT} -DRGB_STRIDE={FRAME_WIDTH*3}' + \ |
||||||
|
f' -DRGB_SIZE={FRAME_WIDTH*FRAME_HEIGHT}' |
||||||
|
rgb_to_yuv_prg = cl.Program(ctx, f.read()).build(options=build_args) |
||||||
|
|
||||||
|
return ctx, debayer_prg, rgb_to_yuv_prg |
||||||
|
|
||||||
|
|
||||||
|
def debayer_frame(ctx, debayer_prg, rgb_to_yuv_prg, data, rgb=False): |
||||||
|
q = cl.CommandQueue(ctx) |
||||||
|
|
||||||
|
rgb_buff = np.empty(FRAME_WIDTH * FRAME_HEIGHT * 3, dtype=np.uint8) |
||||||
|
yuv_buff = np.empty(FRAME_WIDTH * FRAME_HEIGHT + UV_SIZE * 2, dtype=np.uint8) |
||||||
|
|
||||||
|
cam_g = cl.Buffer(ctx, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=data) |
||||||
|
rgb_wg = cl.Buffer(ctx, cl.mem_flags.WRITE_ONLY, FRAME_WIDTH * FRAME_HEIGHT * 3) |
||||||
|
yuv_g = cl.Buffer(ctx, cl.mem_flags.WRITE_ONLY, FRAME_WIDTH * FRAME_HEIGHT + UV_SIZE * 2) |
||||||
|
|
||||||
|
local_worksize = (16, 16) if TICI else (8, 8) |
||||||
|
local_mem = cl.LocalMemory(648 if TICI else 400) |
||||||
|
ev1 = debayer_prg.debayer10(q, (FRAME_WIDTH, FRAME_HEIGHT), local_worksize, cam_g, rgb_wg, local_mem, np.float32(42)) |
||||||
|
cl.enqueue_copy(q, rgb_buff, rgb_wg, wait_for=[ev1]).wait() |
||||||
|
cl.enqueue_barrier(q) |
||||||
|
|
||||||
|
rgb_rg = cl.Buffer(ctx, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=rgb_buff) |
||||||
|
cl.enqueue_barrier(q) |
||||||
|
|
||||||
|
ev3 = rgb_to_yuv_prg.rgb_to_yuv(q, (FRAME_WIDTH // 4, FRAME_HEIGHT // 4), None, rgb_rg, yuv_g) |
||||||
|
cl.enqueue_barrier(q) |
||||||
|
|
||||||
|
cl.enqueue_copy(q, yuv_buff, yuv_g, wait_for=[ev3]).wait() |
||||||
|
cl.enqueue_barrier(q) |
||||||
|
|
||||||
|
y = yuv_buff[:FRAME_WIDTH*FRAME_HEIGHT].reshape((FRAME_HEIGHT, FRAME_WIDTH)) |
||||||
|
u = yuv_buff[FRAME_WIDTH*FRAME_HEIGHT:FRAME_WIDTH*FRAME_HEIGHT+UV_SIZE].reshape((UV_HEIGHT, UV_WIDTH)) |
||||||
|
v = yuv_buff[FRAME_WIDTH*FRAME_HEIGHT+UV_SIZE:].reshape((UV_HEIGHT, UV_WIDTH)) |
||||||
|
|
||||||
|
if rgb: |
||||||
|
return rgb_buff.reshape((FRAME_HEIGHT, FRAME_WIDTH, 3))[:, :, (2, 1, 0)] |
||||||
|
else: |
||||||
|
return y, u, v |
||||||
|
|
||||||
|
|
||||||
|
def debayer_replay(lr): |
||||||
|
ctx, debayer_prg, rgb_to_yuv_prg = init_kernels() |
||||||
|
|
||||||
|
frames = [] |
||||||
|
for m in lr: |
||||||
|
if m.which() == 'roadCameraState': |
||||||
|
cs = m.roadCameraState |
||||||
|
if cs.image: |
||||||
|
data = np.frombuffer(cs.image, dtype=np.uint8) |
||||||
|
img = debayer_frame(ctx, debayer_prg, rgb_to_yuv_prg, data) |
||||||
|
|
||||||
|
frames.append(img) |
||||||
|
|
||||||
|
return frames |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
update = "--update" in sys.argv |
||||||
|
replay_dir = os.path.dirname(os.path.abspath(__file__)) |
||||||
|
ref_commit_fn = os.path.join(replay_dir, "debayer_replay_ref_commit") |
||||||
|
|
||||||
|
# load logs |
||||||
|
lr = list(LogReader(get_url(TEST_ROUTE, SEGMENT))) |
||||||
|
|
||||||
|
# run replay |
||||||
|
frames = debayer_replay(lr) |
||||||
|
|
||||||
|
# get diff |
||||||
|
failed = False |
||||||
|
diff = '' |
||||||
|
yuv_i = ['y', 'u', 'v'] |
||||||
|
if not update: |
||||||
|
with open(ref_commit_fn) as f: |
||||||
|
ref_commit = f.read().strip() |
||||||
|
frame_fn = get_frame_fn(ref_commit, TEST_ROUTE, tici=TICI) |
||||||
|
|
||||||
|
try: |
||||||
|
cmp_frames = unbzip_frames(BASE_URL + frame_fn) |
||||||
|
|
||||||
|
if len(frames) != len(cmp_frames): |
||||||
|
failed = True |
||||||
|
diff += 'amount of frames not equal\n' |
||||||
|
|
||||||
|
for i, (frame, cmp_frame) in enumerate(zip(frames, cmp_frames)): |
||||||
|
for j in range(3): |
||||||
|
fr = frame[j] |
||||||
|
cmp_f = cmp_frame[j] |
||||||
|
if fr.shape != cmp_f.shape: |
||||||
|
failed = True |
||||||
|
diff += f'frame shapes not equal for ({i}, {yuv_i[j]})\n' |
||||||
|
diff += f'{ref_commit}: {cmp_f.shape}\n' |
||||||
|
diff += f'HEAD: {fr.shape}\n' |
||||||
|
elif not np.array_equal(fr, cmp_f): |
||||||
|
failed = True |
||||||
|
if np.allclose(fr, cmp_f, atol=1): |
||||||
|
diff += f'frames not equal for ({i}, {yuv_i[j]}), but are all close\n' |
||||||
|
else: |
||||||
|
diff += f'frames not equal for ({i}, {yuv_i[j]})\n' |
||||||
|
|
||||||
|
frame_diff = np.abs(np.subtract(fr, cmp_f)) |
||||||
|
diff_len = len(np.nonzero(frame_diff)[0]) |
||||||
|
if diff_len > 1000: |
||||||
|
diff += f'different at a large amount of pixels ({diff_len})\n' |
||||||
|
else: |
||||||
|
diff += 'different at (frame, yuv, pixel, ref, HEAD):\n' |
||||||
|
for k in zip(*np.nonzero(frame_diff)): |
||||||
|
diff += f'{i}, {yuv_i[j]}, {k}, {cmp_f[k]}, {fr[k]}\n' |
||||||
|
|
||||||
|
if failed: |
||||||
|
print(diff) |
||||||
|
with open("debayer_diff.txt", "w") as f: |
||||||
|
f.write(diff) |
||||||
|
except Exception as e: |
||||||
|
print(str(e)) |
||||||
|
failed = True |
||||||
|
|
||||||
|
# upload new refs |
||||||
|
if update or (failed and TICI): |
||||||
|
from selfdrive.test.openpilotci import upload_file |
||||||
|
|
||||||
|
print("Uploading new refs") |
||||||
|
|
||||||
|
frames_bzip = bzip_frames(frames) |
||||||
|
|
||||||
|
new_commit = get_commit() |
||||||
|
frame_fn = os.path.join(replay_dir, get_frame_fn(new_commit, TEST_ROUTE, tici=TICI)) |
||||||
|
with open(frame_fn, "wb") as f2: |
||||||
|
f2.write(frames_bzip) |
||||||
|
|
||||||
|
try: |
||||||
|
upload_file(frame_fn, os.path.basename(frame_fn)) |
||||||
|
except Exception as e: |
||||||
|
print("failed to upload", e) |
||||||
|
|
||||||
|
if update: |
||||||
|
with open(ref_commit_fn, 'w') as f: |
||||||
|
f.write(str(new_commit)) |
||||||
|
|
||||||
|
print("\nNew ref commit: ", new_commit) |
||||||
|
|
||||||
|
sys.exit(int(failed)) |
Loading…
Reference in new issue