mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-24 15:40:31 +08:00
delete sdlog2
This commit is contained in:
committed by
Lorenz Meier
parent
83fd5a5fd1
commit
8537863848
@@ -4,30 +4,24 @@
|
||||
# Standard startup script for logging
|
||||
#
|
||||
|
||||
if param compare SYS_LOGGER 0
|
||||
set LOGGER_ARGS ""
|
||||
|
||||
if param compare SDLOG_MODE 1
|
||||
then
|
||||
sdlog2 start -r 100 -a -b 9 -t
|
||||
else
|
||||
set LOGGER_ARGS ""
|
||||
|
||||
if param compare SDLOG_MODE 1
|
||||
then
|
||||
set LOGGER_ARGS "-e"
|
||||
fi
|
||||
|
||||
if param compare SDLOG_MODE 2
|
||||
then
|
||||
set LOGGER_ARGS "-f"
|
||||
fi
|
||||
|
||||
if ver hwcmp AEROFC_V1
|
||||
then
|
||||
set LOGGER_ARGS "-m mavlink"
|
||||
fi
|
||||
|
||||
logger start -b ${LOGGER_BUF} -t ${LOGGER_ARGS}
|
||||
|
||||
unset LOGGER_ARGS
|
||||
set LOGGER_ARGS "-e"
|
||||
fi
|
||||
|
||||
if param compare SDLOG_MODE 2
|
||||
then
|
||||
set LOGGER_ARGS "-f"
|
||||
fi
|
||||
|
||||
if ver hwcmp AEROFC_V1
|
||||
then
|
||||
set LOGGER_ARGS "-m mavlink"
|
||||
fi
|
||||
|
||||
logger start -b ${LOGGER_BUF} -t ${LOGGER_ARGS}
|
||||
|
||||
unset LOGGER_ARGS
|
||||
unset LOGGER_BUF
|
||||
|
||||
@@ -16,7 +16,6 @@ exec find src platforms \
|
||||
-path src/lib/matrix -prune -o \
|
||||
-path src/modules/commander -prune -o \
|
||||
-path src/modules/micrortps_bridge/micro-CDR -prune -o \
|
||||
-path src/modules/sdlog2 -prune -o \
|
||||
-path src/modules/systemlib/uthash -prune -o \
|
||||
-path src/modules/uavcan/libuavcan -prune -o \
|
||||
-type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" \) | grep $PATTERN
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
====== PX4 LOG CONVERSION ======
|
||||
|
||||
On each log session (commonly started and stopped by arming and disarming the vehicle) a new file logxxx.bin is created. In many cases there will be only one logfile named log001.bin (only one flight).
|
||||
|
||||
There are two conversion scripts in this ZIP file:
|
||||
|
||||
logconv.m: This is a MATLAB script which will automatically convert and display the flight data with a GUI. If running this script, the second script can be ignored.
|
||||
|
||||
sdlog2_dump.py: This is a Python script (compatible with v2 and v3) which converts the self-describing binary log format to a CSV file. To export a CSV file from within a shell (Windows CMD or BASH on Linux / Mac OS), run:
|
||||
|
||||
```
|
||||
python sdlog2_dump.py log001.bin -f "export.csv" -t "TIME" -d "," -n ""
|
||||
```
|
||||
|
||||
geo_tag_images.py: Use this script to geotag a set of images. It uses GPS time and file creation date to synchronize the images, so it needs that the images have a valid creation date. Can generate a KML file to view where the photos were taken in Google Earth (including height).
|
||||
|
||||
```sh
|
||||
python geo_tag_images.py --logfile=mylog.bin --input=images/ --output=tagged/ --kml -v
|
||||
|
||||
python geo_tag_images.py -l=mylog.bin -i=images/ -o=tagged/ --kml -v
|
||||
```
|
||||
|
||||
geotagging.py: Use this script to geotag a set of images. It uses the CAM trigger data from the log file for image association.
|
||||
|
||||
```sh
|
||||
python geotagging.py --logfile=mylog.bin --input=images/ --output=tagged/
|
||||
```
|
||||
|
||||
Python can be downloaded from http://python.org, but is available as default on Mac OS and Linux.
|
||||
@@ -1,434 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Tag the images recorded during a flight with geo location extracted from
|
||||
# a PX4 binary log file.
|
||||
#
|
||||
# This file accepts *.jpg format images and reads position information
|
||||
# from a *.px4log file
|
||||
#
|
||||
# Example Syntax:
|
||||
# python geo_tag_images.py --logfile=log001.px4log --input=images/ --output=imagesWithTag/ --offset=-0.4 -v
|
||||
#
|
||||
# Optional: Correct image times first
|
||||
# jhead -exonly -ft -n%Y-%m-%d\ %H.%M.%S -ta+HH:MM:SS *.JPG
|
||||
#
|
||||
# Author: Hector Azpurua hector@azpurua.com
|
||||
# Based on the script of Andreas Bircher
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import bisect
|
||||
import pyexiv2
|
||||
import argparse
|
||||
from lxml import etree
|
||||
import datetime
|
||||
import calendar
|
||||
from shutil import copyfile
|
||||
from subprocess import check_output
|
||||
from pykml.factory import KML_ElementMaker as KML
|
||||
from pykml.factory import GX_ElementMaker as GX
|
||||
|
||||
|
||||
class GpsPosition(object):
|
||||
|
||||
def __init__(self, timestamp, lat, lon, alt):
|
||||
self.timestamp = timestamp
|
||||
self.lat = float(lat)
|
||||
self.lon = float(lon)
|
||||
self.alt = float(alt)
|
||||
|
||||
|
||||
class Main:
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
|
||||
:param logfile:
|
||||
:param input:
|
||||
:param output:
|
||||
:param offset:
|
||||
:param verbose:
|
||||
:return:
|
||||
"""
|
||||
args = self.get_arg()
|
||||
|
||||
self.logfile = args['logfile']
|
||||
self.input = args['input']
|
||||
self.output = args['output']
|
||||
self.kml = args['kml']
|
||||
self.verbose = args['verbose']
|
||||
self.offset = args['offset']
|
||||
self.time_thresh = args['threshold']
|
||||
|
||||
self.tdiff_list = []
|
||||
self.non_processed_files = []
|
||||
self.tagged_gps = []
|
||||
|
||||
print '[INFO] Loading logs and images locations...'
|
||||
|
||||
self.gps_list = self.load_gps_from_log(self.logfile, self.offset)
|
||||
self.img_list = self.load_image_list(self.input)
|
||||
|
||||
if len(self.img_list) <= 0:
|
||||
print '[ERROR] Cannot load JPG images from input folder, please check filename extensions.'
|
||||
sys.exit(1)
|
||||
|
||||
if not os.path.exists(self.output):
|
||||
os.makedirs(self.output)
|
||||
|
||||
if not self.output.endswith(os.path.sep):
|
||||
self.output += os.path.sep
|
||||
|
||||
self.tag_images()
|
||||
|
||||
if self.kml and len(self.tdiff_list) > 0:
|
||||
self.gen_kml()
|
||||
|
||||
if len(self.non_processed_files) > 0:
|
||||
print '[WARNING] Some images werent processed (', len(self.non_processed_files), 'of', len(self.img_list), '):'
|
||||
for elem in self.non_processed_files:
|
||||
print '\t', elem
|
||||
|
||||
@staticmethod
|
||||
def to_degree(value, loc):
|
||||
"""
|
||||
Convert a lat or lon value to degrees/minutes/seconds
|
||||
:param value: the latitude or longitude value
|
||||
:param loc: could be ["S", "N"] or ["W", "E"]
|
||||
:return:
|
||||
"""
|
||||
if value < 0:
|
||||
loc_value = loc[0]
|
||||
elif value > 0:
|
||||
loc_value = loc[1]
|
||||
else:
|
||||
loc_value = ""
|
||||
|
||||
absolute_value = abs(value)
|
||||
deg = int(absolute_value)
|
||||
t1 = (absolute_value - deg) * 60
|
||||
minute = int(t1)
|
||||
sec = round((t1 - minute) * 60, 5)
|
||||
|
||||
return deg, minute, sec, loc_value
|
||||
|
||||
@staticmethod
|
||||
def gps_week_seconds_to_datetime(gpsweek, gpsmillis, leapmillis=0):
|
||||
"""
|
||||
Convert GPS week and seconds to datetime object, using leap milliseconds if necessary
|
||||
:param gpsweek:
|
||||
:param gpsmillis:
|
||||
:param leapmillis:
|
||||
:return:
|
||||
"""
|
||||
datetimeformat = "%Y-%m-%d %H:%M:%S.%f"
|
||||
epoch = datetime.datetime.strptime(
|
||||
"1980-01-06 00:00:00.000", datetimeformat)
|
||||
elapsed = datetime.timedelta(
|
||||
days=(gpsweek * 7), milliseconds=(gpsmillis + leapmillis))
|
||||
|
||||
return Main.utc_to_local(epoch + elapsed)
|
||||
|
||||
@staticmethod
|
||||
def unix_microseconds_to_datetime(unix_us, offset=0):
|
||||
"""
|
||||
Convert unix microseconds to datetime object, using offset milliseconds if necessary
|
||||
:param unix_us:
|
||||
:param offset:
|
||||
:return:
|
||||
"""
|
||||
|
||||
# time in seconds
|
||||
time_s = int(unix_us) / 1000000 + (offset / 1000)
|
||||
datetime_from_unix = datetime.datetime.fromtimestamp(time_s)
|
||||
|
||||
return datetime_from_unix
|
||||
|
||||
@staticmethod
|
||||
def utc_to_local(utc_dt):
|
||||
"""
|
||||
Convert UTC time in local time
|
||||
:param utc_dt:
|
||||
:return:
|
||||
"""
|
||||
# use integer timestamp to avoid precision loss
|
||||
timestamp = calendar.timegm(utc_dt.timetuple())
|
||||
local_dt = datetime.datetime.fromtimestamp(timestamp)
|
||||
assert utc_dt.resolution >= datetime.timedelta(microseconds=1)
|
||||
|
||||
return local_dt.replace(microsecond=utc_dt.microsecond)
|
||||
|
||||
def gen_kml(self):
|
||||
"""
|
||||
Generate a KML file with keypoints on the locations of the pictures, including height
|
||||
:return:
|
||||
"""
|
||||
style_dot = "sn_shaded_dot"
|
||||
style_path = "red_path"
|
||||
|
||||
doc = KML.kml(
|
||||
KML.Document(
|
||||
KML.Name("GPS of the images"),
|
||||
KML.Style(
|
||||
KML.IconStyle(
|
||||
KML.scale(0.4),
|
||||
KML.Icon(
|
||||
KML.href(
|
||||
"http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png")
|
||||
),
|
||||
),
|
||||
id=style_dot,
|
||||
),
|
||||
KML.Style(
|
||||
KML.LineStyle(
|
||||
KML.color('7f0000ff'),
|
||||
KML.width(6),
|
||||
GX.labelVisibility('1'),
|
||||
),
|
||||
id=style_path
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
# create points
|
||||
for i, gps in enumerate(self.tagged_gps):
|
||||
ii = i + 1
|
||||
doc.Document.append(
|
||||
KML.Placemark(
|
||||
KML.styleUrl('#{0}'.format(style_dot)),
|
||||
KML.Point(
|
||||
KML.extrude(True),
|
||||
KML.altitudeMode('absolute'),
|
||||
KML.coordinates(
|
||||
"{},{},{}".format(gps.lon, gps.lat, gps.alt))
|
||||
),
|
||||
KML.name(
|
||||
str(ii)) if ii % 5 == 0 or ii == 1 else KML.name()
|
||||
)
|
||||
)
|
||||
|
||||
# create the path
|
||||
doc.Document.append(
|
||||
KML.Placemark(
|
||||
KML.styleUrl('#{0}'.format(style_path)),
|
||||
KML.LineString(
|
||||
KML.altitudeMode('absolute'),
|
||||
KML.coordinates(
|
||||
' '.join(["{},{},{}".format(gps.lon, gps.lat, gps.alt)
|
||||
for gps in self.tagged_gps])
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
s = etree.tostring(doc)
|
||||
|
||||
file_path = self.output + 'GoogleEarth_points.kml'
|
||||
f = open(file_path, 'w')
|
||||
f.write(s)
|
||||
f.close()
|
||||
|
||||
print '[INFO] KML file generated on:', file_path
|
||||
|
||||
def get_closest_datetime_index(self, datetime_list, elem):
|
||||
"""
|
||||
Get the closest element between a list of datetime objects and a date
|
||||
:param datetime_list:
|
||||
:param elem:
|
||||
:return:
|
||||
"""
|
||||
dlist_len = len(datetime_list)
|
||||
|
||||
i = bisect.bisect_left(datetime_list, elem)
|
||||
|
||||
# Cleanup of the indices
|
||||
if i < 0:
|
||||
i = 0
|
||||
elif i >= dlist_len:
|
||||
i = dlist_len - 1
|
||||
|
||||
date = datetime_list[i]
|
||||
diff = abs((date - elem).total_seconds())
|
||||
|
||||
if diff > self.time_thresh:
|
||||
return -1, diff
|
||||
|
||||
return i, diff
|
||||
|
||||
def set_gps_location(self, file_name, lat, lng, alt):
|
||||
"""
|
||||
Add the GPS tag and altitude to a image file
|
||||
:param file_name:
|
||||
:param lat:
|
||||
:param lng:
|
||||
:param alt:
|
||||
:return:
|
||||
"""
|
||||
lat_deg = self.to_degree(lat, ["S", "N"])
|
||||
lng_deg = self.to_degree(lng, ["W", "E"])
|
||||
|
||||
exiv_lat = (pyexiv2.Rational(lat_deg[0] * 60 + lat_deg[1], 60),
|
||||
pyexiv2.Rational(lat_deg[2] * 100, 6000), pyexiv2.Rational(0, 1))
|
||||
exiv_lng = (pyexiv2.Rational(lng_deg[0] * 60 + lng_deg[1], 60),
|
||||
pyexiv2.Rational(lng_deg[2] * 100, 6000), pyexiv2.Rational(0, 1))
|
||||
|
||||
try:
|
||||
exiv_image = pyexiv2.ImageMetadata(file_name)
|
||||
exiv_image.read()
|
||||
|
||||
exiv_image["Exif.GPSInfo.GPSLatitude"] = exiv_lat
|
||||
exiv_image["Exif.GPSInfo.GPSLatitudeRef"] = lat_deg[3]
|
||||
exiv_image["Exif.GPSInfo.GPSLongitude"] = exiv_lng
|
||||
exiv_image["Exif.GPSInfo.GPSLongitudeRef"] = lng_deg[3]
|
||||
exiv_image["Exif.GPSInfo.GPSAltitude"] = pyexiv2.Rational(alt, 1)
|
||||
exiv_image["Exif.GPSInfo.GPSAltitudeRef"] = '0'
|
||||
exiv_image["Exif.Image.GPSTag"] = 654
|
||||
exiv_image["Exif.GPSInfo.GPSMapDatum"] = "WGS-84"
|
||||
exiv_image["Exif.GPSInfo.GPSVersionID"] = '2 0 0 0'
|
||||
|
||||
exiv_image.write(True)
|
||||
except Exception as e:
|
||||
print '[ERROR]', e
|
||||
|
||||
def load_gps_from_log(self, log_file, offset):
|
||||
"""
|
||||
Load gps list from PX4 binary log
|
||||
:param log_file:
|
||||
:param offset:
|
||||
:return:
|
||||
"""
|
||||
gps_list = []
|
||||
out = check_output(
|
||||
["python", "sdlog2_dump.py", log_file, "-m GPS", "-v"])
|
||||
|
||||
for line in out.splitlines():
|
||||
if not line.startswith("MSG GPS:"):
|
||||
continue
|
||||
|
||||
vdict = {}
|
||||
pairs = re.split(r'[;,:]\s*', line)
|
||||
for pair in pairs:
|
||||
e = pair.split('=')
|
||||
if len(e) == 2:
|
||||
vdict[e[0]] = float(e[1])
|
||||
|
||||
# PX4 GPS.GPSTime is unix time in microseconds
|
||||
gps_time = vdict['GPSTime']
|
||||
gps_lat = vdict['Lat']
|
||||
gps_lon = vdict['Lon']
|
||||
gps_alt = vdict['Alt']
|
||||
|
||||
date = self.unix_microseconds_to_datetime(gps_time, offset)
|
||||
gps_list.append(GpsPosition(date, gps_lat, gps_lon, gps_alt))
|
||||
|
||||
return gps_list
|
||||
|
||||
def get_image_creation_date(self, filename):
|
||||
exiv_image = pyexiv2.ImageMetadata(filename)
|
||||
exiv_image.read()
|
||||
|
||||
# Prefer DateTime/Original over the other values
|
||||
if 'Exif.Photo.DateTimeOriginal' in exiv_image:
|
||||
cdate = exiv_image['Exif.Photo.DateTimeOriginal'].value
|
||||
return cdate
|
||||
elif 'Exif.Image.DateTime' in exiv_image:
|
||||
cdate = exiv_image['Exif.Image.DateTime'].value
|
||||
return cdate
|
||||
else:
|
||||
epoch = os.path.getmtime(filename)
|
||||
return datetime.datetime.fromtimestamp(epoch)
|
||||
|
||||
def load_image_list(self, input_folder, file_type='jpg'):
|
||||
"""
|
||||
Load image list from a folder given a file type
|
||||
:param input_folder:
|
||||
:param file_type:
|
||||
:return:
|
||||
"""
|
||||
self.img_list = [input_folder + filename for filename in os.listdir(input_folder)
|
||||
if re.search(r'\.' + file_type + '$', filename, re.IGNORECASE)]
|
||||
self.img_list = sorted(self.img_list)
|
||||
return self.img_list
|
||||
|
||||
def tag_images(self):
|
||||
"""
|
||||
Tag the image list using the GPS loaded from the LOG file
|
||||
:return:
|
||||
"""
|
||||
tagged_gps = []
|
||||
img_size = len(self.img_list)
|
||||
print '[INFO] Number of images:', img_size
|
||||
print '[INFO] Number of gps logs:', len(self.gps_list)
|
||||
|
||||
dt_list = [x.timestamp for x in self.gps_list]
|
||||
|
||||
img_seq = 1
|
||||
|
||||
for i in xrange(img_size):
|
||||
cdate = self.get_image_creation_date(self.img_list[i])
|
||||
gps_i, img_tdiff = self.get_closest_datetime_index(dt_list, cdate)
|
||||
base_path, filename = os.path.split(self.img_list[i])
|
||||
|
||||
if gps_i == -1:
|
||||
self.non_processed_files.append(filename)
|
||||
continue
|
||||
|
||||
closest_gps = self.gps_list[gps_i]
|
||||
self.tdiff_list.append(img_tdiff)
|
||||
|
||||
if self.verbose:
|
||||
msg = "[DEBUG] %s/%s) %s\n\timg %s -> gps %s (%ss)\n\tlat:%s, lon:%s, alt:%s".ljust(60) %\
|
||||
(i + 1, img_size, filename, cdate, closest_gps.timestamp,
|
||||
img_tdiff, closest_gps.lat, closest_gps.lon, closest_gps.alt)
|
||||
print msg
|
||||
|
||||
output_filename = self.output + str(img_seq) + '_' + filename
|
||||
copyfile(self.img_list[i], output_filename)
|
||||
self.set_gps_location(
|
||||
output_filename, closest_gps.lat, closest_gps.lon, closest_gps.alt)
|
||||
self.tagged_gps.append(closest_gps)
|
||||
img_seq += 1
|
||||
|
||||
if len(self.tdiff_list) > 0:
|
||||
print '[INFO] Mean diff in seconds:', sum(self.tdiff_list) / float(len(self.tdiff_list))
|
||||
|
||||
@staticmethod
|
||||
def get_arg():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Geotag script to add GPS info to pictures from PX4 binary log files.'
|
||||
'It uses synchronized time to allocate GPS positions.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-l', '--logfile', help='PX4 log file containing recorded positions.', required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'-i', '--input', help='Input folder containing untagged images.', required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'-o', '--output', help='Output folder to contain tagged images.', required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'-t', '--threshold', help='Time threshold between the GPS time and the local image time.',
|
||||
default=1, required=False, type=float
|
||||
)
|
||||
parser.add_argument(
|
||||
'-of', '--offset', help='Time offset in MILLISECONDS between the GPS time and the local time.',
|
||||
default=0, required=False, type=float
|
||||
)
|
||||
parser.add_argument(
|
||||
'-kml', '--kml', help='Save the in KML format the information of all tagged images.',
|
||||
required=False, action='store_true'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-v', '--verbose', help='Prints lots of information.',
|
||||
required=False, action='store_true'
|
||||
)
|
||||
|
||||
args = vars(parser.parse_args())
|
||||
return args
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
m = Main()
|
||||
@@ -1,237 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# __geotagging__
|
||||
# Tag the images recorded during a flight with geo location extracted from
|
||||
# a PX4 log file.
|
||||
#
|
||||
# This file accepts *.jpg format images and reads position information
|
||||
# from a *.px4log file
|
||||
#
|
||||
# Example Syntax:
|
||||
# python geotagging.py --logfile=log001.px4log --input=images/
|
||||
# --output=imagesWithTag/
|
||||
#
|
||||
# Author: Andreas Bircher, Wingtra, http://wingtra.com, in 2016
|
||||
#
|
||||
|
||||
import glob
|
||||
import os
|
||||
import pyexiv2
|
||||
from shutil import copyfile
|
||||
from optparse import OptionParser
|
||||
import csv
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
class TriggerList(object):
|
||||
|
||||
def __init__(self):
|
||||
self.CAMT_seq = []
|
||||
self.CAMT_timestamp = []
|
||||
self.GPOS_Lat = []
|
||||
self.GPOS_Lon = []
|
||||
self.GPOS_Alt = []
|
||||
self.GPS_GPSTime = []
|
||||
|
||||
|
||||
class ImageList(object):
|
||||
|
||||
def __init__(self):
|
||||
self.jpg = []
|
||||
self.raw = []
|
||||
|
||||
|
||||
def to_degree(value, loc):
|
||||
if value < 0:
|
||||
loc_value = loc[0]
|
||||
elif value > 0:
|
||||
loc_value = loc[1]
|
||||
else:
|
||||
loc_value = ""
|
||||
absolute_value = abs(value)
|
||||
deg = int(absolute_value)
|
||||
t1 = (absolute_value - deg) * 60
|
||||
min = int(t1)
|
||||
sec = round((t1 - min) * 60, 5)
|
||||
return (deg, min, sec, loc_value)
|
||||
|
||||
|
||||
def SetGpsLocation(file_name, gps_datetime, lat, lng, alt):
|
||||
"""
|
||||
Adding GPS tag
|
||||
|
||||
"""
|
||||
lat_deg = to_degree(lat, ["S", "N"])
|
||||
lng_deg = to_degree(lng, ["W", "E"])
|
||||
|
||||
exiv_lat = (pyexiv2.Rational(lat_deg[0] * 60 + lat_deg[1], 60), pyexiv2.Rational(
|
||||
lat_deg[2] * 100, 6000), pyexiv2.Rational(0, 1))
|
||||
exiv_lng = (pyexiv2.Rational(lng_deg[0] * 60 + lng_deg[1], 60), pyexiv2.Rational(
|
||||
lng_deg[2] * 100, 6000), pyexiv2.Rational(0, 1))
|
||||
|
||||
exiv_image = pyexiv2.ImageMetadata(file_name)
|
||||
exiv_image.read()
|
||||
|
||||
date_tag = exiv_image['Exif.Image.DateTime']
|
||||
|
||||
date_max = max(date_tag.value, gps_datetime)
|
||||
date_min = min(date_tag.value, gps_datetime)
|
||||
time_diff = date_max - date_min
|
||||
if (time_diff > timedelta(seconds=5)):
|
||||
print(
|
||||
"WARNING, camera trigger and photo time different by {}".format(time_diff))
|
||||
print(" Photo tag time: {}".format(date_tag.value))
|
||||
print(" Camera trigger time: {}".format(gps_datetime))
|
||||
|
||||
exiv_image["Exif.GPSInfo.GPSLatitude"] = exiv_lat
|
||||
exiv_image["Exif.GPSInfo.GPSLatitudeRef"] = lat_deg[3]
|
||||
exiv_image["Exif.GPSInfo.GPSLongitude"] = exiv_lng
|
||||
exiv_image["Exif.GPSInfo.GPSLongitudeRef"] = lng_deg[3]
|
||||
exiv_image["Exif.GPSInfo.GPSAltitude"] = pyexiv2.Rational(alt, 1)
|
||||
exiv_image["Exif.GPSInfo.GPSAltitudeRef"] = '0'
|
||||
exiv_image["Exif.Image.GPSTag"] = 654
|
||||
exiv_image["Exif.GPSInfo.GPSMapDatum"] = "WGS-84"
|
||||
exiv_image["Exif.GPSInfo.GPSVersionID"] = '2 0 0 0'
|
||||
|
||||
exiv_image.write(True)
|
||||
|
||||
|
||||
def LoadPX4log(px4_log_file):
|
||||
"""
|
||||
load px4 log file and extract trigger locations
|
||||
"""
|
||||
os.system('python sdlog2_dump.py ' + px4_log_file +
|
||||
' -t time -m TIME -m CAMT -m GPOS -m GPS -f log.csv')
|
||||
f = open('log.csv', 'rb')
|
||||
reader = csv.reader(f)
|
||||
headers = reader.next()
|
||||
line = {}
|
||||
for h in headers:
|
||||
line[h] = []
|
||||
|
||||
for row in reader:
|
||||
for h, v in zip(headers, row):
|
||||
line[h].append(v)
|
||||
|
||||
trigger_list = TriggerList()
|
||||
for seq in range(0, len(line['CAMT_seq']) - 1):
|
||||
if line['CAMT_seq'][seq] != line['CAMT_seq'][seq + 1]:
|
||||
trigger_list.CAMT_seq.append(line['CAMT_seq'][seq + 1])
|
||||
trigger_list.CAMT_timestamp.append(line['CAMT_timestamp'][seq + 1])
|
||||
trigger_list.GPOS_Lat.append(line['GPOS_Lat'][seq + 1])
|
||||
trigger_list.GPOS_Lon.append(line['GPOS_Lon'][seq + 1])
|
||||
trigger_list.GPOS_Alt.append(line['GPOS_Alt'][seq + 1])
|
||||
trigger_list.GPS_GPSTime.append(line['GPS_GPSTime'][seq + 1])
|
||||
|
||||
return trigger_list
|
||||
|
||||
|
||||
def LoadImageList(input_folder):
|
||||
"""
|
||||
load the image list
|
||||
"""
|
||||
image_list = ImageList()
|
||||
for jpg_image in glob.glob(input_folder + "/*.jpg"):
|
||||
image_list.jpg.append(jpg_image)
|
||||
for jpg_image in glob.glob(input_folder + "/*.JPG"):
|
||||
image_list.jpg.append(jpg_image)
|
||||
for raw_image in glob.glob(input_folder + "/*.RC"):
|
||||
image_list.raw.append(raw_image)
|
||||
if len(image_list.jpg) != len(image_list.raw) and len(image_list.jpg) * len(image_list.raw) != 0:
|
||||
print("Unequal number of jpg and raw images")
|
||||
if len(image_list.jpg) == 0 and len(image_list.raw) == 0:
|
||||
print("No images found")
|
||||
image_list.jpg = sorted(image_list.jpg)
|
||||
image_list.raw = sorted(image_list.raw)
|
||||
return image_list
|
||||
|
||||
|
||||
def FilterTrigger(trigger_list, image_list):
|
||||
"""
|
||||
filter triggers to allow exact matching with recorded images
|
||||
"""
|
||||
# filter trigger list to match the number of pics
|
||||
if len(image_list.jpg) != len(trigger_list.CAMT_seq):
|
||||
print('WARNING! differ number of jpg images ({}) and camera triggers ({})'.format(
|
||||
len(image_list.jpg), len(trigger_list.CAMT_seq)))
|
||||
|
||||
n_overlap = min(len(image_list.jpg), len(trigger_list.CAMT_seq))
|
||||
del image_list.jpg[n_overlap:]
|
||||
|
||||
if len(image_list.raw) != len(trigger_list.CAMT_seq):
|
||||
print('WARNING! differ number of raw images ({}) and camera triggers ({})'.format(
|
||||
len(image_list.raw), len(trigger_list.CAMT_seq)))
|
||||
|
||||
n_overlap = min(len(image_list.raw), len(trigger_list.CAMT_seq))
|
||||
del image_list.raw[n_overlap:]
|
||||
|
||||
return trigger_list
|
||||
|
||||
|
||||
def TagImages(trigger_list, image_list, output_folder):
|
||||
"""
|
||||
load px4 log file and extract trigger locations
|
||||
"""
|
||||
for image in range(len(image_list.jpg)):
|
||||
|
||||
print("############################################################")
|
||||
print('Photo {}: {}'.format(image, image_list.jpg[image]))
|
||||
|
||||
cam_time = int(trigger_list.GPS_GPSTime[image]) / 1000000
|
||||
gps_datetime = datetime.fromtimestamp(cam_time)
|
||||
|
||||
base_path, filename = os.path.split(image_list.jpg[image])
|
||||
copyfile(image_list.jpg[image], output_folder + "/" + filename)
|
||||
SetGpsLocation(output_folder + "/" + filename, gps_datetime, float(
|
||||
trigger_list.GPOS_Lat[image]), float(trigger_list.GPOS_Lon[image]), float(trigger_list.GPOS_Alt[image]))
|
||||
|
||||
for image in range(len(image_list.raw)):
|
||||
|
||||
print("############################################################")
|
||||
print('Photo {}: {}'.format(image, image_list.raw[image]))
|
||||
|
||||
cam_time = int(trigger_list.GPS_GPSTime[image]) / 1000000
|
||||
gps_datetime = datetime.fromtimestamp(cam_time)
|
||||
|
||||
base_path, filename = os.path.split(image_list.raw[image])
|
||||
copyfile(image_list.raw[image], output_folder + "/" + filename)
|
||||
SetGpsLocation(output_folder + "/" + filename, gps_datetime, float(
|
||||
trigger_list.GPOS_Lat[image]), float(trigger_list.GPOS_Lon[image]), float(trigger_list.GPOS_Alt[image]))
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main method
|
||||
"""
|
||||
parser = OptionParser()
|
||||
parser.add_option("-l", "--logfile", dest="LogFile",
|
||||
help="PX4 log file containing recorded positions",
|
||||
metavar="string")
|
||||
parser.add_option("-i", "--input", dest="InputFolder",
|
||||
help="Input folder containing untagged images in alphabetical order",
|
||||
type="string")
|
||||
parser.add_option("-o", "--output", dest="OutputFolder",
|
||||
help="Output folder to contain tagged images",
|
||||
type="string")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if not options.LogFile:
|
||||
print "please type python " \
|
||||
"geotagging.py --logfile=[filename] --intput=[folder] [--output=[folder]]"
|
||||
elif not options.InputFolder:
|
||||
print "please type python " \
|
||||
"geotagging.py --logfile=[filename] --intput=[folder] [--output=[folder]]s"
|
||||
else:
|
||||
trigger_list = LoadPX4log(options.LogFile)
|
||||
image_list = LoadImageList(options.InputFolder)
|
||||
|
||||
if not options.OutputFolder:
|
||||
options.OutputFolder = "imagesWithTag"
|
||||
if not os.path.exists(options.OutputFolder):
|
||||
os.makedirs(options.OutputFolder)
|
||||
|
||||
trigger_list = FilterTrigger(trigger_list, image_list)
|
||||
|
||||
TagImages(trigger_list, image_list, options.OutputFolder)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,343 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
"""Dump binary log generated by PX4's sdlog2 or APM as CSV
|
||||
|
||||
Usage: python sdlog2_dump.py <log.bin> [-v] [-e] [-d delimiter] [-n null] [-m MSG[_field1,field2,...]]
|
||||
|
||||
Example Usage: python sdlog2_dump.py log.bin -m GPS_Lat,Lng -m AHR2_Roll,Pitch,Yaw
|
||||
|
||||
-v Use plain debug output instead of CSV.
|
||||
|
||||
-e Recover from errors.
|
||||
|
||||
-d Use "delimiter" in CSV. Default is ",".
|
||||
|
||||
-n Use "null" as placeholder for empty values in CSV. Default is empty.
|
||||
|
||||
-m MSG[_field1,field2,...]
|
||||
Dump only messages of specified type, and only specified fields.
|
||||
Multiple -m options allowed.
|
||||
"""
|
||||
|
||||
__author__ = "Anton Babushkin"
|
||||
__version__ = "1.2"
|
||||
|
||||
import struct, sys
|
||||
|
||||
if sys.hexversion >= 0x030000F0:
|
||||
runningPython3 = True
|
||||
def _parseCString(cstr):
|
||||
return str(cstr, 'ascii').split('\0')[0]
|
||||
else:
|
||||
runningPython3 = False
|
||||
def _parseCString(cstr):
|
||||
return str(cstr).split('\0')[0]
|
||||
|
||||
class SDLog2Parser:
|
||||
BLOCK_SIZE = 8192
|
||||
MSG_HEADER_LEN = 3
|
||||
MSG_HEAD1 = 0xA3
|
||||
MSG_HEAD2 = 0x95
|
||||
MSG_FORMAT_PACKET_LEN = 89
|
||||
MSG_FORMAT_STRUCT = "BB4s16s64s"
|
||||
MSG_TYPE_FORMAT = 0x80
|
||||
FORMAT_TO_STRUCT = {
|
||||
"b": ("b", None),
|
||||
"B": ("B", None),
|
||||
"h": ("h", None),
|
||||
"H": ("H", None),
|
||||
"i": ("i", None),
|
||||
"I": ("I", None),
|
||||
"f": ("f", None),
|
||||
"d": ("d", None),
|
||||
"n": ("4s", None),
|
||||
"N": ("16s", None),
|
||||
"Z": ("64s", None),
|
||||
"c": ("h", 0.01),
|
||||
"C": ("H", 0.01),
|
||||
"e": ("i", 0.01),
|
||||
"E": ("I", 0.01),
|
||||
"L": ("i", 0.0000001),
|
||||
"M": ("b", None),
|
||||
"q": ("q", None),
|
||||
"Q": ("Q", None),
|
||||
}
|
||||
__csv_delim = ","
|
||||
__csv_null = ""
|
||||
__msg_filter = []
|
||||
__time_msg = None
|
||||
__debug_out = False
|
||||
__correct_errors = False
|
||||
__file_name = None
|
||||
__file = None
|
||||
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def reset(self):
|
||||
self.__msg_descrs = {} # message descriptions by message type map
|
||||
self.__msg_labels = {} # message labels by message name map
|
||||
self.__msg_names = [] # message names in the same order as FORMAT messages
|
||||
self.__buffer = bytearray() # buffer for input binary data
|
||||
self.__ptr = 0 # read pointer in buffer
|
||||
self.__csv_columns = [] # CSV file columns in correct order in format "MSG.label"
|
||||
self.__csv_data = {} # current values for all columns
|
||||
self.__csv_updated = False
|
||||
self.__msg_filter_map = {} # filter in form of map, with '*" expanded to full list of fields
|
||||
|
||||
def setCSVDelimiter(self, csv_delim):
|
||||
self.__csv_delim = csv_delim
|
||||
|
||||
def setCSVNull(self, csv_null):
|
||||
self.__csv_null = csv_null
|
||||
|
||||
def setMsgFilter(self, msg_filter):
|
||||
self.__msg_filter = msg_filter
|
||||
|
||||
def setTimeMsg(self, time_msg):
|
||||
self.__time_msg = time_msg
|
||||
|
||||
def setDebugOut(self, debug_out):
|
||||
self.__debug_out = debug_out
|
||||
|
||||
def setCorrectErrors(self, correct_errors):
|
||||
self.__correct_errors = correct_errors
|
||||
|
||||
def setFileName(self, file_name):
|
||||
self.__file_name = file_name
|
||||
if file_name != None:
|
||||
self.__file = open(file_name, 'w+')
|
||||
else:
|
||||
self.__file = None
|
||||
|
||||
|
||||
def process(self, fn):
|
||||
self.reset()
|
||||
if self.__debug_out:
|
||||
# init __msg_filter_map
|
||||
for msg_name, show_fields in self.__msg_filter:
|
||||
self.__msg_filter_map[msg_name] = show_fields
|
||||
first_data_msg = True
|
||||
f = open(fn, "rb")
|
||||
bytes_read = 0
|
||||
while True:
|
||||
chunk = f.read(self.BLOCK_SIZE)
|
||||
if len(chunk) == 0:
|
||||
break
|
||||
self.__buffer = self.__buffer[self.__ptr:] + chunk
|
||||
self.__ptr = 0
|
||||
while self.__bytesLeft() >= self.MSG_HEADER_LEN:
|
||||
head1 = self.__buffer[self.__ptr]
|
||||
head2 = self.__buffer[self.__ptr+1]
|
||||
if (head1 != self.MSG_HEAD1 or head2 != self.MSG_HEAD2):
|
||||
if self.__correct_errors:
|
||||
self.__ptr += 1
|
||||
continue
|
||||
else:
|
||||
raise Exception("Invalid header at %i (0x%X): %02X %02X, must be %02X %02X" % (bytes_read + self.__ptr, bytes_read + self.__ptr, head1, head2, self.MSG_HEAD1, self.MSG_HEAD2))
|
||||
msg_type = self.__buffer[self.__ptr+2]
|
||||
if msg_type == self.MSG_TYPE_FORMAT:
|
||||
# parse FORMAT message
|
||||
if self.__bytesLeft() < self.MSG_FORMAT_PACKET_LEN:
|
||||
break
|
||||
self.__parseMsgDescr()
|
||||
else:
|
||||
# parse data message
|
||||
msg_descr = self.__msg_descrs.get(msg_type, None)
|
||||
if msg_descr == None:
|
||||
if self.__correct_errors:
|
||||
self.__ptr += 1
|
||||
continue
|
||||
else:
|
||||
raise Exception("Unknown msg type: %i" % msg_type)
|
||||
msg_length = msg_descr[0]
|
||||
if self.__bytesLeft() < msg_length:
|
||||
break
|
||||
if first_data_msg:
|
||||
# build CSV columns and init data map
|
||||
if not self.__debug_out:
|
||||
self.__initCSV()
|
||||
first_data_msg = False
|
||||
self.__parseMsg(msg_descr)
|
||||
bytes_read += self.__ptr
|
||||
if not self.__debug_out and self.__time_msg != None and self.__csv_updated:
|
||||
self.__printCSVRow()
|
||||
f.close()
|
||||
|
||||
def __bytesLeft(self):
|
||||
return len(self.__buffer) - self.__ptr
|
||||
|
||||
def __filterMsg(self, msg_name):
|
||||
show_fields = "*"
|
||||
if len(self.__msg_filter_map) > 0:
|
||||
show_fields = self.__msg_filter_map.get(msg_name)
|
||||
return show_fields
|
||||
|
||||
def __initCSV(self):
|
||||
if len(self.__msg_filter) == 0:
|
||||
for msg_name in self.__msg_names:
|
||||
self.__msg_filter.append((msg_name, "*"))
|
||||
for msg_name, show_fields in self.__msg_filter:
|
||||
if show_fields == "*":
|
||||
show_fields = self.__msg_labels.get(msg_name, [])
|
||||
self.__msg_filter_map[msg_name] = show_fields
|
||||
for field in show_fields:
|
||||
full_label = msg_name + "_" + field
|
||||
self.__csv_columns.append(full_label)
|
||||
self.__csv_data[full_label] = None
|
||||
if self.__file != None:
|
||||
print(self.__csv_delim.join(self.__csv_columns), file=self.__file)
|
||||
else:
|
||||
print(self.__csv_delim.join(self.__csv_columns))
|
||||
|
||||
def __printCSVRow(self):
|
||||
s = []
|
||||
for full_label in self.__csv_columns:
|
||||
v = self.__csv_data[full_label]
|
||||
if v == None:
|
||||
v = self.__csv_null
|
||||
else:
|
||||
v = str(v)
|
||||
s.append(v)
|
||||
|
||||
if self.__file != None:
|
||||
print(self.__csv_delim.join(s), file=self.__file)
|
||||
else:
|
||||
print(self.__csv_delim.join(s))
|
||||
|
||||
def __parseMsgDescr(self):
|
||||
if runningPython3:
|
||||
data = struct.unpack(self.MSG_FORMAT_STRUCT, self.__buffer[self.__ptr + 3 : self.__ptr + self.MSG_FORMAT_PACKET_LEN])
|
||||
else:
|
||||
data = struct.unpack(self.MSG_FORMAT_STRUCT, str(self.__buffer[self.__ptr + 3 : self.__ptr + self.MSG_FORMAT_PACKET_LEN]))
|
||||
msg_type = data[0]
|
||||
if msg_type != self.MSG_TYPE_FORMAT:
|
||||
msg_length = data[1]
|
||||
msg_name = _parseCString(data[2])
|
||||
msg_format = _parseCString(data[3])
|
||||
msg_labels = _parseCString(data[4]).split(",")
|
||||
# Convert msg_format to struct.unpack format string
|
||||
msg_struct = ""
|
||||
msg_mults = []
|
||||
for c in msg_format:
|
||||
try:
|
||||
f = self.FORMAT_TO_STRUCT[c]
|
||||
msg_struct += f[0]
|
||||
msg_mults.append(f[1])
|
||||
except KeyError as e:
|
||||
raise Exception("Unsupported format char: %s in message %s (%i)" % (c, msg_name, msg_type))
|
||||
msg_struct = "<" + msg_struct # force little-endian
|
||||
self.__msg_descrs[msg_type] = (msg_length, msg_name, msg_format, msg_labels, msg_struct, msg_mults)
|
||||
self.__msg_labels[msg_name] = msg_labels
|
||||
self.__msg_names.append(msg_name)
|
||||
if self.__debug_out:
|
||||
if self.__filterMsg(msg_name) != None:
|
||||
print("MSG FORMAT: type = %i, length = %i, name = %s, format = %s, labels = %s, struct = %s, mults = %s" % (
|
||||
msg_type, msg_length, msg_name, msg_format, str(msg_labels), msg_struct, msg_mults))
|
||||
self.__ptr += self.MSG_FORMAT_PACKET_LEN
|
||||
|
||||
def __parseMsg(self, msg_descr):
|
||||
msg_length, msg_name, msg_format, msg_labels, msg_struct, msg_mults = msg_descr
|
||||
if not self.__debug_out and self.__time_msg != None and msg_name == self.__time_msg and self.__csv_updated:
|
||||
self.__printCSVRow()
|
||||
self.__csv_updated = False
|
||||
show_fields = self.__filterMsg(msg_name)
|
||||
if (show_fields != None):
|
||||
if runningPython3:
|
||||
data = list(struct.unpack(msg_struct, self.__buffer[self.__ptr+self.MSG_HEADER_LEN:self.__ptr+msg_length]))
|
||||
else:
|
||||
data = list(struct.unpack(msg_struct, str(self.__buffer[self.__ptr+self.MSG_HEADER_LEN:self.__ptr+msg_length])))
|
||||
for i in range(len(data)):
|
||||
if type(data[i]) is str:
|
||||
data[i] = _parseCString(data[i])
|
||||
m = msg_mults[i]
|
||||
if m != None:
|
||||
data[i] = data[i] * m
|
||||
if self.__debug_out:
|
||||
s = []
|
||||
for i in range(len(data)):
|
||||
label = msg_labels[i]
|
||||
if show_fields == "*" or label in show_fields:
|
||||
s.append(label + "=" + str(data[i]))
|
||||
print("MSG %s: %s" % (msg_name, ", ".join(s)))
|
||||
else:
|
||||
# update CSV data buffer
|
||||
for i in range(len(data)):
|
||||
label = msg_labels[i]
|
||||
if label in show_fields:
|
||||
self.__csv_data[msg_name + "_" + label] = data[i]
|
||||
if self.__time_msg != None and msg_name != self.__time_msg:
|
||||
self.__csv_updated = True
|
||||
if self.__time_msg == None:
|
||||
self.__printCSVRow()
|
||||
self.__ptr += msg_length
|
||||
|
||||
def _main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python sdlog2_dump.py <log.bin> [-v] [-e] [-d delimiter] [-n null] [-m MSG[_field1,field2,...]] [-t TIME_MSG_NAME]\n")
|
||||
print("\t-v\tUse plain debug output instead of CSV.\n")
|
||||
print("\t-e\tRecover from errors.\n")
|
||||
print("\t-d\tUse \"delimiter\" in CSV. Default is \",\".\n")
|
||||
print("\t-n\tUse \"null\" as placeholder for empty values in CSV. Default is empty.\n")
|
||||
print("\t-m MSG[_field1,field2,...]\n\t\tDump only messages of specified type, and only specified fields.\n\t\tMultiple -m options allowed.")
|
||||
print("\t-t\tSpecify TIME message name to group data messages by time and significantly reduce duplicate output.\n")
|
||||
print("\t-fPrint to file instead of stdout")
|
||||
return
|
||||
fn = sys.argv[1]
|
||||
debug_out = False
|
||||
correct_errors = False
|
||||
msg_filter = []
|
||||
csv_null = ""
|
||||
csv_delim = ","
|
||||
time_msg = "TIME"
|
||||
file_name = None
|
||||
opt = None
|
||||
for arg in sys.argv[2:]:
|
||||
if opt != None:
|
||||
if opt == "d":
|
||||
csv_delim = arg
|
||||
elif opt == "n":
|
||||
csv_null = arg
|
||||
elif opt == "t":
|
||||
time_msg = arg
|
||||
elif opt == "f":
|
||||
file_name = arg
|
||||
elif opt == "m":
|
||||
show_fields = "*"
|
||||
a = arg.split("_")
|
||||
if len(a) > 1:
|
||||
show_fields = a[1].split(",")
|
||||
msg_filter.append((a[0], show_fields))
|
||||
opt = None
|
||||
else:
|
||||
if arg == "-v":
|
||||
debug_out = True
|
||||
elif arg == "-e":
|
||||
correct_errors = True
|
||||
elif arg == "-d":
|
||||
opt = "d"
|
||||
elif arg == "-n":
|
||||
opt = "n"
|
||||
elif arg == "-m":
|
||||
opt = "m"
|
||||
elif arg == "-t":
|
||||
opt = "t"
|
||||
elif arg == "-f":
|
||||
opt = "f"
|
||||
|
||||
if csv_delim == "\\t":
|
||||
csv_delim = "\t"
|
||||
parser = SDLog2Parser()
|
||||
parser.setCSVDelimiter(csv_delim)
|
||||
parser.setCSVNull(csv_null)
|
||||
parser.setMsgFilter(msg_filter)
|
||||
parser.setTimeMsg(time_msg)
|
||||
parser.setFileName(file_name)
|
||||
parser.setDebugOut(debug_out)
|
||||
parser.setCorrectErrors(correct_errors)
|
||||
parser.process(fn)
|
||||
|
||||
if __name__ == "__main__":
|
||||
_main()
|
||||
@@ -222,7 +222,6 @@ class Graph:
|
||||
special_cases_sub = [
|
||||
('sensors', r'voted_sensors_update\.cpp$', r'\binit_sensor_class\b\(([^,)]+)', r'^meta$'),
|
||||
('mavlink', r'.*', r'\badd_orb_subscription\b\(([^,)]+)', r'^_topic$'),
|
||||
('sdlog2', r'.*', None, r'^topic$'),
|
||||
('logger', r'.*', None, r'^(topic|sub\.metadata|_polling_topic_meta)$'),
|
||||
|
||||
('uavcan', r'uavcan_main\.cpp$', r'\b_control_topics\[[0-9]\]=([^,)]+)', r'^_control_topics\[i\]$'),
|
||||
|
||||
@@ -91,7 +91,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
#modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -111,7 +111,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -103,7 +103,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -107,7 +107,6 @@ set(config_module_list
|
||||
#
|
||||
# Logging
|
||||
#
|
||||
modules/sdlog2
|
||||
modules/logger
|
||||
|
||||
#
|
||||
|
||||
@@ -112,7 +112,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -84,7 +84,6 @@ set(config_module_list
|
||||
#
|
||||
# Logging
|
||||
#
|
||||
modules/sdlog2
|
||||
## modules/logger
|
||||
|
||||
#
|
||||
|
||||
@@ -134,7 +134,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
#modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -123,7 +123,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
#modules/logger
|
||||
#modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -121,7 +121,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -108,7 +108,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -112,7 +112,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -114,7 +114,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -91,7 +91,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -52,7 +52,6 @@ set(config_module_list
|
||||
#
|
||||
# Library modules
|
||||
#
|
||||
modules/sdlog2
|
||||
modules/logger
|
||||
modules/commander
|
||||
modules/dataman
|
||||
|
||||
@@ -29,7 +29,6 @@ set(config_module_list
|
||||
|
||||
modules/sensors
|
||||
modules/dataman
|
||||
modules/sdlog2
|
||||
modules/logger
|
||||
modules/simulator
|
||||
modules/commander
|
||||
|
||||
@@ -55,7 +55,6 @@ set(config_module_list
|
||||
#
|
||||
# Library modules
|
||||
#
|
||||
modules/sdlog2
|
||||
modules/logger
|
||||
modules/commander
|
||||
modules/dataman
|
||||
|
||||
@@ -55,7 +55,6 @@ set(config_module_list
|
||||
#
|
||||
# Library modules
|
||||
#
|
||||
modules/sdlog2
|
||||
modules/logger
|
||||
modules/commander
|
||||
modules/dataman
|
||||
|
||||
@@ -66,7 +66,6 @@ set(config_module_list
|
||||
#
|
||||
# Library modules
|
||||
#
|
||||
modules/sdlog2
|
||||
modules/logger
|
||||
modules/commander
|
||||
modules/dataman
|
||||
|
||||
@@ -58,7 +58,6 @@ set(config_module_list
|
||||
modules/muorb/krait
|
||||
modules/sensors
|
||||
modules/dataman
|
||||
modules/sdlog2
|
||||
modules/logger
|
||||
modules/simulator
|
||||
modules/commander
|
||||
|
||||
@@ -49,7 +49,6 @@ set(config_module_list
|
||||
modules/muorb/krait
|
||||
modules/sensors
|
||||
modules/dataman
|
||||
modules/sdlog2
|
||||
modules/logger
|
||||
modules/simulator
|
||||
modules/commander
|
||||
|
||||
@@ -95,7 +95,6 @@ set(config_module_list
|
||||
# Logging
|
||||
#
|
||||
modules/logger
|
||||
modules/sdlog2
|
||||
|
||||
#
|
||||
# Library modules
|
||||
|
||||
@@ -8,7 +8,6 @@ set(config_module_list
|
||||
systemcmds/perf
|
||||
modules/ekf2
|
||||
modules/ekf2_replay
|
||||
modules/sdlog2
|
||||
modules/logger
|
||||
)
|
||||
|
||||
|
||||
@@ -78,6 +78,6 @@ mavlink stream -r 50 -s SERVO_OUTPUT_RAW_0 -u 14556
|
||||
mavlink stream -r 20 -s RC_CHANNELS -u 14556
|
||||
mavlink stream -r 250 -s HIGHRES_IMU -u 14556
|
||||
mavlink stream -r 10 -s OPTICAL_FLOW_RAD -u 14556
|
||||
sdlog2 start -r 200 -e -t -a
|
||||
logger start -e -t
|
||||
mavlink boot_complete
|
||||
replay trystart
|
||||
|
||||
@@ -68,7 +68,7 @@ accelsim start
|
||||
barosim start
|
||||
gpssim start
|
||||
measairspeedsim start
|
||||
pwm_out_sim start start
|
||||
pwm_out_sim start
|
||||
sensors start
|
||||
commander start
|
||||
land_detector start vtol
|
||||
|
||||
@@ -74,6 +74,6 @@ mavlink stream -r 50 -s SERVO_OUTPUT_RAW_0 -u 14556
|
||||
mavlink stream -r 20 -s RC_CHANNELS -u 14556
|
||||
mavlink stream -r 250 -s HIGHRES_IMU -u 14556
|
||||
mavlink stream -r 10 -s OPTICAL_FLOW_RAD -u 14556
|
||||
sdlog2 start -r 200 -e -t -a
|
||||
logger start -e -t
|
||||
mavlink boot_complete
|
||||
replay trystart
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2015 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
px4_add_module(
|
||||
MODULE modules__sdlog2
|
||||
MAIN sdlog2
|
||||
PRIORITY "SCHED_PRIORITY_MAX-30"
|
||||
STACK_MAIN 1200
|
||||
STACK_MAX 1600
|
||||
COMPILE_FLAGS
|
||||
-Wno-sign-compare # TODO: fix all sign-compare
|
||||
SRCS
|
||||
sdlog2.c
|
||||
logbuffer.c
|
||||
DEPENDS
|
||||
)
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file logbuffer.c
|
||||
*
|
||||
* Ring FIFO buffer for binary log data.
|
||||
*
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#include <px4_defines.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "logbuffer.h"
|
||||
|
||||
int logbuffer_init(struct logbuffer_s *lb, int size)
|
||||
{
|
||||
lb->size = size;
|
||||
lb->write_ptr = 0;
|
||||
lb->read_ptr = 0;
|
||||
lb->data = NULL;
|
||||
lb->perf_dropped = perf_alloc(PC_COUNT, "sd drop");
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
int logbuffer_count(struct logbuffer_s *lb)
|
||||
{
|
||||
int n = lb->write_ptr - lb->read_ptr;
|
||||
|
||||
if (n < 0) {
|
||||
n += lb->size;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int logbuffer_is_empty(struct logbuffer_s *lb)
|
||||
{
|
||||
return lb->read_ptr == lb->write_ptr;
|
||||
}
|
||||
|
||||
bool logbuffer_write(struct logbuffer_s *lb, void *ptr, int size)
|
||||
{
|
||||
// allocate buffer if not yet present
|
||||
if (lb->data == NULL) {
|
||||
lb->data = malloc(lb->size);
|
||||
}
|
||||
|
||||
// allocation failed, bail out
|
||||
if (lb->data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// bytes available to write
|
||||
int available = lb->read_ptr - lb->write_ptr - 1;
|
||||
|
||||
if (available < 0) {
|
||||
available += lb->size;
|
||||
}
|
||||
|
||||
if (size > available) {
|
||||
// buffer overflow
|
||||
perf_count(lb->perf_dropped);
|
||||
return false;
|
||||
}
|
||||
|
||||
char *c = (char *) ptr;
|
||||
int n = lb->size - lb->write_ptr; // bytes to end of the buffer
|
||||
|
||||
if (n < size) {
|
||||
// message goes over end of the buffer
|
||||
memcpy(&(lb->data[lb->write_ptr]), c, n);
|
||||
lb->write_ptr = 0;
|
||||
|
||||
} else {
|
||||
n = 0;
|
||||
}
|
||||
|
||||
// now: n = bytes already written
|
||||
int p = size - n; // number of bytes to write
|
||||
memcpy(&(lb->data[lb->write_ptr]), &(c[n]), p);
|
||||
lb->write_ptr = (lb->write_ptr + p) % lb->size;
|
||||
return true;
|
||||
}
|
||||
|
||||
int logbuffer_get_ptr(struct logbuffer_s *lb, void **ptr, bool *is_part)
|
||||
{
|
||||
// bytes available to read
|
||||
int available = lb->write_ptr - lb->read_ptr;
|
||||
|
||||
if (available == 0) {
|
||||
return 0; // buffer is empty
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
|
||||
if (available > 0) {
|
||||
// read pointer is before write pointer, all available bytes can be read
|
||||
n = available;
|
||||
*is_part = false;
|
||||
|
||||
} else {
|
||||
// read pointer is after write pointer, read bytes from read_ptr to end of the buffer
|
||||
n = lb->size - lb->read_ptr;
|
||||
*is_part = lb->write_ptr > 0;
|
||||
}
|
||||
|
||||
*ptr = &(lb->data[lb->read_ptr]);
|
||||
return n;
|
||||
}
|
||||
|
||||
void logbuffer_mark_read(struct logbuffer_s *lb, int n)
|
||||
{
|
||||
lb->read_ptr = (lb->read_ptr + n) % lb->size;
|
||||
}
|
||||
|
||||
void logbuffer_free(struct logbuffer_s *lb)
|
||||
{
|
||||
if (lb->data) {
|
||||
free(lb->data);
|
||||
lb->write_ptr = 0;
|
||||
lb->read_ptr = 0;
|
||||
lb->data = NULL;
|
||||
perf_free(lb->perf_dropped);
|
||||
}
|
||||
}
|
||||
|
||||
void logbuffer_reset(struct logbuffer_s *lb)
|
||||
{
|
||||
// Keep the buffer but reset the pointers.
|
||||
lb->write_ptr = 0;
|
||||
lb->read_ptr = 0;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Anton Babushkin <anton.babushkin@me.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file logbuffer.h
|
||||
*
|
||||
* Ring FIFO buffer for binary log data.
|
||||
*
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#ifndef SDLOG2_RINGBUFFER_H_
|
||||
#define SDLOG2_RINGBUFFER_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <perf/perf_counter.h>
|
||||
|
||||
struct logbuffer_s {
|
||||
// pointers and size are in bytes
|
||||
int write_ptr;
|
||||
int read_ptr;
|
||||
int size;
|
||||
char *data;
|
||||
perf_counter_t perf_dropped;
|
||||
};
|
||||
|
||||
int logbuffer_init(struct logbuffer_s *lb, int size);
|
||||
|
||||
int logbuffer_count(struct logbuffer_s *lb);
|
||||
|
||||
int logbuffer_is_empty(struct logbuffer_s *lb);
|
||||
|
||||
bool logbuffer_write(struct logbuffer_s *lb, void *ptr, int size);
|
||||
|
||||
int logbuffer_get_ptr(struct logbuffer_s *lb, void **ptr, bool *is_part);
|
||||
|
||||
void logbuffer_mark_read(struct logbuffer_s *lb, int n);
|
||||
|
||||
void logbuffer_free(struct logbuffer_s *lb);
|
||||
|
||||
void logbuffer_reset(struct logbuffer_s *lb);
|
||||
|
||||
#endif
|
||||
@@ -1,95 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012-2016 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Logging rate.
|
||||
*
|
||||
* A value of -1 indicates the commandline argument
|
||||
* should be obeyed. A value of 0 sets the minimum rate,
|
||||
* any other value is interpreted as rate in Hertz. This
|
||||
* parameter is only read out before logging starts (which
|
||||
* commonly is before arming).
|
||||
*
|
||||
* @unit Hz
|
||||
* @min -1
|
||||
* @max 250
|
||||
* @group SD Logging
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SDLOG_RATE, -1);
|
||||
|
||||
/**
|
||||
* Extended logging mode
|
||||
*
|
||||
* A value of -1 indicates the command line argument
|
||||
* should be obeyed. A value of 0 disables extended
|
||||
* logging mode, a value of 1 enables it. This
|
||||
* parameter is only read out before logging starts
|
||||
* (which commonly is before arming).
|
||||
*
|
||||
* @min -1
|
||||
* @max 1
|
||||
* @value -1 Command Line
|
||||
* @value 0 Disable
|
||||
* @value 1 Enable
|
||||
* @group SD Logging
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SDLOG_EXT, -1);
|
||||
|
||||
/**
|
||||
* Use timestamps only if GPS 3D fix is available
|
||||
*
|
||||
* Constrain the log folder creation
|
||||
* to only use the time stamp if a 3D GPS lock is
|
||||
* present.
|
||||
*
|
||||
* @boolean
|
||||
* @group SD Logging
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SDLOG_GPSTIME, 1);
|
||||
|
||||
/**
|
||||
* Give logging app higher thread priority to avoid data loss.
|
||||
* This is used for gathering replay logs for the ekf2 module.
|
||||
*
|
||||
* A value of 0 indicates that the default priority is used.
|
||||
* Increasing the parameter in steps of one increases the priority.
|
||||
*
|
||||
* @min 0
|
||||
* @max 3
|
||||
* @value 0 Low priority
|
||||
* @value 1 Default priority
|
||||
* @value 2 Medium priority
|
||||
* @value 3 Max priority
|
||||
* @group SD Logging
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SDLOG_PRIO_BOOST, 2);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,106 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2013 PX4 Development Team. All rights reserved.
|
||||
* Author: Anton Babushkin <anton.babushkin@me.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file sdlog2_format.h
|
||||
*
|
||||
* General log format structures and macro.
|
||||
*
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
Format characters in the format string for binary log messages
|
||||
b : int8_t
|
||||
B : uint8_t
|
||||
h : int16_t
|
||||
H : uint16_t
|
||||
i : int32_t
|
||||
I : uint32_t
|
||||
f : float
|
||||
n : char[4]
|
||||
N : char[16]
|
||||
Z : char[64]
|
||||
c : int16_t * 100
|
||||
C : uint16_t * 100
|
||||
e : int32_t * 100
|
||||
E : uint32_t * 100
|
||||
L : int32_t latitude/longitude
|
||||
M : uint8_t flight mode
|
||||
|
||||
q : int64_t
|
||||
Q : uint64_t
|
||||
*/
|
||||
|
||||
#ifndef SDLOG2_FORMAT_H_
|
||||
#define SDLOG2_FORMAT_H_
|
||||
|
||||
#define LOG_PACKET_HEADER_LEN 3
|
||||
#define LOG_PACKET_HEADER uint8_t head1, head2, msg_type
|
||||
#define LOG_PACKET_HEADER_INIT(id) .head1 = HEAD_BYTE1, .head2 = HEAD_BYTE2, .msg_type = id
|
||||
|
||||
// once the logging code is all converted we will remove these from
|
||||
// this header
|
||||
#define HEAD_BYTE1 0xA3 // Decimal 163
|
||||
#define HEAD_BYTE2 0x95 // Decimal 149
|
||||
|
||||
struct log_format_s {
|
||||
uint8_t type;
|
||||
uint8_t length; // full packet length including header
|
||||
char name[4];
|
||||
char format[16];
|
||||
char labels[64];
|
||||
};
|
||||
|
||||
#define LOG_FORMAT(_name, _format, _labels) { \
|
||||
.type = LOG_##_name##_MSG, \
|
||||
.length = sizeof(struct log_##_name##_s) + LOG_PACKET_HEADER_LEN, \
|
||||
.name = #_name, \
|
||||
.format = _format, \
|
||||
.labels = _labels \
|
||||
}
|
||||
|
||||
#define LOG_FORMAT_S(_name, _struct_name, _format, _labels) { \
|
||||
.type = LOG_##_name##_MSG, \
|
||||
.length = sizeof(struct log_##_struct_name##_s) + LOG_PACKET_HEADER_LEN, \
|
||||
.name = #_name, \
|
||||
.format = _format, \
|
||||
.labels = _labels \
|
||||
}
|
||||
|
||||
#define LOG_FORMAT_MSG 0x80
|
||||
|
||||
#define LOG_PACKET_SIZE(_name) LOG_PACKET_HEADER_LEN + sizeof(struct log_##_name##_s)
|
||||
|
||||
#endif /* SDLOG2_FORMAT_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -152,18 +152,6 @@ PARAM_DEFINE_INT32(SYS_COMPANION, 157600);
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SYS_PARAM_VER, 1);
|
||||
|
||||
/**
|
||||
* SD logger
|
||||
*
|
||||
* @value 0 sdlog2 (legacy)
|
||||
* @value 1 logger (default)
|
||||
* @min 0
|
||||
* @max 1
|
||||
* @reboot_required true
|
||||
* @group System
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SYS_LOGGER, 1);
|
||||
|
||||
/**
|
||||
* Enable stack checking
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user