mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
[wpiutil] Add high speed data logging
This commit is contained in:
@@ -7,7 +7,7 @@ package edu.wpi.first.util;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public final class WPIUtilJNI {
|
||||
public class WPIUtilJNI {
|
||||
static boolean libraryLoaded = false;
|
||||
static RuntimeLoader<WPIUtilJNI> loader = null;
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log array of boolean values. */
|
||||
public class BooleanArrayLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "boolean[]";
|
||||
|
||||
public BooleanArrayLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
super(log, name, kDataType, metadata, timestamp);
|
||||
}
|
||||
|
||||
public BooleanArrayLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public BooleanArrayLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public BooleanArrayLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(boolean[] value, long timestamp) {
|
||||
m_log.appendBooleanArray(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(boolean[] value) {
|
||||
m_log.appendBooleanArray(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log boolean values. */
|
||||
public class BooleanLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "boolean";
|
||||
|
||||
public BooleanLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
super(log, name, kDataType, metadata, timestamp);
|
||||
}
|
||||
|
||||
public BooleanLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public BooleanLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public BooleanLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(boolean value, long timestamp) {
|
||||
m_log.appendBoolean(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(boolean value) {
|
||||
m_log.appendBoolean(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
242
wpiutil/src/main/java/edu/wpi/first/util/datalog/DataLog.java
Normal file
242
wpiutil/src/main/java/edu/wpi/first/util/datalog/DataLog.java
Normal file
@@ -0,0 +1,242 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/**
|
||||
* A data log. The log file is created immediately upon construction with a temporary filename. The
|
||||
* file may be renamed at any time using the setFilename() function.
|
||||
*
|
||||
* <p>The data log is periodically flushed to disk. It can also be explicitly flushed to disk by
|
||||
* using the flush() function.
|
||||
*/
|
||||
@SuppressWarnings({"PMD.TooManyMethods", "PMD.ExcessivePublicCount"})
|
||||
public final class DataLog implements AutoCloseable {
|
||||
/**
|
||||
* Construct a new Data Log. The log will be initially created with a temporary filename.
|
||||
*
|
||||
* @param dir directory to store the log
|
||||
* @param filename filename to use; if none provided, a random filename is generated of the form
|
||||
* "wpilog_{}.wpilog"
|
||||
* @param period time between automatic flushes to disk, in seconds; this is a time/storage
|
||||
* tradeoff
|
||||
* @param extraHeader extra header data
|
||||
*/
|
||||
public DataLog(String dir, String filename, double period, String extraHeader) {
|
||||
m_impl = DataLogJNI.create(dir, filename, period, extraHeader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new Data Log. The log will be initially created with a temporary filename.
|
||||
*
|
||||
* @param dir directory to store the log
|
||||
* @param filename filename to use; if none provided, a random filename is generated of the form
|
||||
* "wpilog_{}.wpilog"
|
||||
* @param period time between automatic flushes to disk, in seconds; this is a time/storage
|
||||
* tradeoff
|
||||
*/
|
||||
public DataLog(String dir, String filename, double period) {
|
||||
this(dir, filename, period, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new Data Log. The log will be initially created with a temporary filename.
|
||||
*
|
||||
* @param dir directory to store the log
|
||||
* @param filename filename to use; if none provided, a random filename is generated of the form
|
||||
* "wpilog_{}.wpilog"
|
||||
*/
|
||||
public DataLog(String dir, String filename) {
|
||||
this(dir, filename, 0.25);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new Data Log. The log will be initially created with a temporary filename.
|
||||
*
|
||||
* @param dir directory to store the log
|
||||
*/
|
||||
public DataLog(String dir) {
|
||||
this(dir, "", 0.25);
|
||||
}
|
||||
|
||||
/** Construct a new Data Log. The log will be initially created with a temporary filename. */
|
||||
public DataLog() {
|
||||
this("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Change log filename.
|
||||
*
|
||||
* @param filename filename
|
||||
*/
|
||||
public void setFilename(String filename) {
|
||||
DataLogJNI.setFilename(m_impl, filename);
|
||||
}
|
||||
|
||||
/** Explicitly flushes the log data to disk. */
|
||||
public void flush() {
|
||||
DataLogJNI.flush(m_impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses appending of data records to the log. While paused, no data records are saved (e.g.
|
||||
* AppendX is a no-op). Has no effect on entry starts / finishes / metadata changes.
|
||||
*/
|
||||
public void pause() {
|
||||
DataLogJNI.pause(m_impl);
|
||||
}
|
||||
|
||||
/** Resumes appending of data records to the log. */
|
||||
public void resume() {
|
||||
DataLogJNI.resume(m_impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an entry. Duplicate names are allowed (with the same type), and result in the same index
|
||||
* being returned (start/finish are reference counted). A duplicate name with a different type
|
||||
* will result in an error message being printed to the console and 0 being returned (which will
|
||||
* be ignored by the append functions).
|
||||
*
|
||||
* @param name Name
|
||||
* @param type Data type
|
||||
* @param metadata Initial metadata (e.g. data properties)
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
* @return Entry index
|
||||
*/
|
||||
public int start(String name, String type, String metadata, long timestamp) {
|
||||
return DataLogJNI.start(m_impl, name, type, metadata, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an entry. Duplicate names are allowed (with the same type), and result in the same index
|
||||
* being returned (start/finish are reference counted). A duplicate name with a different type
|
||||
* will result in an error message being printed to the console and 0 being returned (which will
|
||||
* be ignored by the append functions).
|
||||
*
|
||||
* @param name Name
|
||||
* @param type Data type
|
||||
* @param metadata Initial metadata (e.g. data properties)
|
||||
* @return Entry index
|
||||
*/
|
||||
public int start(String name, String type, String metadata) {
|
||||
return start(name, type, metadata, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an entry. Duplicate names are allowed (with the same type), and result in the same index
|
||||
* being returned (start/finish are reference counted). A duplicate name with a different type
|
||||
* will result in an error message being printed to the console and 0 being returned (which will
|
||||
* be ignored by the append functions).
|
||||
*
|
||||
* @param name Name
|
||||
* @param type Data type
|
||||
* @return Entry index
|
||||
*/
|
||||
public int start(String name, String type) {
|
||||
return start(name, type, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish an entry.
|
||||
*
|
||||
* @param entry Entry index
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void finish(int entry, long timestamp) {
|
||||
DataLogJNI.finish(m_impl, entry, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish an entry.
|
||||
*
|
||||
* @param entry Entry index
|
||||
*/
|
||||
public void finish(int entry) {
|
||||
finish(entry, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the metadata for an entry.
|
||||
*
|
||||
* @param entry Entry index
|
||||
* @param metadata New metadata for the entry
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void setMetadata(int entry, String metadata, long timestamp) {
|
||||
DataLogJNI.setMetadata(m_impl, entry, metadata, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the metadata for an entry.
|
||||
*
|
||||
* @param entry Entry index
|
||||
* @param metadata New metadata for the entry
|
||||
*/
|
||||
public void setMetadata(int entry, String metadata) {
|
||||
setMetadata(entry, metadata, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param entry Entry index, as returned by Start()
|
||||
* @param data Data to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void appendRaw(int entry, byte[] data, long timestamp) {
|
||||
DataLogJNI.appendRaw(m_impl, entry, data, timestamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
DataLogJNI.close(m_impl);
|
||||
m_impl = 0;
|
||||
}
|
||||
|
||||
public void appendBoolean(int entry, boolean value, long timestamp) {
|
||||
DataLogJNI.appendBoolean(m_impl, entry, value, timestamp);
|
||||
}
|
||||
|
||||
public void appendInteger(int entry, long value, long timestamp) {
|
||||
DataLogJNI.appendInteger(m_impl, entry, value, timestamp);
|
||||
}
|
||||
|
||||
public void appendFloat(int entry, float value, long timestamp) {
|
||||
DataLogJNI.appendFloat(m_impl, entry, value, timestamp);
|
||||
}
|
||||
|
||||
public void appendDouble(int entry, double value, long timestamp) {
|
||||
DataLogJNI.appendDouble(m_impl, entry, value, timestamp);
|
||||
}
|
||||
|
||||
public void appendString(int entry, String value, long timestamp) {
|
||||
DataLogJNI.appendString(m_impl, entry, value, timestamp);
|
||||
}
|
||||
|
||||
public void appendBooleanArray(int entry, boolean[] arr, long timestamp) {
|
||||
DataLogJNI.appendBooleanArray(m_impl, entry, arr, timestamp);
|
||||
}
|
||||
|
||||
public void appendIntegerArray(int entry, long[] arr, long timestamp) {
|
||||
DataLogJNI.appendIntegerArray(m_impl, entry, arr, timestamp);
|
||||
}
|
||||
|
||||
public void appendFloatArray(int entry, float[] arr, long timestamp) {
|
||||
DataLogJNI.appendFloatArray(m_impl, entry, arr, timestamp);
|
||||
}
|
||||
|
||||
public void appendDoubleArray(int entry, double[] arr, long timestamp) {
|
||||
DataLogJNI.appendDoubleArray(m_impl, entry, arr, timestamp);
|
||||
}
|
||||
|
||||
public void appendStringArray(int entry, String[] arr, long timestamp) {
|
||||
DataLogJNI.appendStringArray(m_impl, entry, arr, timestamp);
|
||||
}
|
||||
|
||||
public long getImpl() {
|
||||
return m_impl;
|
||||
}
|
||||
|
||||
private long m_impl;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log entry base class. */
|
||||
public class DataLogEntry {
|
||||
protected DataLogEntry(DataLog log, String name, String type, String metadata, long timestamp) {
|
||||
m_log = log;
|
||||
m_entry = log.start(name, type, metadata, timestamp);
|
||||
}
|
||||
|
||||
protected DataLogEntry(DataLog log, String name, String type, String metadata) {
|
||||
this(log, name, type, metadata, 0);
|
||||
}
|
||||
|
||||
protected DataLogEntry(DataLog log, String name, String type) {
|
||||
this(log, name, type, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the metadata for the entry.
|
||||
*
|
||||
* @param metadata New metadata for the entry
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void setMetadata(String metadata, long timestamp) {
|
||||
m_log.setMetadata(m_entry, metadata, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the metadata for the entry.
|
||||
*
|
||||
* @param metadata New metadata for the entry
|
||||
*/
|
||||
public void setMetadata(String metadata) {
|
||||
setMetadata(metadata, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the entry.
|
||||
*
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void finish(long timestamp) {
|
||||
m_log.finish(m_entry, timestamp);
|
||||
}
|
||||
|
||||
/** Finishes the entry. */
|
||||
public void finish() {
|
||||
finish(0);
|
||||
}
|
||||
|
||||
protected final DataLog m_log;
|
||||
protected final int m_entry;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/** DataLogReader iterator. */
|
||||
public class DataLogIterator implements Iterator<DataLogRecord> {
|
||||
DataLogIterator(DataLogReader reader, int pos) {
|
||||
m_reader = reader;
|
||||
m_pos = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(Consumer<? super DataLogRecord> action) {
|
||||
int size = m_reader.size();
|
||||
for (; m_pos < size; m_pos = m_reader.getNextRecord(m_pos)) {
|
||||
DataLogRecord record;
|
||||
try {
|
||||
record = m_reader.getRecord(m_pos);
|
||||
} catch (NoSuchElementException ex) {
|
||||
break;
|
||||
}
|
||||
action.accept(record);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return (m_pos + 16) <= m_reader.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataLogRecord next() {
|
||||
DataLogRecord record = m_reader.getRecord(m_pos);
|
||||
m_pos = m_reader.getNextRecord(m_pos);
|
||||
return record;
|
||||
}
|
||||
|
||||
private final DataLogReader m_reader;
|
||||
private int m_pos;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
import edu.wpi.first.util.WPIUtilJNI;
|
||||
|
||||
public class DataLogJNI extends WPIUtilJNI {
|
||||
static native long create(String dir, String filename, double period, String extraHeader);
|
||||
|
||||
static native void setFilename(long impl, String filename);
|
||||
|
||||
static native void flush(long impl);
|
||||
|
||||
static native void pause(long impl);
|
||||
|
||||
static native void resume(long impl);
|
||||
|
||||
static native int start(long impl, String name, String type, String metadata, long timestamp);
|
||||
|
||||
static native void finish(long impl, int entry, long timestamp);
|
||||
|
||||
static native void setMetadata(long impl, int entry, String metadata, long timestamp);
|
||||
|
||||
static native void close(long impl);
|
||||
|
||||
static native void appendRaw(long impl, int entry, byte[] data, long timestamp);
|
||||
|
||||
static native void appendBoolean(long impl, int entry, boolean value, long timestamp);
|
||||
|
||||
static native void appendInteger(long impl, int entry, long value, long timestamp);
|
||||
|
||||
static native void appendFloat(long impl, int entry, float value, long timestamp);
|
||||
|
||||
static native void appendDouble(long impl, int entry, double value, long timestamp);
|
||||
|
||||
static native void appendString(long impl, int entry, String value, long timestamp);
|
||||
|
||||
static native void appendBooleanArray(long impl, int entry, boolean[] value, long timestamp);
|
||||
|
||||
static native void appendIntegerArray(long impl, int entry, long[] value, long timestamp);
|
||||
|
||||
static native void appendFloatArray(long impl, int entry, float[] value, long timestamp);
|
||||
|
||||
static native void appendDoubleArray(long impl, int entry, double[] value, long timestamp);
|
||||
|
||||
static native void appendStringArray(long impl, int entry, String[] value, long timestamp);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/** Data log reader (reads logs written by the DataLog class). */
|
||||
public class DataLogReader implements Iterable<DataLogRecord> {
|
||||
/**
|
||||
* Constructs from a byte buffer.
|
||||
*
|
||||
* @param buffer byte buffer
|
||||
*/
|
||||
public DataLogReader(ByteBuffer buffer) {
|
||||
m_buf = buffer;
|
||||
m_buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs from a file.
|
||||
*
|
||||
* @param filename filename
|
||||
* @throws IOException if could not open/read file
|
||||
*/
|
||||
public DataLogReader(String filename) throws IOException {
|
||||
RandomAccessFile f = new RandomAccessFile(filename, "r");
|
||||
FileChannel channel = f.getChannel();
|
||||
MappedByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
|
||||
m_buf = buf;
|
||||
m_buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
channel.close();
|
||||
f.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the data log is valid (e.g. has a valid header).
|
||||
*
|
||||
* @return True if valid, false otherwise
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return m_buf.remaining() >= 12
|
||||
&& m_buf.get(0) == 'W'
|
||||
&& m_buf.get(1) == 'P'
|
||||
&& m_buf.get(2) == 'I'
|
||||
&& m_buf.get(3) == 'L'
|
||||
&& m_buf.get(4) == 'O'
|
||||
&& m_buf.get(5) == 'G'
|
||||
&& m_buf.getShort(6) >= 0x0100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data log version. Returns 0 if data log is invalid.
|
||||
*
|
||||
* @return Version number; most significant byte is major, least significant is minor (so version
|
||||
* 1.0 will be 0x0100)
|
||||
*/
|
||||
public short getVersion() {
|
||||
if (m_buf.remaining() < 12) {
|
||||
return 0;
|
||||
}
|
||||
return m_buf.getShort(6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the extra header data.
|
||||
*
|
||||
* @return Extra header data
|
||||
*/
|
||||
public String getExtraHeader() {
|
||||
ByteBuffer buf = m_buf.duplicate();
|
||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
buf.position(8);
|
||||
int size = buf.getInt();
|
||||
byte[] arr = new byte[size];
|
||||
buf.get(arr);
|
||||
return new String(arr, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super DataLogRecord> action) {
|
||||
int size = m_buf.remaining();
|
||||
for (int pos = 12 + m_buf.getInt(8); pos < size; pos = getNextRecord(pos)) {
|
||||
DataLogRecord record;
|
||||
try {
|
||||
record = getRecord(pos);
|
||||
} catch (NoSuchElementException ex) {
|
||||
break;
|
||||
}
|
||||
action.accept(record);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataLogIterator iterator() {
|
||||
return new DataLogIterator(this, 12 + m_buf.getInt(8));
|
||||
}
|
||||
|
||||
private long readVarInt(int pos, int len) {
|
||||
long val = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
val |= ((long) (m_buf.get(pos + i) & 0xff)) << (i * 8);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@SuppressWarnings("PMD.PreserveStackTrace")
|
||||
DataLogRecord getRecord(int pos) {
|
||||
try {
|
||||
int lenbyte = m_buf.get(pos) & 0xff;
|
||||
int entryLen = (lenbyte & 0x3) + 1;
|
||||
int sizeLen = ((lenbyte >> 2) & 0x3) + 1;
|
||||
int timestampLen = ((lenbyte >> 4) & 0x7) + 1;
|
||||
int headerLen = 1 + entryLen + sizeLen + timestampLen;
|
||||
int entry = (int) readVarInt(pos + 1, entryLen);
|
||||
int size = (int) readVarInt(pos + 1 + entryLen, sizeLen);
|
||||
long timestamp = readVarInt(pos + 1 + entryLen + sizeLen, timestampLen);
|
||||
// build a slice of the data contents
|
||||
ByteBuffer data = m_buf.duplicate();
|
||||
data.position(pos + headerLen);
|
||||
data.limit(pos + headerLen + size);
|
||||
return new DataLogRecord(entry, timestamp, data.slice());
|
||||
} catch (BufferUnderflowException | IndexOutOfBoundsException ex) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
int getNextRecord(int pos) {
|
||||
int lenbyte = m_buf.get(pos) & 0xff;
|
||||
int entryLen = (lenbyte & 0x3) + 1;
|
||||
int sizeLen = ((lenbyte >> 2) & 0x3) + 1;
|
||||
int timestampLen = ((lenbyte >> 4) & 0x7) + 1;
|
||||
int headerLen = 1 + entryLen + sizeLen + timestampLen;
|
||||
|
||||
int size = 0;
|
||||
for (int i = 0; i < sizeLen; i++) {
|
||||
size |= ((int) (m_buf.get(pos + 1 + entryLen + i) & 0xff)) << (i * 8);
|
||||
}
|
||||
return pos + headerLen + size;
|
||||
}
|
||||
|
||||
int size() {
|
||||
return m_buf.remaining();
|
||||
}
|
||||
|
||||
private final ByteBuffer m_buf;
|
||||
}
|
||||
@@ -0,0 +1,435 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.LongBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.InputMismatchException;
|
||||
|
||||
/**
|
||||
* A record in the data log. May represent either a control record (entry == 0) or a data record.
|
||||
* Used only for reading (e.g. with DataLogReader).
|
||||
*/
|
||||
@SuppressWarnings("PMD.PreserveStackTrace")
|
||||
public class DataLogRecord {
|
||||
private static final int kControlStart = 0;
|
||||
private static final int kControlFinish = 1;
|
||||
private static final int kControlSetMetadata = 2;
|
||||
|
||||
DataLogRecord(int entry, long timestamp, ByteBuffer data) {
|
||||
m_entry = entry;
|
||||
m_timestamp = timestamp;
|
||||
m_data = data;
|
||||
m_data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entry ID.
|
||||
*
|
||||
* @return entry ID
|
||||
*/
|
||||
public int getEntry() {
|
||||
return m_entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the record timestamp.
|
||||
*
|
||||
* @return Timestamp, in integer microseconds
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the raw data.
|
||||
*
|
||||
* @return size
|
||||
*/
|
||||
public int getSize() {
|
||||
return m_data.remaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw data. Use the GetX functions to decode based on the data type in the entry's start
|
||||
* record.
|
||||
*
|
||||
* @return byte array
|
||||
*/
|
||||
public byte[] getRaw() {
|
||||
ByteBuffer buf = getRawBuffer();
|
||||
byte[] arr = new byte[buf.remaining()];
|
||||
buf.get(arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw data. Use the GetX functions to decode based on the data type in the entry's start
|
||||
* record.
|
||||
*
|
||||
* @return byte buffer
|
||||
*/
|
||||
public ByteBuffer getRawBuffer() {
|
||||
ByteBuffer buf = m_data.duplicate();
|
||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the record is a control record.
|
||||
*
|
||||
* @return True if control record, false if normal data record.
|
||||
*/
|
||||
public boolean isControl() {
|
||||
return m_entry == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the record is a start control record. Use GetStartData() to decode the
|
||||
* contents.
|
||||
*
|
||||
* @return True if start control record, false otherwise.
|
||||
*/
|
||||
public boolean isStart() {
|
||||
return m_entry == 0 && m_data.remaining() >= 17 && m_data.get(0) == kControlStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the record is a finish control record. Use GetFinishEntry() to decode the
|
||||
* contents.
|
||||
*
|
||||
* @return True if finish control record, false otherwise.
|
||||
*/
|
||||
public boolean isFinish() {
|
||||
return m_entry == 0 && m_data.remaining() == 5 && m_data.get(0) == kControlFinish;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the record is a set metadata control record. Use GetSetMetadataData() to decode
|
||||
* the contents.
|
||||
*
|
||||
* @return True if set metadata control record, false otherwise.
|
||||
*/
|
||||
public boolean isSetMetadata() {
|
||||
return m_entry == 0 && m_data.remaining() >= 9 && m_data.get(0) == kControlSetMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data contained in a start control record as created by DataLog.start() when writing the log.
|
||||
* This can be read by calling getStartData().
|
||||
*/
|
||||
public static class StartRecordData {
|
||||
StartRecordData(int entry, String name, String type, String metadata) {
|
||||
this.entry = entry;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
/** Entry ID; this will be used for this entry in future records. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public final int entry;
|
||||
|
||||
/** Entry name. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public final String name;
|
||||
|
||||
/** Type of the stored data for this entry, as a string, e.g. "double". */
|
||||
@SuppressWarnings("MemberName")
|
||||
public final String type;
|
||||
|
||||
/** Initial metadata. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public final String metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a start control record.
|
||||
*
|
||||
* @return start record decoded data
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public StartRecordData getStartData() {
|
||||
if (!isStart()) {
|
||||
throw new InputMismatchException("not a start record");
|
||||
}
|
||||
ByteBuffer buf = getRawBuffer();
|
||||
buf.position(1); // skip over control type
|
||||
int entry = buf.getInt();
|
||||
String name = readInnerString(buf);
|
||||
String type = readInnerString(buf);
|
||||
String metadata = readInnerString(buf);
|
||||
return new StartRecordData(entry, name, type, metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data contained in a set metadata control record as created by DataLog.setMetadata(). This can
|
||||
* be read by calling getSetMetadataData().
|
||||
*/
|
||||
public static class MetadataRecordData {
|
||||
MetadataRecordData(int entry, String metadata) {
|
||||
this.entry = entry;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
/** Entry ID. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public final int entry;
|
||||
|
||||
/** New metadata for the entry. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public final String metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a finish control record.
|
||||
*
|
||||
* @return finish record entry ID
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public int getFinishEntry() {
|
||||
if (!isFinish()) {
|
||||
throw new InputMismatchException("not a finish record");
|
||||
}
|
||||
return m_data.getInt(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a set metadata control record.
|
||||
*
|
||||
* @return set metadata record decoded data
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public MetadataRecordData getSetMetadataData() {
|
||||
if (!isSetMetadata()) {
|
||||
throw new InputMismatchException("not a set metadata record");
|
||||
}
|
||||
ByteBuffer buf = getRawBuffer();
|
||||
buf.position(1); // skip over control type
|
||||
int entry = buf.getInt();
|
||||
String metadata = readInnerString(buf);
|
||||
return new MetadataRecordData(entry, metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a boolean. Note if the data type (as indicated in the corresponding
|
||||
* start control record for this entry) is not "boolean", invalid results may be returned.
|
||||
*
|
||||
* @return boolean value
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public boolean getBoolean() {
|
||||
try {
|
||||
return m_data.get(0) != 0;
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
throw new InputMismatchException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as an integer. Note if the data type (as indicated in the corresponding
|
||||
* start control record for this entry) is not "int64", invalid results may be returned.
|
||||
*
|
||||
* @return integer value
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public long getInteger() {
|
||||
try {
|
||||
return m_data.getLong(0);
|
||||
} catch (BufferUnderflowException | IndexOutOfBoundsException ex) {
|
||||
throw new InputMismatchException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a float. Note if the data type (as indicated in the corresponding
|
||||
* start control record for this entry) is not "float", invalid results may be returned.
|
||||
*
|
||||
* @return float value
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public float getFloat() {
|
||||
try {
|
||||
return m_data.getFloat(0);
|
||||
} catch (BufferUnderflowException | IndexOutOfBoundsException ex) {
|
||||
throw new InputMismatchException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a double. Note if the data type (as indicated in the corresponding
|
||||
* start control record for this entry) is not "double", invalid results may be returned.
|
||||
*
|
||||
* @return double value
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public double getDouble() {
|
||||
try {
|
||||
return m_data.getDouble(0);
|
||||
} catch (BufferUnderflowException | IndexOutOfBoundsException ex) {
|
||||
throw new InputMismatchException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a string. Note if the data type (as indicated in the corresponding
|
||||
* start control record for this entry) is not "string", invalid results may be returned.
|
||||
*
|
||||
* @return string value
|
||||
*/
|
||||
public String getString() {
|
||||
return new String(getRaw(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a boolean array. Note if the data type (as indicated in the
|
||||
* corresponding start control record for this entry) is not "boolean[]", invalid results may be
|
||||
* returned.
|
||||
*
|
||||
* @return boolean array
|
||||
*/
|
||||
public boolean[] getBooleanArray() {
|
||||
boolean[] arr = new boolean[m_data.remaining()];
|
||||
for (int i = 0; i < m_data.remaining(); i++) {
|
||||
arr[i] = m_data.get(i) != 0;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as an integer array. Note if the data type (as indicated in the
|
||||
* corresponding start control record for this entry) is not "int64[]", invalid results may be
|
||||
* returned.
|
||||
*
|
||||
* @return integer array
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public long[] getIntegerArray() {
|
||||
LongBuffer buf = getIntegerBuffer();
|
||||
long[] arr = new long[buf.remaining()];
|
||||
buf.get(arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as an integer array. Note if the data type (as indicated in the
|
||||
* corresponding start control record for this entry) is not "int64[]", invalid results may be
|
||||
* returned.
|
||||
*
|
||||
* @return integer buffer
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public LongBuffer getIntegerBuffer() {
|
||||
if ((m_data.limit() % 8) != 0) {
|
||||
throw new InputMismatchException("data size is not a multiple of 8");
|
||||
}
|
||||
return m_data.asLongBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a float array. Note if the data type (as indicated in the
|
||||
* corresponding start control record for this entry) is not "float[]", invalid results may be
|
||||
* returned.
|
||||
*
|
||||
* @return float array
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public float[] getFloatArray() {
|
||||
FloatBuffer buf = getFloatBuffer();
|
||||
float[] arr = new float[buf.remaining()];
|
||||
buf.get(arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a float array. Note if the data type (as indicated in the
|
||||
* corresponding start control record for this entry) is not "float[]", invalid results may be
|
||||
* returned.
|
||||
*
|
||||
* @return float buffer
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public FloatBuffer getFloatBuffer() {
|
||||
if ((m_data.limit() % 4) != 0) {
|
||||
throw new InputMismatchException("data size is not a multiple of 4");
|
||||
}
|
||||
return m_data.asFloatBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a double array. Note if the data type (as indicated in the
|
||||
* corresponding start control record for this entry) is not "double[]", invalid results may be
|
||||
* returned.
|
||||
*
|
||||
* @return double array
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public double[] getDoubleArray() {
|
||||
DoubleBuffer buf = getDoubleBuffer();
|
||||
double[] arr = new double[buf.remaining()];
|
||||
buf.get(arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a double array. Note if the data type (as indicated in the
|
||||
* corresponding start control record for this entry) is not "double[]", invalid results may be
|
||||
* returned.
|
||||
*
|
||||
* @return double buffer
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public DoubleBuffer getDoubleBuffer() {
|
||||
if ((m_data.limit() % 8) != 0) {
|
||||
throw new InputMismatchException("data size is not a multiple of 8");
|
||||
}
|
||||
return m_data.asDoubleBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a data record as a string array. Note if the data type (as indicated in the
|
||||
* corresponding start control record for this entry) is not "string[]", invalid results may be
|
||||
* returned.
|
||||
*
|
||||
* @return string array
|
||||
* @throws InputMismatchException on error
|
||||
*/
|
||||
public String[] getStringArray() {
|
||||
ByteBuffer buf = getRawBuffer();
|
||||
try {
|
||||
int size = buf.getInt();
|
||||
// sanity check size
|
||||
if (size > (buf.remaining() / 4)) {
|
||||
throw new InputMismatchException("invalid size");
|
||||
}
|
||||
String[] arr = new String[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
arr[i] = readInnerString(buf);
|
||||
}
|
||||
return arr;
|
||||
} catch (BufferUnderflowException | IndexOutOfBoundsException ex) {
|
||||
throw new InputMismatchException();
|
||||
}
|
||||
}
|
||||
|
||||
private String readInnerString(ByteBuffer buf) {
|
||||
int size = buf.getInt();
|
||||
if (size > buf.remaining()) {
|
||||
throw new InputMismatchException("invalid string size");
|
||||
}
|
||||
byte[] arr = new byte[size];
|
||||
buf.get(arr);
|
||||
return new String(arr, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private final int m_entry;
|
||||
private final long m_timestamp;
|
||||
private final ByteBuffer m_data;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log array of double values. */
|
||||
public class DoubleArrayLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "double[]";
|
||||
|
||||
public DoubleArrayLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
super(log, name, kDataType, metadata, timestamp);
|
||||
}
|
||||
|
||||
public DoubleArrayLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public DoubleArrayLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public DoubleArrayLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(double[] value, long timestamp) {
|
||||
m_log.appendDoubleArray(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(double[] value) {
|
||||
m_log.appendDoubleArray(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log double values. */
|
||||
public class DoubleLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "double";
|
||||
|
||||
public DoubleLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
super(log, name, kDataType, metadata, timestamp);
|
||||
}
|
||||
|
||||
public DoubleLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public DoubleLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public DoubleLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(double value, long timestamp) {
|
||||
m_log.appendDouble(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(double value) {
|
||||
m_log.appendDouble(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log array of float values. */
|
||||
public class FloatArrayLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "float[]";
|
||||
|
||||
public FloatArrayLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
super(log, name, kDataType, metadata, timestamp);
|
||||
}
|
||||
|
||||
public FloatArrayLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public FloatArrayLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public FloatArrayLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(float[] value, long timestamp) {
|
||||
m_log.appendFloatArray(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(float[] value) {
|
||||
m_log.appendFloatArray(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log float values. */
|
||||
public class FloatLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "float";
|
||||
|
||||
public FloatLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
super(log, name, kDataType, metadata, timestamp);
|
||||
}
|
||||
|
||||
public FloatLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public FloatLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public FloatLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(float value, long timestamp) {
|
||||
m_log.appendFloat(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(float value) {
|
||||
m_log.appendFloat(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log array of integer values. */
|
||||
public class IntegerArrayLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "int64[]";
|
||||
|
||||
public IntegerArrayLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
super(log, name, kDataType, metadata, timestamp);
|
||||
}
|
||||
|
||||
public IntegerArrayLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public IntegerArrayLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public IntegerArrayLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(long[] value, long timestamp) {
|
||||
m_log.appendIntegerArray(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(long[] value) {
|
||||
m_log.appendIntegerArray(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log integer values. */
|
||||
public class IntegerLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "int64";
|
||||
|
||||
public IntegerLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
super(log, name, kDataType, metadata, timestamp);
|
||||
}
|
||||
|
||||
public IntegerLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public IntegerLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public IntegerLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(long value, long timestamp) {
|
||||
m_log.appendInteger(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(long value) {
|
||||
m_log.appendInteger(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log raw byte array values. */
|
||||
public class RawLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "raw";
|
||||
|
||||
public RawLogEntry(DataLog log, String name, String metadata, String type, long timestamp) {
|
||||
super(log, name, type, metadata, timestamp);
|
||||
}
|
||||
|
||||
public RawLogEntry(DataLog log, String name, String metadata, String type) {
|
||||
this(log, name, metadata, type, 0);
|
||||
}
|
||||
|
||||
public RawLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
this(log, name, metadata, kDataType, timestamp);
|
||||
}
|
||||
|
||||
public RawLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public RawLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public RawLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(byte[] value, long timestamp) {
|
||||
m_log.appendRaw(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(byte[] value) {
|
||||
m_log.appendRaw(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log array of string values. */
|
||||
public class StringArrayLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "string[]";
|
||||
|
||||
public StringArrayLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
super(log, name, kDataType, metadata, timestamp);
|
||||
}
|
||||
|
||||
public StringArrayLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public StringArrayLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public StringArrayLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(String[] value, long timestamp) {
|
||||
m_log.appendStringArray(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(String[] value) {
|
||||
m_log.appendStringArray(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.datalog;
|
||||
|
||||
/** Log string values. */
|
||||
public class StringLogEntry extends DataLogEntry {
|
||||
public static final String kDataType = "string";
|
||||
|
||||
public StringLogEntry(DataLog log, String name, String metadata, String type, long timestamp) {
|
||||
super(log, name, type, metadata, timestamp);
|
||||
}
|
||||
|
||||
public StringLogEntry(DataLog log, String name, String metadata, String type) {
|
||||
this(log, name, metadata, type, 0);
|
||||
}
|
||||
|
||||
public StringLogEntry(DataLog log, String name, String metadata, long timestamp) {
|
||||
this(log, name, metadata, kDataType, timestamp);
|
||||
}
|
||||
|
||||
public StringLogEntry(DataLog log, String name, String metadata) {
|
||||
this(log, name, metadata, 0);
|
||||
}
|
||||
|
||||
public StringLogEntry(DataLog log, String name, long timestamp) {
|
||||
this(log, name, "", timestamp);
|
||||
}
|
||||
|
||||
public StringLogEntry(DataLog log, String name) {
|
||||
this(log, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
* @param timestamp Time stamp (may be 0 to indicate now)
|
||||
*/
|
||||
public void append(String value, long timestamp) {
|
||||
m_log.appendString(m_entry, value, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a record to the log.
|
||||
*
|
||||
* @param value Value to record
|
||||
*/
|
||||
public void append(String value) {
|
||||
m_log.appendString(m_entry, value, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user