offline_check.py 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env python
  2. '''
  3. Check a set of terrain files for corruption
  4. '''
  5. import os
  6. #from multiprocessing import Pool
  7. from multiprocessing.pool import ThreadPool
  8. import argparse
  9. import time
  10. import gzip
  11. import shutil
  12. import struct
  13. import crc16
  14. from terrain_gen import TERRAIN_GRID_BLOCK_SIZE_Y, east_blocks, IO_BLOCK_SIZE, TERRAIN_GRID_FORMAT_VERSION, GridBlock
  15. # IO block size is 2048
  16. # Actual size is 1821 bytes
  17. # Last 227 bytes is filling
  18. def check_filled(block, lat_int, lon_int, grid_spacing):
  19. '''check a block for validity'''
  20. if len(block) != IO_BLOCK_SIZE - 227:
  21. print("Bad size {0} of {1}".format(len(block), IO_BLOCK_SIZE))
  22. return False
  23. (bitmap, lat, lon, crc, version, spacing) = struct.unpack("<QiiHHH", block[:22])
  24. if (version != TERRAIN_GRID_FORMAT_VERSION):
  25. print("Bad version: " + str(version))
  26. return False
  27. if abs(lat_int - (lat/1E7)) > 2 or abs(lon_int - (lon/1E7)) > 2:
  28. print("Bad lat/lon: {0}, {1}".format((lat/1E7), (lon/1E7)))
  29. return False
  30. if spacing != 100:
  31. print("Bad spacing: " + str(spacing))
  32. return False
  33. if bitmap != (1<<56)-1:
  34. print("Bad bitmap")
  35. return False
  36. block = block[:16] + struct.pack("<H", 0) + block[18:]
  37. crc2 = crc16.crc16xmodem(block[:1821])
  38. if crc2 != crc:
  39. print("Bad CRC")
  40. return False
  41. return True
  42. if __name__ == '__main__':
  43. # Create the parser
  44. parser = argparse.ArgumentParser(description='ArduPilot Terrain DAT file generator')
  45. # Add the arguments
  46. # Folder to store processed DAT files
  47. parser.add_argument('-folder', action="store", dest="folder", default="processedTerrain")
  48. args = parser.parse_args()
  49. targetFolder = os.path.join(os.getcwd(), args.folder)
  50. grid_spacing = 100
  51. #for each file in folder
  52. for file in os.listdir(targetFolder):
  53. if file.endswith("DAT.gz") or file.endswith("DAT"):
  54. # It's a compressed tile
  55. # 1. Check it's a valid gzip
  56. tile = None
  57. try:
  58. lat_int = int(os.path.basename(file)[1:3])
  59. if os.path.basename(file)[0:1] == "S":
  60. lat_int = -lat_int
  61. lon_int = int(os.path.basename(file)[4:7])
  62. if os.path.basename(file)[3:4] == "W":
  63. lon_int = -lon_int
  64. if file.endswith("DAT.gz"):
  65. with gzip.open(os.path.join(targetFolder, file), 'rb') as f:
  66. tile = f.read()
  67. else:
  68. with open(os.path.join(targetFolder, file), 'rb') as f:
  69. tile = f.read()
  70. except Exception as e:
  71. print("Bad file: " + file)
  72. print(e)
  73. # 2. Is it a valid dat file?
  74. if (tile):
  75. total_blocks = east_blocks(lat_int*1e7, lon_int*1e7, grid_spacing) * TERRAIN_GRID_BLOCK_SIZE_Y
  76. # 2a. Are the correct number of blocks present?
  77. # There is an extra 1821 bytes at the end on the file (2048-1821 = 227), as the
  78. # terrain blocks only take up 1821 bytes.
  79. if (len(tile)+227) != (total_blocks * IO_BLOCK_SIZE):
  80. print("Bad number of blocks: {0}, {1} vs {2}".format(file, len(tile), total_blocks * IO_BLOCK_SIZE))
  81. # 2b. Does each block have the correct CRC and fields?
  82. for blocknum in range(total_blocks):
  83. block = tile[(blocknum * IO_BLOCK_SIZE):((blocknum + 1)* IO_BLOCK_SIZE)-227]
  84. if not check_filled(block, lat_int, lon_int, 100):
  85. print("Bad data in block {0} of {1}".format(blocknum, total_blocks))
  86. else:
  87. print("Bad tile: " + file)
  88. print("Done!")