-
Notifications
You must be signed in to change notification settings - Fork 76
nbtool
NOW SEE tool8
To run the tool: cd in nbites/src/nbtool and enter the command:
./RUNnbtool
To run nbcross: while the tool is running, cd into nbites/src/nbcross and run the command:
make nbcross
If everything works correctly, the 'cpp' label in the sidebar on the right of the tool should turn green!
This document also covers the logging and control frameworks that integrate with nbtool
first version :
https://github.com/philipkoch/nbites/commit/5e5a9888068769b1a25b05d669327d01b445c83b
latest version:
https://github.com/philipkoch/nbites/tree/tool6-clean
The first few sections of this document cover a few functional topics. More detailed pages for specific sections of the logging system are listed after.
The new logging and tool system has three components. First, there is the c++ code that runs on the robot – logging and control . These two components coordinate getting information out of man during play, as well as allowing external applications to manipulate the man process. Next, there is the external java tool (nbtool). This cross-platform tool facilitates offline manipulation of logged data, offline communication with nbcross instances, and communication with active robots. The final section is nbcross, which allows nbtool to call and examine the output of c++ code, usually portions of man being run offline.
The simplest and quickest part of the new system to use is nbtool. To run the tool, you must have at least java SE 1.7 (i.e. version 7) installed on your machine. To get your java version, execute
java -version
Install java on ubuntu here: https://www.digitalocean.com/community/tutorials/how-to-install-java-on-ubuntu-with-apt-get
With 1.7 or better, you can copy the entire nbites directory from any team member who has built the tool. Then execute RUNnbtool-nobuild (with a correctly set NBITES_DIR variable – see below).
To compile the tool, you must have a java SDK (Standard Development Kit) version 1.7 or higher. To check your sdk version, execute
javac -version
The tool requires google's protobuf library to compile, but a copy of this library's source is included. Compiling the tool with BUILDnbtool requires that the environment variable NBITES_DIR
be set correctly. If you are running a linux machine and have used the setup script, this should be set automatically. Otherwise, you will need to set this variable manually. In any case, execute env
to check.
BUILD ERRORS RESEMBLING THE FOLLOWING ARE PROBABLY DUE TO BAD NBITES_DIR VARIABLES
mkdir: /build/nbtool: Permission denied
javac: directory not found: /build/nbtool
Usage: javac <options> <source files> use -help for a list of possible options
Another great option for building and editing the tool's src is to use an IDE like eclipse. You can link all of the tool source into your IDE's project even if that project is not in the nbites directory, which allows your edits to occur on the original source code without adding project configuration files and testing code to your nbites clone and git commits.
The tool's log format (indicated by file extension .nblog
) is mirrored between the java and c++ implementations. The format has two major components and two minor components. In order:
1 description length, 4 bytes network order comprising a 32 bit signed integer.
2 description description length
byte sized characters (UTF8) composing a human readable S expression. In the source, S expressions are called SExprs. Note also that if this string is null-terminated (which is not guaranteed), the null byte will be included in description length
. This field is typically accessible in a given language by calling .tree()
on the log. This will return the top-level SExpr object represented by the log's description. The source character array of the description is either inaccessible or nonexistent after the log has been read into the language.
3 data length, 4 bytes network order comprising a 32 bit signed integer.
4 data data length
bytes of data, with any format allowed. Typically accessible in a given language by calling .data()
on the log.
Therefore, the minimum size of any nblog is 8 bytes. For logs intended to be loaded by nbtool, the description
field must start with the character string (nblog
or the log will be rejected.
The 4 byte fields are required to be in network order. IO operations in java do not typically need to worry about this: IO operations in c++ almost always do. This is because java uses network order by default while c++ uses the host endianness, which on x86 machines is typically little-endian (the opposite of network order) In either case, worry about writing or reading logs can almost always be differed to nblog::Log::write()
and nblog::Log::send()
in c++ or nbtool.io.CommonIO.readLog()
and nbtool.io.CommonIO.writeLog()
in java.
####using log data
The log format does not explicitly determine what format a log's data bytes will be in. Typically, some portion of the description will declare what information is stored in the data field. For example, YUVImage logs have a (type YUVImage)
key value pair in their description which directs the tool to interpret the data bytes as pixels.
-
Even if the format of the data has been determined, further processing may be necessary. For example, the data fields of logs containing protobufs hold the serialized protobuf. To access fields of the protobuf, users must first deserialize the protobuf into a language appropriate object.
-
Except for default views (which don't try to parse a log), if the tool does not recognize a log's type it won't try to load views for it. So you may create logs of any format; as long as they declare a previously unused type the tool will not mistakenly try to parse them.
NOTE: the tool assumes it may load certain protobuf views for all logs whose type has prefix '-proto'
####using S expressions (SExpr
in the source)
Dedicated to Cheddar whose SExpr induced loss of sanity motivated the creation of these pages.
Though SExprs may at first be intimidating, they are a simple protocol for encoding nested lists (i.e., trees). Though Lisp uses SExprs as both source code and data, we allow and interpret a subset of the full S expression notation.
every SExpr node is either
- an atom – i.e. an indivisible string
- a list – i.e. a (possibly empty) list of other SExpr nodes.
Because the characters " ( )
are considered special in SExpr notation, atoms which would like to include these characters must escape them by surrounding the atom in "
characters, which will not be included in the atom's value. To include an actual "
character, use ""
inside an escaped string.
Though all atoms are essentially strings, we may interpret these strings as integers, floats, or boolean values as necessary. Support for doing this in both languages is provided (see the valueAsX
methods in the c++ impl and java impl ).
Here is an example YUVImage log's SExpr tree (note that in actual logs the SExpr is serialized into a more compact but equivalent string). This tree demonstrates how the first atom of a list can be used as the key with which to interpret the subsequent nodes – so SExprs can encode dictionaries.
( nblog
(created LogModule "01.05.2015 23:34:45")
(version 6)
(checksum 71290316)
( contents
(
(type YUVImage)
(from camera_TOP)
(when 457970000)
(iindex 2659)
(nbytes 614400)
(width 640)
(height 480)
(encoding "[Y8(U8/V8)]")
)
)
(host_type V4ROBOT)
)
This SExpr demonstrates a few standard (and in some cases necessary) paths in a log's tree. All logs must have their top level node be a list – the tree cannot start with an atom, and the tool ignores any nodes after the top-level list terminates. Second, all logs which might need to be written to a filesystem (so not logs like command logs) must have as the first child node of the top-level-list the atom "nblog". These two requirements lead to the first characters in almost all logs serialized descriptions being
(nblog
In the top namespace of a log, a few keys (lists where the first node is an atom) are reserved. Here they are listed, and their typical values explained.
-
created
"where" "when" -
version
"versionAsInt" -
checksum
signed 32 bit checksum ofdata
. -
contents
one or more lists, where each list contains key-value pairs describing specific attributes of a certain data-type stored in this log (e.g.,(type typeName)
). These 'sub-dictionaries' should be listed in the same order as their corresponding data is stored in thedata
field. For an example of this, see 'tripoint' logs. -
host_type
V4ROBOT, V5ROBOT, or UNKNOWN -
from_address
address from which this log was streamed, if applicable
In nbtool, views are ways of interpreting and displaying data to the user. The tool automatically loads the correct views when a log of a specific type is selected.
Each logview
is a specific way of viewing a log of a certain type.
Every view must extend nbtool.gui.logviews.misc.ViewParent
, which is an abstract class extending JPanel
. ViewParent
has one abstract method which subclasses must implement:
-
setLog(Log newlog)
this method is called with the log to display as argument. Though any subclass may use the no-argument constructor to initialize GUI elements, populating those elements will likely need to wait until the relevant log is supplied by the GUI via this method. - views may modify the logs they are provided – the modifications will persist through the lifetime of the process but will not be written to fs unless the log is (re)saved.
- views may conduct essentially any computation they want in this method, including requesting c++ computation via nbcross
ViewParent
also has a few other methods which subclasses may override for non-standard functionalities. These methods have default implementations which effectively do nothing.
-
shouldLoadInParallel()
returns a boolean letting the GUI know if this class's instances should be created and given their log in a separate (non-GUI) thread. By default, views are created and set in the GUI thread. Since Swing is single-threaded, the GUI cannot process other actions (such as user clicks) while views load. Returning true allows a view to take its time loading without freezing the entire tool – whensetLog()
returns, the GUI will synchronize with the view's thread and add it to the display. -
alsoSelected(ArrayList<Log> also)
provides the view with all other logs currently selected by the user, excluding the primary log supplied bysetLog()
. Though the order of these logs is undefined, in practice it is reasonably predictable.
View instances are automatically resized by the log display according to user actions. Subclasses only need to define what to paint/display in that space.
To get the tool to automatically load a view when logs are selected, two things must happen. First, the view's class must be added to the appropriate array in NBConstants.java's setupPossible()
initialization function. The string key to which each array of classes is mapped expresses what log types the view is capable of displaying. So if you wish to load an instance of NewView.class
whenever a log of type "NewType" is selected, add a line like
map.put("NewType", new Class[]{NewView.class});
to setupPossible()
.
There are two special super types: default and protobuf. Classes added to either of these keys must be capable of displaying all logs and all protobuf logs, respectively. The tool assumes classes mapped to default (DEFAULT_S
in NBConstants.java) may be loaded for any log. It assumes classes mapped to protobuf (PROTOBUF_S
in NBConstants.java) may be loaded for any protobuf log – which to the tool is any log whose type has prefix 'proto-'.
The second necessary step in getting a view to display is making sure it is enabled in a users view mapping. This is as simple as opening the LogToViewUtility in the utility pane of the tool and selecting the view under the appropriate type.
All logging and control code on the robot can be (and is) turned off by disabling the USE_LOGGING
flag. If USE_LOGGING
is enabled, four threads are created: log_main, which for now only handles reporting about the status of the robot, log_streamio, which handles sending any and all logs to connected tools, log_fileio – writing logs to the robot's filesystem, and control which is explained elsewhere. Note that these threads typically spend 99% of their time sleeping.
man/log contains the code specific to setting up the log server. See nblog for more details about logging on the robots.
man/control contains the code specific to setting up the control server. This server is responsible for communicating with hosts (like nbtool) outside the man process. control.h also includes a number of flags which control logging on the robot and can be remotely set by nbtool. See control for more details.
-
nbtool
fin.