Java and Python Wrappers: Not available in Java or Python wrapper libraries. " \
+ "notwindows=@note Not available on Windows " \
+ "windowsonly=@note Available on Windows only " \
+ "linuxonly=@note Available on Linux only "
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be extracted
+# and appear in the documentation as a namespace called 'anonymous_namespace{file}',
+# where file will be replaced with the base name of the file that contains the anonymous
+# namespace. By default anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command , where is the value of
+# the FILE_VERSION_FILTER tag, and is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text "
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = src/ \
+ include/ \
+ examples/ \
+ docs/options/all_options.dox
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.cpp \
+ *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = proprietary*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = examples/ docs/options/
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *.cpp *_options
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = docs/figures
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command , where
+# is the value of the INPUT_FILTER tag, and is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH
+# then you must also enable this option. If you don't then doxygen will produce
+# a warning and turn it on anyway
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = ./
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = YES
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = AREXPORT=
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES = ../docs/Aria.tag=../../docs
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = docs/ArNetworking.tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = NO
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the number
+# of direct children of the root node in a graph is already larger than
+# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/Legacy/Aria/ArNetworking/doxygen.conf.in b/Legacy/Aria/ArNetworking/doxygen.conf.in
new file mode 100644
index 0000000..de5a767
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/doxygen.conf.in
@@ -0,0 +1,1304 @@
+# Doxyfile 1.5.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = ArNetworking
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = docs/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES = "javanote=
Java Wrapper Library: " \
+ "pynote=
Python Wrapper Library: " \
+ "swignote=
Java and Python Wrappers: " \
+ "swigomit=
Java and Python Wrappers: Not available in Java or Python wrapper libraries. " \
+ "notwindows=@note Not available on Windows " \
+ "windowsonly=@note Available on Windows only " \
+ "linuxonly=@note Available on Linux only "
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be extracted
+# and appear in the documentation as a namespace called 'anonymous_namespace{file}',
+# where file will be replaced with the base name of the file that contains the anonymous
+# namespace. By default anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command , where is the value of
+# the FILE_VERSION_FILTER tag, and is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text "
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = src/ \
+ include/ \
+ examples/ \
+ docs/options/all_options.dox
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.cpp \
+ *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = proprietary*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = examples/ docs/options/
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *.cpp *_options
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = docs/figures
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command , where
+# is the value of the INPUT_FILTER tag, and is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH
+# then you must also enable this option. If you don't then doxygen will produce
+# a warning and turn it on anyway
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = ./
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = YES
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = AREXPORT=
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES = ../docs/Aria.tag=../../docs
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = docs/ArNetworking.tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = NO
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the number
+# of direct children of the root node in a graph is already larger than
+# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/Legacy/Aria/ArNetworking/examples/ArNetworking_Examples-vc2003.sln b/Legacy/Aria/ArNetworking/examples/ArNetworking_Examples-vc2003.sln
new file mode 100644
index 0000000..e31b6c2
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/ArNetworking_Examples-vc2003.sln
@@ -0,0 +1,87 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clientDemoStatic", "clientDemoStatic-vc2003.vcproj", "{0A8A179D-832B-44B2-829A-AB6E61BFF46E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {527BBF7C-631F-486B-8E4F-EA594299A71A} = {527BBF7C-631F-486B-8E4F-EA594299A71A}
+ {1D08AFC4-1036-425C-B381-6FE522207D47} = {1D08AFC4-1036-425C-B381-6FE522207D47}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ArNetworkingDLL", "..\src\ArNetworkingDLL-vc2003.vcproj", "{95FF1CC1-5006-4DEE-99D9-0B6C418C9689}"
+ ProjectSection(ProjectDependencies) = postProject
+ {606257AE-E882-4C66-84C0-72331642D09F} = {606257AE-E882-4C66-84C0-72331642D09F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ArNetworkingStatic", "..\src\ArNetworkingStatic-vc2003.vcproj", "{1D08AFC4-1036-425C-B381-6FE522207D47}"
+ ProjectSection(ProjectDependencies) = postProject
+ {527BBF7C-631F-486B-8E4F-EA594299A71A} = {527BBF7C-631F-486B-8E4F-EA594299A71A}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clientDemo", "clientDemo-vc2003.vcproj", "{806E0C42-BE8A-4857-A97B-068FD56C27A1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {606257AE-E882-4C66-84C0-72331642D09F} = {606257AE-E882-4C66-84C0-72331642D09F}
+ {95FF1CC1-5006-4DEE-99D9-0B6C418C9689} = {95FF1CC1-5006-4DEE-99D9-0B6C418C9689}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "serverDemo", "serverDemo-vc2003.vcproj", "{7AEA7E4D-0984-4A16-8A3F-AF36B1A27836}"
+ ProjectSection(ProjectDependencies) = postProject
+ {606257AE-E882-4C66-84C0-72331642D09F} = {606257AE-E882-4C66-84C0-72331642D09F}
+ {95FF1CC1-5006-4DEE-99D9-0B6C418C9689} = {95FF1CC1-5006-4DEE-99D9-0B6C418C9689}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "serverDemoStatic", "serverDemoStatic-vc2003.vcproj", "{31A8793E-E70A-4C52-B470-971BAF9DE5E0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {527BBF7C-631F-486B-8E4F-EA594299A71A} = {527BBF7C-631F-486B-8E4F-EA594299A71A}
+ {1D08AFC4-1036-425C-B381-6FE522207D47} = {1D08AFC4-1036-425C-B381-6FE522207D47}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AriaDLL", "..\..\src\AriaDLL-vc2003.vcproj", "{606257AE-E882-4C66-84C0-72331642D09F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AriaStatic", "..\..\src\AriaStatic-vc2003.vcproj", "{527BBF7C-631F-486B-8E4F-EA594299A71A}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {0A8A179D-832B-44B2-829A-AB6E61BFF46E}.Debug.ActiveCfg = Debug|Win32
+ {0A8A179D-832B-44B2-829A-AB6E61BFF46E}.Debug.Build.0 = Debug|Win32
+ {0A8A179D-832B-44B2-829A-AB6E61BFF46E}.Release.ActiveCfg = Release|Win32
+ {0A8A179D-832B-44B2-829A-AB6E61BFF46E}.Release.Build.0 = Release|Win32
+ {95FF1CC1-5006-4DEE-99D9-0B6C418C9689}.Debug.ActiveCfg = Debug|Win32
+ {95FF1CC1-5006-4DEE-99D9-0B6C418C9689}.Debug.Build.0 = Debug|Win32
+ {95FF1CC1-5006-4DEE-99D9-0B6C418C9689}.Release.ActiveCfg = Release|Win32
+ {95FF1CC1-5006-4DEE-99D9-0B6C418C9689}.Release.Build.0 = Release|Win32
+ {1D08AFC4-1036-425C-B381-6FE522207D47}.Debug.ActiveCfg = Debug|Win32
+ {1D08AFC4-1036-425C-B381-6FE522207D47}.Debug.Build.0 = Debug|Win32
+ {1D08AFC4-1036-425C-B381-6FE522207D47}.Release.ActiveCfg = Release|Win32
+ {1D08AFC4-1036-425C-B381-6FE522207D47}.Release.Build.0 = Release|Win32
+ {806E0C42-BE8A-4857-A97B-068FD56C27A1}.Debug.ActiveCfg = Debug|Win32
+ {806E0C42-BE8A-4857-A97B-068FD56C27A1}.Debug.Build.0 = Debug|Win32
+ {806E0C42-BE8A-4857-A97B-068FD56C27A1}.Release.ActiveCfg = Release|Win32
+ {806E0C42-BE8A-4857-A97B-068FD56C27A1}.Release.Build.0 = Release|Win32
+ {7AEA7E4D-0984-4A16-8A3F-AF36B1A27836}.Debug.ActiveCfg = Debug|Win32
+ {7AEA7E4D-0984-4A16-8A3F-AF36B1A27836}.Debug.Build.0 = Debug|Win32
+ {7AEA7E4D-0984-4A16-8A3F-AF36B1A27836}.Release.ActiveCfg = Release|Win32
+ {7AEA7E4D-0984-4A16-8A3F-AF36B1A27836}.Release.Build.0 = Release|Win32
+ {31A8793E-E70A-4C52-B470-971BAF9DE5E0}.Debug.ActiveCfg = Debug|Win32
+ {31A8793E-E70A-4C52-B470-971BAF9DE5E0}.Debug.Build.0 = Debug|Win32
+ {31A8793E-E70A-4C52-B470-971BAF9DE5E0}.Release.ActiveCfg = Release|Win32
+ {31A8793E-E70A-4C52-B470-971BAF9DE5E0}.Release.Build.0 = Release|Win32
+ {606257AE-E882-4C66-84C0-72331642D09F}.Debug.ActiveCfg = Debug|Win32
+ {606257AE-E882-4C66-84C0-72331642D09F}.Debug.Build.0 = Debug|Win32
+ {606257AE-E882-4C66-84C0-72331642D09F}.Release.ActiveCfg = Release|Win32
+ {606257AE-E882-4C66-84C0-72331642D09F}.Release.Build.0 = Release|Win32
+ {527BBF7C-631F-486B-8E4F-EA594299A71A}.Debug.ActiveCfg = Debug|Win32
+ {527BBF7C-631F-486B-8E4F-EA594299A71A}.Debug.Build.0 = Debug|Win32
+ {527BBF7C-631F-486B-8E4F-EA594299A71A}.Release.ActiveCfg = Release|Win32
+ {527BBF7C-631F-486B-8E4F-EA594299A71A}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Legacy/Aria/ArNetworking/examples/ArNetworking_Examples-vc2008.sln b/Legacy/Aria/ArNetworking/examples/ArNetworking_Examples-vc2008.sln
new file mode 100644
index 0000000..a83f152
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/ArNetworking_Examples-vc2008.sln
@@ -0,0 +1,79 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clientDemoStatic", "clientDemoStatic-vc2008.vcproj", "{0A8A179D-832B-44B2-829A-AB6E61BFF46E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {527BBF7C-631F-486B-8E4F-EA594299A71A} = {527BBF7C-631F-486B-8E4F-EA594299A71A}
+ {5AD87287-2610-453A-A986-A4CDCCC24C89} = {5AD87287-2610-453A-A986-A4CDCCC24C89}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ArNetworkingDLL", "..\src\ArNetworkingDLL-vc2008.vcproj", "{783BA2AB-07CE-43AD-8FC2-FFD9F19DF575}"
+ ProjectSection(ProjectDependencies) = postProject
+ {606257AE-E882-4C66-84C0-72331642D09F} = {606257AE-E882-4C66-84C0-72331642D09F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ArNetworkingStatic", "..\src\ArNetworkingStatic-vc2008.vcproj", "{5AD87287-2610-453A-A986-A4CDCCC24C89}"
+ ProjectSection(ProjectDependencies) = postProject
+ {527BBF7C-631F-486B-8E4F-EA594299A71A} = {527BBF7C-631F-486B-8E4F-EA594299A71A}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clientDemo", "clientDemo-vc2008.vcproj", "{806E0C42-BE8A-4857-A97B-068FD56C27A1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {606257AE-E882-4C66-84C0-72331642D09F} = {606257AE-E882-4C66-84C0-72331642D09F}
+ {783BA2AB-07CE-43AD-8FC2-FFD9F19DF575} = {783BA2AB-07CE-43AD-8FC2-FFD9F19DF575}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "serverDemoStatic", "serverDemoStatic-vc2008.vcproj", "{EEF9FE4C-34C4-4C76-94C4-D11930C88DE1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {527BBF7C-631F-486B-8E4F-EA594299A71A} = {527BBF7C-631F-486B-8E4F-EA594299A71A}
+ {5AD87287-2610-453A-A986-A4CDCCC24C89} = {5AD87287-2610-453A-A986-A4CDCCC24C89}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AriaDLL", "..\..\src\AriaDLL-vc2008.vcproj", "{606257AE-E882-4C66-84C0-72331642D09F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AriaStatic", "..\..\src\AriaStatic-vc2008.vcproj", "{527BBF7C-631F-486B-8E4F-EA594299A71A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "serverDemo", "serverDemo-vc2008.vcproj", "{B9C37E51-E357-4019-B4B5-71C42E1FCD11}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0A8A179D-832B-44B2-829A-AB6E61BFF46E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0A8A179D-832B-44B2-829A-AB6E61BFF46E}.Debug|Win32.Build.0 = Debug|Win32
+ {0A8A179D-832B-44B2-829A-AB6E61BFF46E}.Release|Win32.ActiveCfg = Release|Win32
+ {0A8A179D-832B-44B2-829A-AB6E61BFF46E}.Release|Win32.Build.0 = Release|Win32
+ {783BA2AB-07CE-43AD-8FC2-FFD9F19DF575}.Debug|Win32.ActiveCfg = Debug|Win32
+ {783BA2AB-07CE-43AD-8FC2-FFD9F19DF575}.Debug|Win32.Build.0 = Debug|Win32
+ {783BA2AB-07CE-43AD-8FC2-FFD9F19DF575}.Release|Win32.ActiveCfg = Release|Win32
+ {783BA2AB-07CE-43AD-8FC2-FFD9F19DF575}.Release|Win32.Build.0 = Release|Win32
+ {5AD87287-2610-453A-A986-A4CDCCC24C89}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5AD87287-2610-453A-A986-A4CDCCC24C89}.Debug|Win32.Build.0 = Debug|Win32
+ {5AD87287-2610-453A-A986-A4CDCCC24C89}.Release|Win32.ActiveCfg = Release|Win32
+ {5AD87287-2610-453A-A986-A4CDCCC24C89}.Release|Win32.Build.0 = Release|Win32
+ {806E0C42-BE8A-4857-A97B-068FD56C27A1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {806E0C42-BE8A-4857-A97B-068FD56C27A1}.Debug|Win32.Build.0 = Debug|Win32
+ {806E0C42-BE8A-4857-A97B-068FD56C27A1}.Release|Win32.ActiveCfg = Release|Win32
+ {806E0C42-BE8A-4857-A97B-068FD56C27A1}.Release|Win32.Build.0 = Release|Win32
+ {EEF9FE4C-34C4-4C76-94C4-D11930C88DE1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EEF9FE4C-34C4-4C76-94C4-D11930C88DE1}.Debug|Win32.Build.0 = Debug|Win32
+ {EEF9FE4C-34C4-4C76-94C4-D11930C88DE1}.Release|Win32.ActiveCfg = Release|Win32
+ {EEF9FE4C-34C4-4C76-94C4-D11930C88DE1}.Release|Win32.Build.0 = Release|Win32
+ {606257AE-E882-4C66-84C0-72331642D09F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {606257AE-E882-4C66-84C0-72331642D09F}.Debug|Win32.Build.0 = Debug|Win32
+ {606257AE-E882-4C66-84C0-72331642D09F}.Release|Win32.ActiveCfg = Release|Win32
+ {606257AE-E882-4C66-84C0-72331642D09F}.Release|Win32.Build.0 = Release|Win32
+ {527BBF7C-631F-486B-8E4F-EA594299A71A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {527BBF7C-631F-486B-8E4F-EA594299A71A}.Debug|Win32.Build.0 = Debug|Win32
+ {527BBF7C-631F-486B-8E4F-EA594299A71A}.Release|Win32.ActiveCfg = Release|Win32
+ {527BBF7C-631F-486B-8E4F-EA594299A71A}.Release|Win32.Build.0 = Release|Win32
+ {B9C37E51-E357-4019-B4B5-71C42E1FCD11}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B9C37E51-E357-4019-B4B5-71C42E1FCD11}.Debug|Win32.Build.0 = Debug|Win32
+ {B9C37E51-E357-4019-B4B5-71C42E1FCD11}.Release|Win32.ActiveCfg = Release|Win32
+ {B9C37E51-E357-4019-B4B5-71C42E1FCD11}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Legacy/Aria/ArNetworking/examples/Makefile b/Legacy/Aria/ArNetworking/examples/Makefile
new file mode 100644
index 0000000..d977f56
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/Makefile
@@ -0,0 +1,8 @@
+
+all:
+ $(MAKE) -C .. examples
+
+%: %.cpp
+ $(MAKE) -C .. examples/$@
+
+.PHONY: all
diff --git a/Legacy/Aria/ArNetworking/examples/README.txt b/Legacy/Aria/ArNetworking/examples/README.txt
new file mode 100644
index 0000000..0e7e0bf
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/README.txt
@@ -0,0 +1,26 @@
+These mostly come in pairs, with the description in front then the
+client or server tag
+
+clientCommandLister - A client that just connects to the server then lists the
+ data that the server has available. Also useful as a testing/diagnostic tool.
+
+configClient - A client that will get the ArConfig information from the server
+
+configClientToServer - A client that will send ArConfig information from
+ a config file to the server
+
+configServer - A server that takes the ArConfig information and
+ makes it available to the client, use in conjunction with configClient
+
+configServerRobot - Serves up a robot parameter file to edit (example)
+
+serverDemo - An example that will show the setting up of a
+ server with robot sensor visualization, robot control, and more...
+ connect with MobileEyes.
+
+drawingsExample - Shows how to display custom graphics (drawings) in
+ a client
+
+drawingsExampleWithRobot - Shows how to display custom graphics (drawings)
+ in a client, along with the robot and its sensors.
+
diff --git a/Legacy/Aria/ArNetworking/examples/clientCommandLister.cpp b/Legacy/Aria/ArNetworking/examples/clientCommandLister.cpp
new file mode 100644
index 0000000..b7a2cd8
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/clientCommandLister.cpp
@@ -0,0 +1,36 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ ArLog::init(ArLog::StdOut, ArLog::Normal);
+ ArClientBase client;
+
+ ArArgumentParser parser(&argc, argv);
+
+ ArClientSimpleConnector clientConnector(&parser);
+ parser.loadDefaultArguments();
+
+ if (!clientConnector.parseArgs() || !parser.checkHelpAndWarnUnparsed())
+ {
+ clientConnector.logOptions();
+ exit(0);
+ }
+
+ if (!clientConnector.connectClient(&client))
+ {
+ if (client.wasRejected())
+ printf("Server '%s' rejected connection, exiting\n", client.getHost());
+ else
+ printf("Could not connect to server '%s', exiting\n", client.getHost());
+ exit(1);
+ }
+ client.setRobotName(client.getHost()); // include server hostname in log messages
+ client.runAsync();
+ ArUtil::sleep(500);
+ client.logDataList();
+ Aria::shutdown();
+ return 0;
+}
+
diff --git a/Legacy/Aria/ArNetworking/examples/clientDemo-vc2003.vcproj b/Legacy/Aria/ArNetworking/examples/clientDemo-vc2003.vcproj
new file mode 100644
index 0000000..856fa8b
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/clientDemo-vc2003.vcproj
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/clientDemo-vc2008.vcproj b/Legacy/Aria/ArNetworking/examples/clientDemo-vc2008.vcproj
new file mode 100644
index 0000000..7c4c2b3
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/clientDemo-vc2008.vcproj
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/clientDemo-vc2010.vcxproj b/Legacy/Aria/ArNetworking/examples/clientDemo-vc2010.vcxproj
new file mode 100644
index 0000000..a2b2546
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/clientDemo-vc2010.vcxproj
@@ -0,0 +1,159 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ clientDemo
+ {806E0C42-BE8A-4857-A97B-068FD56C27A1}
+
+
+
+ Application
+ false
+ MultiByte
+ v100
+
+
+ Application
+ false
+ MultiByte
+ v100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ ../../bin/
+ ../../obj/$(ProjectName)-$(Configuration)-VC10/
+ false
+ ../../bin/
+ ../../obj/$(ProjectName)-$(Configuration)-VC10/
+ false
+ clientDemoDebugVC10
+ $(ProjectName)VC10
+
+
+
+ $(IntDir)$(ProjectName)BuildLog.htm
+
+
+ .\../../bin/clientDemo.tlb
+
+
+
+
+ Disabled
+ ..\include;..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDebugDLL
+ false
+
+
+ .\../../obj/
+ .\../../obj/
+ $(IntDir)vc100.pdb
+ true
+ Level3
+ true
+ ProgramDatabase
+ Default
+ true
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ AriaDebugVC10.lib;ArNetworkingDebugVC10.lib
+ $(OutDir)$(TargetFileName)
+ 1.0
+ true
+ ..\..\lib;%(AdditionalLibraryDirectories)
+ true
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)$(ProjectName)BuildLog.htm
+
+
+ .\../../bin/clientDemo.tlb
+
+
+
+
+ MaxSpeed
+ AnySuitable
+ true
+ ..\include;..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDLL
+ false
+ false
+ .\../../obj/clientDemo.pch
+ .\../../obj/
+ .\../../obj/
+ .\../../obj/
+ Level3
+ true
+ Default
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ AriaVC10.lib;ArNetworkingVC10.lib
+ $(OutDir)$(TargetFileName)
+ 1.0
+ true
+ ..\..\lib;%(AdditionalLibraryDirectories)
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ true
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Legacy/Aria/ArNetworking/examples/clientDemo.cpp b/Legacy/Aria/ArNetworking/examples/clientDemo.cpp
new file mode 100644
index 0000000..03a000c
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/clientDemo.cpp
@@ -0,0 +1,634 @@
+/* This is the ArNetworking example client.
+ * It connects to an ArNetworking server, and provides continuous
+ * information about the robot state (position, speed, server mode, etc.),
+ * and, if the server supports the commands, lets you drive the robot with
+ * the keyboard.
+ *
+ * To see the example client in action, first run a server on the robot's
+ * onboard computer, for example, serverDemo, testServer, guiServer (from ARNL),
+ * or ARAM. Make sure the robot computer is on a network, and run this
+ * clientDemo with the hostname of the robot computer as an argument:
+ *
+ * ./clientDemo -host myrobot
+ *
+ */
+
+#include "Aria.h"
+#include "ArNetworking.h"
+
+
+/* This class provides callback functions which are called by the ArKeyHandler
+ * object when the user presses keys. These callback functions adjust member
+ * variables. The sendInput() method sends a command with those values
+ * to the server using the "ratioDrive" request.
+ */
+
+class InputHandler
+{
+public:
+ /**
+ * @param client Our client networking object
+ * @param keyHandler Key handler to register command callbacks with
+ */
+ InputHandler(ArClientBase *client, ArKeyHandler *keyHandler);
+ virtual ~InputHandler(void);
+
+ /// Up arrow key handler: drive the robot forward
+ void up(void);
+
+ /// Down arrow key handler: drive the robot backward
+ void down(void);
+
+ /// Left arrow key handler: turn the robot left
+ void left(void);
+
+ /// Right arrow key handler: turn the robot right
+ void right(void);
+
+ /// Move the robot laterally right (q key)
+ void lateralLeft(void);
+
+ /// Move the robot laterally right (e key)
+ void lateralRight(void);
+
+ /// Send drive request to the server with stored values
+ void sendInput(void);
+
+ /// Send a request to enable "safe drive" mode on the server
+ void safeDrive();
+
+ /// Send a request to disable "safe drive" mode on the server
+ void unsafeDrive();
+
+ void listData();
+
+ void logTrackingTerse();
+ void logTrackingVerbose();
+ void resetTracking();
+protected:
+ ArClientBase *myClient;
+ ArKeyHandler *myKeyHandler;
+
+ /// Set this to true in the constructor to print out debugging information
+ bool myPrinting;
+
+ /// Current translation value (a percentage of the maximum speed)
+ double myTransRatio;
+
+ /// Current rotation ration value (a percentage of the maximum rotational velocity)
+ double myRotRatio;
+
+ /// Current rotation ration value (a percentage of the maximum rotational velocity)
+ double myLatRatio;
+
+ /** Functor objects, given to the key handler, which then call our handler
+ * methods above */
+ ///@{
+ ArFunctorC myUpCB;
+ ArFunctorC myDownCB;
+ ArFunctorC myLeftCB;
+ ArFunctorC myRightCB;
+ ArFunctorC myLateralLeftCB;
+ ArFunctorC myLateralRightCB;
+ ArFunctorC mySafeDriveCB;
+ ArFunctorC myUnsafeDriveCB;
+ ArFunctorC myListDataCB;
+ ArFunctorC myLogTrackingTerseCB;
+ ArFunctorC myLogTrackingVerboseCB;
+ ArFunctorC myResetTrackingCB;
+ ///@}
+};
+
+InputHandler::InputHandler(ArClientBase *client, ArKeyHandler *keyHandler) :
+ myClient(client), myKeyHandler(keyHandler),
+ myPrinting(false), myTransRatio(0.0), myRotRatio(0.0), myLatRatio(0.0),
+
+ /* Initialize functor objects with pointers to our handler methods: */
+ myUpCB(this, &InputHandler::up),
+ myDownCB(this, &InputHandler::down),
+ myLeftCB(this, &InputHandler::left),
+ myRightCB(this, &InputHandler::right),
+ myLateralLeftCB(this, &InputHandler::lateralLeft),
+ myLateralRightCB(this, &InputHandler::lateralRight),
+ mySafeDriveCB(this, &InputHandler::safeDrive),
+ myUnsafeDriveCB(this, &InputHandler::unsafeDrive),
+ myListDataCB(this, &InputHandler::listData),
+ myLogTrackingTerseCB(this, &InputHandler::logTrackingTerse),
+ myLogTrackingVerboseCB(this, &InputHandler::logTrackingVerbose),
+ myResetTrackingCB(this, &InputHandler::resetTracking)
+{
+
+ /* Add our functor objects to the key handler, associated with the appropriate
+ * keys: */
+ myKeyHandler->addKeyHandler(ArKeyHandler::UP, &myUpCB);
+ myKeyHandler->addKeyHandler(ArKeyHandler::DOWN, &myDownCB);
+ myKeyHandler->addKeyHandler(ArKeyHandler::LEFT, &myLeftCB);
+ myKeyHandler->addKeyHandler(ArKeyHandler::RIGHT, &myRightCB);
+ myKeyHandler->addKeyHandler('q', &myLateralLeftCB);
+ myKeyHandler->addKeyHandler('e', &myLateralRightCB);
+ myKeyHandler->addKeyHandler('s', &mySafeDriveCB);
+ myKeyHandler->addKeyHandler('u', &myUnsafeDriveCB);
+ myKeyHandler->addKeyHandler('l', &myListDataCB);
+ myKeyHandler->addKeyHandler('t', &myLogTrackingTerseCB);
+ myKeyHandler->addKeyHandler('v', &myLogTrackingVerboseCB);
+ myKeyHandler->addKeyHandler('r', &myResetTrackingCB);
+}
+
+InputHandler::~InputHandler(void)
+{
+
+}
+
+void InputHandler::up(void)
+{
+ if (myPrinting)
+ printf("Forwards\n");
+ myTransRatio = 100;
+}
+
+void InputHandler::down(void)
+{
+ if (myPrinting)
+ printf("Backwards\n");
+ myTransRatio = -100;
+}
+
+void InputHandler::left(void)
+{
+ if (myPrinting)
+ printf("Left\n");
+ myRotRatio = 100;
+}
+
+void InputHandler::right(void)
+{
+ if (myPrinting)
+ printf("Right\n");
+ myRotRatio = -100;
+}
+
+void InputHandler::lateralLeft(void)
+{
+ if (myPrinting)
+ printf("Lateral left\n");
+ myLatRatio = 100;
+}
+
+void InputHandler::lateralRight(void)
+{
+ if (myPrinting)
+ printf("Lateral right\n");
+ myLatRatio = -100;
+}
+
+void InputHandler::safeDrive()
+{
+ /* Construct a request packet. The data is a single byte, with value
+ * 1 to enable safe drive, 0 to disable. */
+ ArNetPacket p;
+ p.byteToBuf(1);
+
+ /* Send the packet as a single request: */
+ if(myPrinting)
+ printf("Sending setSafeDrive 1.\n");
+ myClient->requestOnce("setSafeDrive",&p);
+ if(myPrinting)
+ printf("\nSent enable safe drive.\n");
+}
+
+void InputHandler::unsafeDrive()
+{
+ /* Construct a request packet. The data is a single byte, with value
+ * 1 to enable safe drive, 0 to disable. */
+ ArNetPacket p;
+ p.byteToBuf(0);
+
+ /* Send the packet as a single request: */
+ if(myPrinting)
+ printf("Sending setSafeDrive 0.\n");
+ myClient->requestOnce("setSafeDrive",&p);
+ if(myPrinting)
+ printf("\nSent disable safe drive command. Your robot WILL run over things if you're not careful.\n");
+}
+
+void InputHandler::listData()
+{
+ myClient->logDataList();
+}
+
+void InputHandler::logTrackingTerse()
+{
+ myClient->logTracking(true);
+}
+
+void InputHandler::logTrackingVerbose()
+{
+ myClient->logTracking(false);
+}
+
+void InputHandler::resetTracking()
+{
+ myClient->resetTracking();
+}
+
+
+void InputHandler::sendInput(void)
+{
+ /* This method is called by the main function to send a ratioDrive
+ * request with our current velocity values. If the server does
+ * not support the ratioDrive request, then we abort now: */
+ if(!myClient->dataExists("ratioDrive")) return;
+
+ /* Construct a ratioDrive request packet. It consists
+ * of three doubles: translation ratio, rotation ratio, and an overall scaling
+ * factor. */
+ ArNetPacket packet;
+ packet.doubleToBuf(myTransRatio);
+ packet.doubleToBuf(myRotRatio);
+ packet.doubleToBuf(50); // use half of the robot's maximum.
+ packet.doubleToBuf(myLatRatio);
+ if (myPrinting)
+ printf("Sending\n");
+ myClient->requestOnce("ratioDrive", &packet);
+ myTransRatio = 0;
+ myRotRatio = 0;
+ myLatRatio = 0;
+}
+
+
+/** This class requests continual data updates from the server and prints them
+ * out.
+ */
+class OutputHandler
+{
+public:
+ OutputHandler(ArClientBase *client);
+ virtual ~OutputHandler(void);
+
+ /// This callback is called when an update on general robot state arrives
+ void handleOutput(ArNetPacket *packet);
+ /// This callback is called when an update on general robot state arrives
+ void handleOutputNumbers(ArNetPacket *packet);
+ /// This callback is called when an update on general robot state arrives
+ void handleOutputStrings(ArNetPacket *packet);
+
+ /// This callback is called when an update on the battery configuration changes
+ void handleBatteryInfo(ArNetPacket *packet);
+ /// This is called when the physical robot information comes back
+ void handlePhysicalInfo(ArNetPacket *packet);
+ /// This callback is called when an update on the temperature information changes
+ void handleTemperatureInfo(ArNetPacket *packet);
+ /// Called when the map on the server changes.
+ void handleMapUpdated(ArNetPacket *packet);
+protected:
+
+ /// The results from the data update are stored in these variables
+ //@{
+ double myX;
+ double myY;
+ double myTh;
+ double myVel;
+ double myRotVel;
+ double myLatVel;
+ bool myVoltageIsStateOfCharge;
+ char myTemperature;
+ double myVoltage;
+ char myStatus[256];
+ char myMode[256];
+ //@}
+ ArClientBase *myClient;
+
+ /** These functor objects are given to the client to receive updates when they
+ * arrive from the server.
+ */
+ //@{
+ ArFunctor1C myHandleOutputCB;
+ ArFunctor1C myHandleOutputNumbersCB;
+ ArFunctor1C myHandleOutputStringsCB;
+ ArFunctor1C myHandleBatteryInfoCB;
+ ArFunctor1C myHandlePhysicalInfoCB;
+ ArFunctor1C myHandleTemperatureInfoCB;
+ ArFunctor1C myHandleMapUpdatedCB;
+ //@}
+
+ /// A header for the columns in the data printout is sometimes printed
+ bool myNeedToPrintHeader;
+ /// Don't print any information until we get the battery info
+ bool myGotBatteryInfo;
+};
+
+OutputHandler::OutputHandler(ArClientBase *client) :
+ myClient(client),
+ myHandleOutputCB(this, &OutputHandler::handleOutput),
+ myHandleOutputNumbersCB(this, &OutputHandler::handleOutputNumbers),
+ myHandleOutputStringsCB(this, &OutputHandler::handleOutputStrings),
+ myHandleBatteryInfoCB(this, &OutputHandler::handleBatteryInfo),
+ myHandlePhysicalInfoCB(this, &OutputHandler::handlePhysicalInfo),
+ myHandleTemperatureInfoCB(this, &OutputHandler::handleTemperatureInfo),
+ myHandleMapUpdatedCB(this, &OutputHandler::handleMapUpdated),
+ myNeedToPrintHeader(false),
+ myGotBatteryInfo(false)
+{
+ /* Add a handler for battery info, and make a single request for it */
+ myClient->addHandler("physicalInfo", &myHandlePhysicalInfoCB);
+ myClient->requestOnce("physicalInfo");
+
+
+ /* Add a handler for battery info, and make a single request for it */
+ myClient->addHandler("batteryInfo", &myHandleBatteryInfoCB);
+ myClient->requestOnce("batteryInfo");
+
+ /* If it exists add a handler for temperature info, and make a
+ * single request for it */
+ if (myClient->dataExists("temperatureInfo"))
+ {
+ myClient->addHandler("temperatureInfo", &myHandleTemperatureInfoCB);
+ myClient->requestOnce("temperatureInfo");
+ }
+
+ // if we have the new way of broadcasting that only pushes strings
+ // when they change then use that
+ if (myClient->dataExists("updateNumbers") &&
+ myClient->dataExists("updateStrings"))
+ {
+ printf("Using new updates\n");
+ // get the numbers every 100 ms
+ myClient->addHandler("updateNumbers", &myHandleOutputNumbersCB);
+ myClient->request("updateNumbers", 100);
+ // and the strings whenever they change (and are broadcast)
+ myClient->addHandler("updateStrings", &myHandleOutputStringsCB);
+ myClient->request("updateStrings", -1);
+ }
+ else
+ {
+ printf("Using old updates\n");
+ // For the old way, just Add a handler for general info, and
+ // request it to be called every 100 ms
+ myClient->addHandler("update", &myHandleOutputCB);
+ myClient->request("update", 100);
+ }
+
+ if(myClient->dataExists("mapUpdated"))
+ {
+ myClient->addHandler("mapUpdated", &myHandleMapUpdatedCB);
+ myClient->request("mapUpdated", -1);
+ }
+}
+
+OutputHandler::~OutputHandler(void)
+{
+ /* Halt the request for data updates */
+ myClient->requestStop("update");
+}
+
+void OutputHandler::handleOutput(ArNetPacket *packet)
+{
+ /* Extract the data from the update packet. Its format is status and
+ * mode (null-terminated strings), then 6 doubles for battery voltage,
+ * x position, y position and orientation (theta) (from odometry), current
+ * translational velocity, and current rotational velocity. Translation is
+ * always milimeters, rotation in degrees.
+ */
+ memset(myStatus, 0, sizeof(myStatus));
+ memset(myMode, 0, sizeof(myMode));
+ packet->bufToStr(myStatus, sizeof(myStatus));
+ packet->bufToStr(myMode, sizeof(myMode));
+ myVoltage = ( (double) packet->bufToByte2() )/10.0;
+ myX = (double) packet->bufToByte4();
+ myY = (double) packet->bufToByte4();
+ myTh = (double) packet->bufToByte2();
+ myVel = (double) packet->bufToByte2();
+ myRotVel = (double) packet->bufToByte2();
+ myLatVel = (double) packet->bufToByte2();
+ myTemperature = (double) packet->bufToByte();
+
+ if(myNeedToPrintHeader)
+ {
+ printf("\n%6s|%6s|%6s|%6s|%6s|%6s|%4s|%6s|%15s|%20s|\n",
+ "x","y","theta", "vel", "rotVel", "latVel", "temp", myVoltageIsStateOfCharge ? "charge" : "volts", "mode","status");
+ fflush(stdout);
+ myNeedToPrintHeader = false;
+ }
+ if (myGotBatteryInfo)
+ printf("%6.0f|%6.0f|%6.1f|%6.0f|%6.0f|%6.0f|%4.0d|%6.1f|%15s|%20s|\r",
+ myX, myY, myTh, myVel, myRotVel, myLatVel, myTemperature, myVoltage, myMode, myStatus);
+
+ fflush(stdout);
+}
+
+void OutputHandler::handleOutputNumbers(ArNetPacket *packet)
+{
+ /* Extract the data from the updateNumbers packet. Its format is 6
+ * doubles for battery voltage, x position, y position and
+ * orientation (theta) (from odometry), current translational
+ * velocity, and current rotational velocity. Translation is always
+ * milimeters, rotation in degrees.
+ */
+ myVoltage = ( (double) packet->bufToByte2() )/10.0;
+ myX = (double) packet->bufToByte4();
+ myY = (double) packet->bufToByte4();
+ myTh = (double) packet->bufToByte2();
+ myVel = (double) packet->bufToByte2();
+ myRotVel = (double) packet->bufToByte2();
+ myLatVel = (double) packet->bufToByte2();
+ myTemperature = (double) packet->bufToByte();
+
+ if(myNeedToPrintHeader)
+ {
+ printf("\n%6s|%6s|%6s|%6s|%6s|%6s|%4s|%6s|%15s|%20s|\n",
+ "x","y","theta", "vel", "rotVel", "latVel", "temp", myVoltageIsStateOfCharge ? "charge" : "volts", "mode","status");
+ fflush(stdout);
+ myNeedToPrintHeader = false;
+ }
+ if (myGotBatteryInfo)
+ printf("%6.0f|%6.0f|%6.1f|%6.0f|%6.0f|%6.0f|%4.0d|%6.1f|%15s|%20s|\r",
+ myX, myY, myTh, myVel, myRotVel, myLatVel, myTemperature, myVoltage, myMode, myStatus);
+
+ fflush(stdout);
+}
+
+void OutputHandler::handleOutputStrings(ArNetPacket *packet)
+{
+ /* Extract the data from the updateStrings packet. Its format is
+ * status and mode (null-terminated strings).
+ */
+ memset(myStatus, 0, sizeof(myStatus));
+ memset(myMode, 0, sizeof(myMode));
+ packet->bufToStr(myStatus, sizeof(myStatus));
+ packet->bufToStr(myMode, sizeof(myMode));
+}
+
+void OutputHandler::handleBatteryInfo(ArNetPacket *packet)
+{
+ /* Get battery configuration parameters: when the robot will begin beeping and
+ * warning about low battery, and when it will automatically disconnect and
+ * shutdown. */
+ double lowBattery = packet->bufToDouble();
+ double shutdown = packet->bufToDouble();
+ printf("Low battery voltage: %6g Shutdown battery voltage: %6g\n", lowBattery, shutdown);
+ fflush(stdout);
+ myNeedToPrintHeader = true;
+ myGotBatteryInfo = true;
+
+ if (packet->getDataReadLength() == packet->getDataLength())
+ {
+ printf("Packet is too small so its an old server, though you could just get to the bufToUByte anyways, since it'd be 0 anyhow\n");
+ myVoltageIsStateOfCharge = false;
+ }
+ else
+ myVoltageIsStateOfCharge = (packet->bufToUByte() == 1);
+
+}
+
+
+void OutputHandler::handlePhysicalInfo(ArNetPacket *packet)
+{
+ /* Get phyiscal configuration parameters: */
+ char robotType[512];
+ char robotSubtype[512];
+ int width;
+ int lengthFront;
+ int lengthRear;
+
+ packet->bufToStr(robotType, sizeof(robotType));
+ packet->bufToStr(robotSubtype, sizeof(robotSubtype));
+ width = packet->bufToByte2();
+ lengthFront = packet->bufToByte2();
+ lengthRear = packet->bufToByte2();
+
+ printf("Type: %s Subtype: %s Width %d: LengthFront: %d LengthRear: %d\n",
+ robotType, robotSubtype, width, lengthFront, lengthRear);
+ fflush(stdout);
+}
+
+void OutputHandler::handleTemperatureInfo(ArNetPacket *packet)
+{
+ char warning = packet->bufToByte();
+ char shutdown = packet->bufToByte();
+ printf("High temperature warning: %4d High temperature shutdown: %4d\n", warning, shutdown);
+ fflush(stdout);
+ myNeedToPrintHeader = true;
+}
+
+void OutputHandler::handleMapUpdated(ArNetPacket *packet)
+{
+ printf("\nMap changed.\n");
+ fflush(stdout);
+ myNeedToPrintHeader = true;
+}
+
+
+/* Key handler for the escape key: shutdown all of Aria. */
+void escape(void)
+{
+ printf("esc pressed, shutting down aria\n");
+ Aria::shutdown();
+}
+
+int main(int argc, char **argv)
+{
+ /* Aria initialization: */
+ Aria::init();
+
+ //ArLog::init(ArLog::StdErr, ArLog::Verbose);
+
+
+ /* Create our client object. This is the object which connects with a remote
+ * server over the network, and which manages all of our communication with it
+ * once connected by sending data "requests". Requests may be sent once, or
+ * may be repeated at any frequency. Requests and replies to requsets contain
+ * payload "packets", into which various data types may be packed (when making a
+ * request), and from which they may also be extracted (when handling a reply).
+ * See the InputHandler and OutputHandler classes above for
+ * examples of making requests and reading/writing the data in packets.
+ */
+ ArClientBase client;
+
+ /* Aria components use this to get options off the command line: */
+ ArArgumentParser parser(&argc, argv);
+
+ /* This will be used to connect our client to the server, including
+ * various bits of handshaking (e.g. sending a password, retrieving a list
+ * of data requests and commands...)
+ * It will get the hostname from the -host command line argument: */
+ ArClientSimpleConnector clientConnector(&parser);
+
+ parser.loadDefaultArguments();
+
+ /* Check for -help, and unhandled arguments: */
+ if (!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed())
+ {
+ Aria::logOptions();
+ exit(0);
+ }
+
+
+ /* Connect our client object to the remote server: */
+ if (!clientConnector.connectClient(&client))
+ {
+ if (client.wasRejected())
+ printf("Server '%s' rejected connection, exiting\n", client.getHost());
+ else
+ printf("Could not connect to server '%s', exiting\n", client.getHost());
+ exit(1);
+ }
+
+ printf("Connected to server.\n");
+
+ client.setRobotName(client.getHost()); // include server name in log messages
+
+ /* Create a key handler and also tell Aria about it */
+ ArKeyHandler keyHandler;
+ Aria::setKeyHandler(&keyHandler);
+
+ /* Global escape-key handler to shut everythnig down */
+ ArGlobalFunctor escapeCB(&escape);
+ keyHandler.addKeyHandler(ArKeyHandler::ESCAPE, &escapeCB);
+
+ /* Now that we're connected, we can run the client in a background thread,
+ * sending requests and receiving replies. When a reply to a request arrives,
+ * or the server makes a request of the client, a handler functor is invoked.
+ * The handlers for this program are registered with the client by the
+ * InputHandler and OutputHandler classes (in their constructors, above) */
+ client.runAsync();
+
+ /* Create the InputHandler object and request safe-drive mode */
+ InputHandler inputHandler(&client, &keyHandler);
+ inputHandler.safeDrive();
+
+ /* Use ArClientBase::dataExists() to see if the "ratioDrive" request is available on the
+ * currently connected server. */
+ if(!client.dataExists("ratioDrive") )
+ printf("Warning: server does not have ratioDrive command, can not use drive commands!\n");
+ else
+ printf("Keys are:\nUP: Forward\nDOWN: Backward\nLEFT: Turn Left\nRIGHT: Turn Right\n");
+ printf("s: Enable safe drive mode (if supported).\nu: Disable safe drive mode (if supported).\nl: list all data requests on server\n\nDrive commands use 'ratioDrive'.\nt: logs the network tracking tersely\nv: logs the network tracking verbosely\nr: resets the network tracking\n\n");
+
+
+ /* Create the OutputHandler object. It will begin printing out data from the
+ * server. */
+ OutputHandler outputHandler(&client);
+
+
+ /* Begin capturing keys into the key handler. Callbacks will be called
+ * asyncrosously from this main thread when pressed. */
+
+ /* While the client is still running (getRunningWithLock locks the "running"
+ * flag until it returns), check keys on the key handler (which will call
+ * our callbacks), then tell the input handler to send drive commands.
+ * Sleep a fraction of a second as well to avoid using
+ * too much CPU time, and give other threads time to work.
+ */
+ while (client.getRunningWithLock())
+ {
+ keyHandler.checkKeys();
+ inputHandler.sendInput();
+ ArUtil::sleep(100);
+ }
+
+ /* The client stopped running, due to disconnection from the server, general
+ * Aria shutdown, or some other reason. */
+ client.disconnect();
+ Aria::shutdown();
+ return 0;
+}
diff --git a/Legacy/Aria/ArNetworking/examples/clientDemoStatic-vc2003.vcproj b/Legacy/Aria/ArNetworking/examples/clientDemoStatic-vc2003.vcproj
new file mode 100644
index 0000000..5ecefa7
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/clientDemoStatic-vc2003.vcproj
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/clientDemoStatic-vc2008.vcproj b/Legacy/Aria/ArNetworking/examples/clientDemoStatic-vc2008.vcproj
new file mode 100644
index 0000000..fa75c01
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/clientDemoStatic-vc2008.vcproj
@@ -0,0 +1,214 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/clientDemoStatic-vc2010.vcxproj b/Legacy/Aria/ArNetworking/examples/clientDemoStatic-vc2010.vcxproj
new file mode 100644
index 0000000..2912652
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/clientDemoStatic-vc2010.vcxproj
@@ -0,0 +1,146 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ clientDemoStatic
+ {0A8A179D-832B-44B2-829A-AB6E61BFF46E}
+ clientDemoStatic
+ ManagedCProj
+
+
+
+ Application
+ MultiByte
+ false
+
+
+ Application
+ MultiByte
+ false
+ v100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ ..\..\bin\
+ ../../obj/$(ProjectName)-$(Configuration)-VC10/
+ true
+ ..\..\bin\
+ ../../obj/$(ProjectName)-$(Configuration)-VC10/
+ false
+ clientDemoStaticDebugVC10
+ $(ProjectName)VC10
+
+
+
+ $(IntDir)$(ProjectName)BuildLog.htm
+
+
+ Disabled
+ ..\..\include;..\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;ARIA_STATIC;%(PreprocessorDefinitions)
+ false
+ Default
+ MultiThreadedDebug
+ false
+
+
+ Level3
+ ProgramDatabase
+ true
+
+
+ false
+
+
+ ArNetworkingStaticDebugVC10.lib;AriaStaticDebugVC10.lib;ws2_32.lib;winmm.lib;advapi32.lib
+ $(OutDir)$(TargetFileName)
+ true
+ ..\..\lib;%(AdditionalLibraryDirectories)
+ %(IgnoreSpecificDefaultLibraries)
+ true
+ true
+ false
+
+
+ NotSet
+
+
+
+
+ $(IntDir)$(ProjectName)BuildLog.htm
+
+
+ AnySuitable
+ true
+ ..\..\include;..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;ARIA_STATIC;%(PreprocessorDefinitions)
+ false
+ MultiThreaded
+ false
+ true
+
+
+ Level3
+ ProgramDatabase
+ true
+
+
+ false
+
+
+ ArNetworkingStaticVC10.lib;AriaStaticVC10.lib;winmm.lib;ws2_32.lib;advapi32.lib;%(AdditionalDependencies)
+ $(OutDir)$(TargetFileName)
+ true
+ ..\..\lib;%(AdditionalLibraryDirectories)
+ %(IgnoreSpecificDefaultLibraries)
+ false
+ false
+
+
+
+
+ NotSet
+
+
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Legacy/Aria/ArNetworking/examples/configClient.cpp b/Legacy/Aria/ArNetworking/examples/configClient.cpp
new file mode 100644
index 0000000..453fb2f
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/configClient.cpp
@@ -0,0 +1,66 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+
+ArClientBase *client;
+ArClientHandlerConfig *configHandler;
+bool done = false;
+
+void gotConfig(void)
+{
+ ArConfig *newConfig;
+ done = true;
+ configHandler->getConfig()->writeFile("configClient.txt");
+ newConfig = new ArConfig(*(configHandler->getConfig()));
+ newConfig->writeFile("configClientNew.txt");
+}
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ ArGlobalFunctor gotConfigCB(&gotConfig);
+ std::string hostname;
+
+ client = new ArClientBase;
+ configHandler = new ArClientHandlerConfig(client);
+
+ configHandler->addGotConfigCB(&gotConfigCB);
+
+ ArArgumentParser parser(&argc, argv);
+
+ ArClientSimpleConnector clientConnector(&parser);
+
+ parser.loadDefaultArguments();
+
+ /* Check for -help, and unhandled arguments: */
+ if (!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed())
+ {
+ Aria::logOptions();
+ exit(0);
+ }
+ /* Connect our client object to the remote server: */
+ if (!clientConnector.connectClient(client))
+ {
+ exit(1);
+ }
+
+ client->setRobotName(client->getHost()); // include server hostname in log messages
+
+ configHandler->requestConfigFromServer();
+ client->runAsync();
+
+ while (!done)
+ ArUtil::sleep(100);
+
+ if (configHandler->canRequestDefaults())
+ {
+ configHandler->requestDefaultConfigFromServer();
+ while (!configHandler->haveGottenDefaults())
+ ArUtil::sleep(100);
+ printf("%d\n", configHandler->haveGottenDefaults());
+ configHandler->getDefaultConfig()->writeFile("configClientDefaults.txt");
+ printf("wrote defaults\n");
+ }
+
+
+ Aria::exit(0);
+}
diff --git a/Legacy/Aria/ArNetworking/examples/configClientToServer.cpp b/Legacy/Aria/ArNetworking/examples/configClientToServer.cpp
new file mode 100644
index 0000000..3d19828
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/configClientToServer.cpp
@@ -0,0 +1,82 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+
+/*
+ Pass this a file to send to the server (should be made by configClient then modified).
+
+ Takes a file to send, and can take the host to send to too
+
+ */
+
+ArClientBase *client;
+ArClientHandlerConfig *configHandler;
+
+char *file;
+
+void saveConfigSucceeded(void)
+{
+ printf("HERE: Save config succeeded\n");
+}
+
+void saveConfigFailed(const char *str)
+{
+ printf("HERE: Save config failed: %s\n", str);
+}
+
+void gotConfig(void)
+{
+ char errorBuffer[1024];
+ ArConfig *newConfig;
+ if (!configHandler->getConfig()->parseFile(file, false, false, errorBuffer,
+ sizeof(errorBuffer)))
+ printf("Error loading file: %s\n", errorBuffer);
+
+ configHandler->saveConfigToServer();
+ client->loopOnce();
+ ArUtil::sleep(1000);
+ client->loopOnce();
+ ArUtil::sleep(1000);
+ client->disconnect();
+ Aria::shutdown();
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ //ArLog::init(ArLog::StdOut, ArLog::Verbose);
+ ArGlobalFunctor gotConfigCB(&gotConfig);
+ ArGlobalFunctor saveConfigSucceededCB(&saveConfigSucceeded);
+ ArGlobalFunctor1 saveConfigFailedCB(&saveConfigFailed);
+ std::string hostname;
+
+ client = new ArClientBase;
+ configHandler = new ArClientHandlerConfig(client, true);
+
+ configHandler->addGotConfigCB(&gotConfigCB);
+ configHandler->addSaveConfigSucceededCB(&saveConfigSucceededCB);
+ configHandler->addSaveConfigFailedCB(&saveConfigFailedCB);
+
+ if (argc == 1)
+ {
+ printf("Usage: %s \n", argv[0]);
+ exit(1);
+ }
+ file = argv[1];
+ if (argc == 2)
+ hostname = "localhost";
+ else
+ hostname = argv[2];
+
+
+ if (!client->blockingConnect(hostname.c_str(), 7272))
+ {
+ printf("Could not connect to server, exiting\n");
+ exit(1);
+ }
+ //client->requestOnce("setConfig");
+ configHandler->requestConfigFromServer();
+ //client->requestOnce("setConfig");
+ client->run();
+ return 0;
+}
diff --git a/Legacy/Aria/ArNetworking/examples/configServer.cpp b/Legacy/Aria/ArNetworking/examples/configServer.cpp
new file mode 100644
index 0000000..ac858ca
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/configServer.cpp
@@ -0,0 +1,61 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ ArServerBase server;
+
+ ArConfig *config;
+ config = Aria::getConfig();
+ std::string section;
+ char joy[512];
+ sprintf(joy, "Joy");
+ section = "section1";
+ config->addParam(ArConfigArg("int", new int, "fun int", 0), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("double", new double, "fun double", 0, 1), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("bool", new bool, "fun bool"), section.c_str(), ArPriority::IMPORTANT);
+ config->addParam(ArConfigArg("string", joy, "fun string", sizeof(joy)), section.c_str(), ArPriority::TRIVIAL);
+ section = "section8";
+ config->addParam(ArConfigArg("int", new int, "fun int", 0), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("double", new double, "fun double", 0, 1), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("doubleFOUR", (double).4, "fun double", 0.0, 1.0), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("double three", new double, "fun double", 0, 1), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("double two", new double, "fun double", 0, 1), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("double one", new double, "fun double", 0, 1), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("double", new double, "fun double", 0, 1), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("bool", new bool, "fun bool"), section.c_str(), ArPriority::IMPORTANT);
+ config->addParam(ArConfigArg("string", joy, "fun string", sizeof(joy)), section.c_str(), ArPriority::TRIVIAL);
+ section = "some section";
+ config->setSectionComment("some section", "this is a random section with 4 ints");
+ config->addParam(ArConfigArg("int1", new int, "fun int"), section.c_str(), ArPriority::TRIVIAL);
+ config->addParam(ArConfigArg("int2", new int, "fun int", -1, 1200), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("int3", new int, "fun int"), section.c_str(), ArPriority::IMPORTANT);
+ config->addParam(ArConfigArg("int4", new int, "fun int"), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("int4", new int, "fun int"), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("int1", new int, "fun int"), section.c_str(), ArPriority::TRIVIAL);
+ section = "another section";
+ config->setSectionComment("another section", "this is another section with 1 of each type");
+ config->addParam(ArConfigArg("inta", new int, "fun int"), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("doublea", new double, "fun double"), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("boola", new bool, "fun bool"), section.c_str(), ArPriority::NORMAL);
+ config->addParam(ArConfigArg("stringa", new char[512], "fun string", 512), section.c_str(), ArPriority::NORMAL);
+
+ if (!server.open(7272))
+ {
+ printf("Could not open server port\n");
+ exit(1);
+ }
+ config->setBaseDirectory("./");
+ config->writeFile("default.txt");
+ config->parseFile("modified.txt");
+ config->writeFile("modifiedModified.txt");
+ ArServerHandlerConfig configHandler(&server, Aria::getConfig(),
+ "default.txt");
+
+ server.run();
+
+ Aria::shutdown();
+
+ return 0;
+}
diff --git a/Legacy/Aria/ArNetworking/examples/configServerRobot.cpp b/Legacy/Aria/ArNetworking/examples/configServerRobot.cpp
new file mode 100644
index 0000000..60d0036
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/configServerRobot.cpp
@@ -0,0 +1,30 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ ArServerBase server;
+
+ //ArLog::init(ArLog::StdOut, ArLog::Verbose);
+ ArConfig *config;
+ config = Aria::getConfig();
+
+ ArRobotP3DX dx;
+ //dx.writeFile("dx.txt");
+ *Aria::getConfig() = dx;
+ //Aria::getConfig()->writeFile("dxcopy.txt");
+
+ if (!server.open(7272))
+ {
+ printf("Could not open server port\n");
+ exit(1);
+ }
+
+ ArServerHandlerConfig configHandler(&server, Aria::getConfig());
+ server.run();
+
+ Aria::shutdown();
+
+ return 0;
+}
diff --git a/Legacy/Aria/ArNetworking/examples/drawingsExample.cpp b/Legacy/Aria/ArNetworking/examples/drawingsExample.cpp
new file mode 100644
index 0000000..9486158
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/drawingsExample.cpp
@@ -0,0 +1,287 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+#include
+
+
+/** @example drawingsExample.cpp Example showing how to draw custom graphics in
+ * clients such as MobileEyes
+ *
+ * This is an example server that shows how to draw arbitrary figures in a
+ * client (e.g. MobileEyes) via ArServerInfoDrawings. It draws some lines, "arrows", and moving dots
+ * with various sizes and colors. You can use these drawings for debugging
+ * or visualization, for example, to represent sensor readings. In fact,
+ * specific support for ArRobot, ArSick, ArSonarDevice, ArIRs and ArBumpers
+ * are built in to ArServerInfoDrawings: see drawingsExampleWithRobot.cpp
+ * or serverDemo.cpp.
+ *
+ * @sa drawingsExampleWithRobot.cpp
+ */
+
+
+/* These are some callbacks that respond to client requests for the drawings'
+ * geometry data. */
+void exampleHomeDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt);
+void exampleDotsDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt);
+void exampleXDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt);
+void exampleArrowsDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt);
+
+
+/* This class shows how to encapsulate the various aspects of a drawing into one
+ * object that other parts of the program can easily access in a more general
+ * (and thread-safe) way. It lets you change position, radius, resolution
+ * (number of dots), and dot drawing properties.
+ * The default radius is 1 meter and the default number of points is 360.
+ *
+ * In this example program, the radius is updated periodically by a loop in the
+ * main thread (see main() function), while ArNetworking requests are handled
+ * in the separate ArNetworking server thread, calling drawingServerCB() callback (this is
+ * registered with the server when we register the drawing with the
+ * ArServerInfoDrawings object). So note the use of an ArMutex object to
+ * control this asyrchronous access to the reply packet.
+ */
+class Circle
+{
+private:
+ ArNetPacket myReply;
+ ArMutex myMutex; // mutex around myReply
+ ArPose myPos;
+ double myRadius;
+ unsigned int myNumPoints;
+ void drawingServerCB(ArServerClient *client, ArNetPacket *pkt);
+ ArFunctor2C callback;
+ void regenerate();
+public:
+ Circle(ArServerInfoDrawings *drawingsServer, const std::string& name, ArDrawingData *drawData);
+ ~Circle();
+
+ void setPos(const ArPose& p)
+ {
+ myPos = p;
+ regenerate();
+ }
+
+ void setRadius(double r)
+ {
+ myRadius = r;
+ regenerate();
+ }
+
+ void setNumPoints(unsigned int r)
+ {
+ myNumPoints = r;
+ regenerate();
+ }
+
+};
+
+Circle::Circle(ArServerInfoDrawings *drawingsServer, const std::string& name, ArDrawingData* drawData) :
+ myRadius(1000.0),
+ myNumPoints(360),
+ callback(this, &Circle::drawingServerCB)
+{
+ drawingsServer->addDrawing(drawData, name.c_str(), &callback);
+}
+
+Circle::~Circle()
+{
+ // TODO remove drawing from the server, but not implemented yet
+}
+
+void Circle::drawingServerCB(ArServerClient *client, ArNetPacket *pkt)
+{
+ myMutex.lock();
+ client->sendPacketUdp(&myReply);
+ myMutex.unlock();
+}
+
+// Method called by accessor methods when properties changed. This reconstructs
+// the myReply packet sent in response to requests from clients
+void Circle::regenerate()
+{
+ myMutex.lock();
+ myReply.empty();
+ myReply.byte4ToBuf(myNumPoints);
+ double a = 360.0/myNumPoints;
+ for(unsigned int i = 0; i < myNumPoints; ++i)
+ {
+ myReply.byte4ToBuf(ArMath::roundInt(myPos.getX()+ArMath::cos(i*a)*myRadius)); // X
+ myReply.byte4ToBuf(ArMath::roundInt(myPos.getY()+ArMath::sin(i*a)*myRadius)); // Y
+ }
+ myMutex.unlock();
+}
+
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ ArServerBase server;
+
+ ArArgumentParser parser(&argc, argv);
+ ArServerSimpleOpener simpleOpener(&parser);
+
+ // parse the command line... fail and print the help if the parsing fails
+ // or if help was requested
+ parser.loadDefaultArguments();
+ if (!simpleOpener.parseArgs() || !parser.checkHelpAndWarnUnparsed())
+ {
+ simpleOpener.logOptions();
+ exit(1);
+ }
+
+
+ // first open the server up
+ if (!simpleOpener.open(&server))
+ {
+ if (simpleOpener.wasUserFileBad())
+ printf("Error: Bad user/password/permissions file.\n");
+ else
+ printf("Error: Could not open server port. Use -help to see options.\n");
+ exit(1);
+ }
+
+
+ // This is the service that provides drawing data to the client.
+ ArServerInfoDrawings drawings(&server);
+
+ // Add our custom drawings
+ drawings.addDrawing(
+ // shape: color: size: layer:
+ new ArDrawingData("polyLine", ArColor(255, 0, 0), 2, 49),
+ "exampleDrawing_Home",
+ new ArGlobalFunctor2(&exampleHomeDrawingNetCallback)
+ );
+ drawings.addDrawing(
+ new ArDrawingData("polyDots", ArColor(0, 255, 0), 250, 48),
+ "exampleDrawing_Dots",
+ new ArGlobalFunctor2(&exampleDotsDrawingNetCallback)
+ );
+ drawings.addDrawing(
+ new ArDrawingData("polySegments", ArColor(0, 0, 0), 4, 52),
+ "exampleDrawing_XMarksTheSpot",
+ new ArGlobalFunctor2(&exampleXDrawingNetCallback)
+ );
+ drawings.addDrawing(
+ new ArDrawingData("polyArrows", ArColor(255, 0, 255), 500, 100),
+ "exampleDrawing_Arrows",
+ new ArGlobalFunctor2(&exampleArrowsDrawingNetCallback)
+ );
+
+ Circle circle(&drawings, "exampleDrawing_circle",
+ new ArDrawingData("polySegments", ArColor(255, 150, 0), 3, 120));
+ circle.setPos(ArPose(0, -5000));
+ circle.setRadius(1000);
+ circle.setNumPoints(360);
+
+ // log whatever we wanted to before the runAsync
+ simpleOpener.checkAndLog();
+
+ // run the server thread in the background
+ server.runAsync();
+
+ printf("Server is now running...\n");
+
+
+ // Add a key handler mostly that windows can exit by pressing
+ // escape, note that the key handler prevents you from running this program
+ // in the background on Linux.
+ ArKeyHandler *keyHandler;
+ if ((keyHandler = Aria::getKeyHandler()) == NULL)
+ {
+ keyHandler = new ArKeyHandler;
+ Aria::setKeyHandler(keyHandler);
+ printf("To exit, press escape.\n");
+ }
+
+
+ double circleRadius = 1000;
+ while(true)
+ {
+ ArUtil::sleep(100);
+ circleRadius += 50;
+ if(circleRadius > 5000)
+ circleRadius = 0;
+ circle.setRadius(circleRadius);
+ }
+
+ Aria::shutdown();
+ exit(0);
+}
+
+
+
+
+// Network callbacks for drawings' current geometry data:
+
+void exampleHomeDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt) {
+ ArNetPacket reply;
+
+ // 7 Vertices
+ reply.byte4ToBuf(7);
+
+ // Centered on 0,0.
+ // X: Y:
+ reply.byte4ToBuf(-500); reply.byte4ToBuf(500); // Vertex 1
+ reply.byte4ToBuf(-500); reply.byte4ToBuf(-500); // Vertex 2
+ reply.byte4ToBuf(500); reply.byte4ToBuf(-500); // Vertex 3
+ reply.byte4ToBuf(500); reply.byte4ToBuf(500); // Vertex 4
+ reply.byte4ToBuf(0); reply.byte4ToBuf(1000); // Vertex 5
+ reply.byte4ToBuf(-500); reply.byte4ToBuf(500); // Vertex 6
+ reply.byte4ToBuf(500); reply.byte4ToBuf(500); // Vertex 7
+
+ client->sendPacketUdp(&reply);
+}
+
+void exampleDotsDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt) {
+ ArNetPacket reply;
+
+ unsigned int tik = ArUtil::getTime() % 200;
+ double t = tik / 5.0;
+
+ // Three dots
+ reply.byte4ToBuf(3);
+
+ // Dot 1:
+ reply.byte4ToBuf(3000); // X coordinate (mm)
+ reply.byte4ToBuf((int) (sin(t) * 1000));// Y
+
+ // Dot 2:
+ reply.byte4ToBuf(3500); // X
+ reply.byte4ToBuf((int) (sin(t+500) * 1000));// Y
+
+ // Dot 3:
+ reply.byte4ToBuf(4000); // X
+ reply.byte4ToBuf((int) (sin(t+1000) * 1000));// Y
+
+ client->sendPacketUdp(&reply);
+}
+
+void exampleXDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt) {
+ ArNetPacket reply;
+
+ // X marks the spot. 2 line segments, so 4 vertices:
+ reply.byte4ToBuf(4);
+
+ // Segment 1:
+ reply.byte4ToBuf(-4250); // X1
+ reply.byte4ToBuf(250); // Y1
+ reply.byte4ToBuf(-3750); // X2
+ reply.byte4ToBuf(-250); // Y2
+
+ // Segment 2:
+ reply.byte4ToBuf(-4250); // X1
+ reply.byte4ToBuf(-250); // Y1
+ reply.byte4ToBuf(-3750); // X2
+ reply.byte4ToBuf(250); // Y2
+
+ client->sendPacketUdp(&reply);
+}
+
+void exampleArrowsDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt) {
+ // 1 Arrow that points at the robot
+ ArNetPacket reply;
+ reply.byte4ToBuf(1);
+ reply.byte4ToBuf(0); // Pos. X
+ reply.byte4ToBuf(700); // Pos. Y
+ client->sendPacketUdp(&reply);
+}
+
diff --git a/Legacy/Aria/ArNetworking/examples/drawingsExampleWithRobot.cpp b/Legacy/Aria/ArNetworking/examples/drawingsExampleWithRobot.cpp
new file mode 100644
index 0000000..49525de
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/drawingsExampleWithRobot.cpp
@@ -0,0 +1,256 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+#include
+
+/** @example drawingsExampleWithRobot.cpp Example showing how to draw custom
+ * graphics in clients such as MobileEyes, and enable drawing of sensor
+ * readings as well.
+ *
+ * This is an example server that shows how to draw arbitrary figures in a
+ * client (e.g. MobileEyes). It also uses the convenient built-in
+ * support for visualization built in to ArRobot, ArSick, ArSonarDevice,
+ * etc.
+ *
+ * @sa drawingsExample.cpp which does not include robot and sensor drawings
+ */
+
+/* These are callbacks that respond to client requests for the drawings'
+ * geometry data. */
+void exampleHomeDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt);
+void exampleDotsDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt);
+void exampleXDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt);
+void exampleArrowsDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt);
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ ArRobot robot;
+ ArServerBase server;
+
+ ArArgumentParser parser(&argc, argv);
+ ArSimpleConnector simpleConnector(&parser);
+ ArServerSimpleOpener simpleOpener(&parser);
+
+
+ // parse the command line... fail and print the help if the parsing fails
+ // or if help was requested
+ parser.loadDefaultArguments();
+ if (!simpleConnector.parseArgs() || !simpleOpener.parseArgs() ||
+ !parser.checkHelpAndWarnUnparsed())
+ {
+ simpleConnector.logOptions();
+ simpleOpener.logOptions();
+ exit(1);
+ }
+
+ // Set up where we'll look for files such as config file, user/password file,
+ // etc.
+ char fileDir[1024];
+ ArUtil::addDirectories(fileDir, sizeof(fileDir), Aria::getDirectory(),
+ "ArNetworking/examples");
+
+ // first open the server up
+ if (!simpleOpener.open(&server, fileDir, 240))
+ {
+ if (simpleOpener.wasUserFileBad())
+ printf("Error: Bad user/password/permissions file.\n");
+ else
+ printf("Error: Could not open server port. Use -help to see options.\n");
+ exit(1);
+ }
+
+
+ // Devices
+ ArAnalogGyro gyro(&robot);
+
+ ArSonarDevice sonarDev;
+ robot.addRangeDevice(&sonarDev);
+
+ ArIRs irs;
+ robot.addRangeDevice(&irs);
+
+ ArBumpers bumpers;
+ robot.addRangeDevice(&bumpers);
+
+ ArSick sick(361, 180);
+ robot.addRangeDevice(&sick);
+
+
+ ArServerInfoRobot serverInfoRobot(&server, &robot);
+ ArServerInfoSensor serverInfoSensor(&server, &robot);
+
+ // This is the service that provides drawing data to the client.
+ ArServerInfoDrawings drawings(&server);
+
+ // Convenience function that sets up drawings for all the robot's current
+ // range devices (using default shape and color info)
+ drawings.addRobotsRangeDevices(&robot);
+
+ // Add our custom drawings
+ drawings.addDrawing(
+ // shape: color: size: layer:
+ new ArDrawingData("polyLine", ArColor(255, 0, 0), 2, 49),
+ "exampleDrawing_Home",
+ new ArGlobalFunctor2(&exampleHomeDrawingNetCallback)
+ );
+ drawings.addDrawing(
+ new ArDrawingData("polyDots", ArColor(0, 255, 0), 250, 48),
+ "exampleDrawing_Dots",
+ new ArGlobalFunctor2(&exampleDotsDrawingNetCallback)
+ );
+ drawings.addDrawing(
+ new ArDrawingData("polySegments", ArColor(0, 0, 0), 4, 52),
+ "exampleDrawing_XMarksTheSpot",
+ new ArGlobalFunctor2(&exampleXDrawingNetCallback)
+ );
+ drawings.addDrawing(
+ new ArDrawingData("polyArrows", ArColor(255, 0, 255), 500, 100),
+ "exampleDrawing_Arrows",
+ new ArGlobalFunctor2(&exampleArrowsDrawingNetCallback)
+ );
+
+ // modes for moving the robot
+ ArServerModeStop modeStop(&server, &robot);
+ ArServerModeDrive modeDrive(&server, &robot);
+ ArServerModeRatioDrive modeRatioDrive(&server, &robot);
+ ArServerModeWander modeWander(&server, &robot);
+ modeStop.addAsDefaultMode();
+ modeStop.activate();
+
+
+
+ // Connect to the robot.
+ if (!simpleConnector.connectRobot(&robot))
+ {
+ printf("Error: Could not connect to robot... exiting\n");
+ Aria::shutdown();
+ return 1;
+ }
+
+ // set up the laser before handing it to the laser mode
+ simpleConnector.setupLaser(&sick);
+
+ robot.enableMotors();
+
+ // start the robot cycle running in a background thread
+ robot.runAsync(true);
+
+ // start the laser processing cycle in a background thread
+ sick.runAsync();
+
+ // connect the laser if it was requested
+ if (!simpleConnector.connectLaser(&sick))
+ {
+ printf("Error: Could not connect to laser... exiting\n");
+ Aria::shutdown();
+ return 1;
+ }
+
+ // log whatever we wanted to before the runAsync
+ simpleOpener.checkAndLog();
+
+ // run the server thread in the background
+ server.runAsync();
+
+ printf("Server is now running...\n");
+
+
+ // Add a key handler mostly that windows can exit by pressing
+ // escape, note that the key handler prevents you from running this program
+ // in the background on Linux.
+ ArKeyHandler *keyHandler;
+ if ((keyHandler = Aria::getKeyHandler()) == NULL)
+ {
+ keyHandler = new ArKeyHandler;
+ Aria::setKeyHandler(keyHandler);
+ robot.lock();
+ robot.attachKeyHandler(keyHandler);
+ robot.unlock();
+ printf("To exit, press escape.\n");
+ }
+
+ robot.waitForRunExit();
+
+
+ Aria::shutdown();
+ exit(0);
+}
+
+
+
+
+// Network callbacks for drawings' current geometry data:
+
+void exampleHomeDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt) {
+ ArNetPacket reply;
+
+ // 7 Vertices
+ reply.byte4ToBuf(7);
+
+ // Centered on 0,0.
+ // X: Y:
+ reply.byte4ToBuf(-500); reply.byte4ToBuf(500); // Vertex 1
+ reply.byte4ToBuf(-500); reply.byte4ToBuf(-500); // Vertex 2
+ reply.byte4ToBuf(500); reply.byte4ToBuf(-500); // Vertex 3
+ reply.byte4ToBuf(500); reply.byte4ToBuf(500); // Vertex 4
+ reply.byte4ToBuf(0); reply.byte4ToBuf(1000); // Vertex 5
+ reply.byte4ToBuf(-500); reply.byte4ToBuf(500); // Vertex 6
+ reply.byte4ToBuf(500); reply.byte4ToBuf(500); // Vertex 7
+
+ client->sendPacketUdp(&reply);
+}
+
+void exampleDotsDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt) {
+ ArNetPacket reply;
+
+ unsigned int tik = ArUtil::getTime() % 200;
+ double t = tik / 5.0;
+
+ // Three dots
+ reply.byte4ToBuf(3);
+
+ // Dot 1:
+ reply.byte4ToBuf(3000); // X coordinate (mm)
+ reply.byte4ToBuf((int) (sin(t) * 1000));// Y
+
+ // Dot 2:
+ reply.byte4ToBuf(3500); // X
+ reply.byte4ToBuf((int) (sin(t+500) * 1000));// Y
+
+ // Dot 3:
+ reply.byte4ToBuf(4000); // X
+ reply.byte4ToBuf((int) (sin(t+1000) * 1000));// Y
+
+ client->sendPacketUdp(&reply);
+}
+
+void exampleXDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt) {
+ ArNetPacket reply;
+
+ // X marks the spot. 2 line segments, so 4 vertices:
+ reply.byte4ToBuf(4);
+
+ // Segment 1:
+ reply.byte4ToBuf(-4250); // X1
+ reply.byte4ToBuf(250); // Y1
+ reply.byte4ToBuf(-3750); // X2
+ reply.byte4ToBuf(-250); // Y2
+
+ // Segment 2:
+ reply.byte4ToBuf(-4250); // X1
+ reply.byte4ToBuf(-250); // Y1
+ reply.byte4ToBuf(-3750); // X2
+ reply.byte4ToBuf(250); // Y2
+
+ client->sendPacketUdp(&reply);
+}
+
+void exampleArrowsDrawingNetCallback(ArServerClient* client, ArNetPacket* requestPkt) {
+ // 1 Arrow that points at the robot
+ ArNetPacket reply;
+ reply.byte4ToBuf(1);
+ reply.byte4ToBuf(0); // Pos. X
+ reply.byte4ToBuf(700); // Pos. Y
+ client->sendPacketUdp(&reply);
+}
+
diff --git a/Legacy/Aria/ArNetworking/examples/getVideoExample.cpp b/Legacy/Aria/ArNetworking/examples/getVideoExample.cpp
new file mode 100644
index 0000000..e7e65f9
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/getVideoExample.cpp
@@ -0,0 +1,164 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+
+/** @example getVideoExample.cpp
+ *
+ * This example client requests video images from the server
+ * and saves them repeatedly to a file named "video.jpg", or
+ * to a series of files ("video1.jpg", "video2.jpg", etc.) if
+ * you give the -counter option. Give the image request rate
+ * in images per second with the -rate option (or use -1 to let
+ * the server decide when to send image; may not work with all servers).
+ *
+ * Connect to SAVserver, ACTS, or another video server to get
+ * images.
+ *
+ * To make a movie from the images, you can use ffmpeg on Linux.
+ * First run with frame rate and counter options to save multiple images:
+ * ./getVideoExample -host robothost -port 7272 -rate 20 -counter
+ * Then use ffmpeg:
+ * ffmpeg -i video%d.jpeg -r 20 movie.mpeg
+ * See ffmpeg -h for full list of options.
+ */
+
+
+bool useCounter = false;
+unsigned long counter = 1;
+
+double rate = 0;
+int rateAsTime = 0;
+
+void jpegHandler(ArNetPacket *packet)
+{
+ unsigned int width;
+ unsigned int height;
+ static unsigned char jpeg[50000];
+ int jpegSize;
+ FILE *file;
+
+ width = packet->bufToUByte2();
+ height = packet->bufToUByte2();
+ jpegSize = packet->getDataLength() - packet->getDataReadLength();
+ if(jpegSize > 50000)
+ {
+ ArLog::log(ArLog::Normal, "Cannot save image, it's too big. (image is %d bytes, my buffer is 50000 bytes)", jpegSize);
+ return;
+ }
+ packet->bufToData((char *)jpeg, jpegSize);
+ char filename[128];
+ char tmpFilename[128];
+ sprintf(tmpFilename, "tmp.jpg");
+ if ((file = ArUtil::fopen(tmpFilename, "wb")) != NULL)
+ {
+ fwrite(jpeg, jpegSize, 1, file);
+ fclose(file);
+ if(useCounter)
+ snprintf(filename, 64, "video%lu.jpg", counter++);
+ else
+ strcpy(filename, "video.jpg");
+#ifdef WIN32
+ // On windows, rename() fails if the new file already exists
+ unlink(filename);
+#endif
+ if (rename(tmpFilename, filename) == 0)
+ ArLog::log(ArLog::Normal, "Wrote a %dx%d image, %d bytes, named %s.", width, height, jpegSize, filename);
+ else
+ ArLog::log(ArLog::Normal, "Wrote a %dx%d image, %d bytes, named %s (could not rename to real name).", width, height, jpegSize, tmpFilename);
+ }
+ else
+ ArLog::log(ArLog::Normal, "Could not write temp file %s", tmpFilename);
+
+ if (rate == 0 || rateAsTime == 0)
+ {
+ ArLog::log(ArLog::Normal, "Only one frame was requested, so exiting");
+ Aria::exit(0);
+ }
+}
+
+int main(int argc, char **argv)
+{
+
+#ifndef WIN32
+ ArDaemonizer daemonizer(&argc, argv, false);
+ bool isDaemonized = false;
+ if (!daemonizer.daemonize())
+ {
+ ArLog::log(ArLog::Terse, "Could not daemonize process");
+ exit(1);
+ }
+ if (daemonizer.isDaemonized())
+ isDaemonized = true;
+#endif
+
+ Aria::init();
+ ArLog::init(ArLog::File, ArLog::Normal, "getVideoLog.txt", true, true, true);
+
+ ArArgumentParser argParser(&argc, argv);
+ argParser.loadDefaultArguments();
+
+ ArClientSimpleConnector clientConnector(&argParser);
+
+ if(argParser.checkParameterArgumentDouble("-rate", &rate) && rate != 0.0)
+ {
+ if(rate == -1)
+ rateAsTime = -1;
+ else
+ rateAsTime = ArMath::roundInt(1000.0 / rate);
+ }
+
+ useCounter = argParser.checkArgument("-counter");
+
+ if(!Aria::parseArgs() || !argParser.checkHelpAndWarnUnparsed())
+ {
+ Aria::logOptions();
+ ArLog::log(ArLog::Terse, "\n\n%s options:\n-rate (If this isn't given, then the program will take one frame then exit, note that it is a double (so you can do .5 to do one frame per 2 seconds) and that if you set it to be too fast you'll saturate the robot's bandwidth and make it useless)\n-counter (default no)\n", argv[0]);
+
+ ArLog::log(ArLog::Terse, "\n\nNotes:\nThis program saves the images as video.jpg if you aren't using a counter, or video.jpg if you are using the counter.\nIt puts its logs into getVideoLog.txt, and overwrites it whenever it runs\n");
+
+ return 1;
+ }
+
+
+
+ ArClientBase client;
+ if (!clientConnector.connectClient(&client))
+ {
+ ArLog::log(ArLog::Normal, "Could not connect to server, exiting\n");
+ exit(1);
+ }
+
+ ArGlobalFunctor1 jpegHandlerCB(&jpegHandler);
+
+ if(client.dataExists("getPictureCam1"))
+ {
+ ArLog::log(ArLog::Normal, "Requesting images using \"getPictureCam1\" request.");
+ client.addHandler("getPictureCam1", &jpegHandlerCB);
+ if (rate != 0 && rateAsTime != 0)
+ client.request("getPictureCam1", rateAsTime);
+ else
+ client.requestOnce("getPictureCam1");
+ }
+ else if(client.dataExists("sendVideo"))
+ {
+ ArLog::log(ArLog::Normal, "Server does not have \"getPictureCam1\" request, requesting images using old \"sendVideo\" request.");
+ client.addHandler("sendVideo", &jpegHandlerCB);
+ if (rate != 0 && rateAsTime != 0)
+ client.request("sendVideo", rateAsTime);
+ else
+ client.requestOnce("sendVideo");
+ }
+ else
+ {
+ ArLog::log(ArLog::Terse, "Error: Server does not have \"getPictureCam1\" or \"sendVideo\" request, cannot request images.");
+ Aria::exit(2);
+ }
+
+
+ client.run();
+
+ Aria::shutdown();
+ return 0;
+}
+
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/popupExample.cpp b/Legacy/Aria/ArNetworking/examples/popupExample.cpp
new file mode 100644
index 0000000..fa8cc14
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/popupExample.cpp
@@ -0,0 +1,189 @@
+
+#include "Aria.h"
+#include "ArNetworking.h"
+
+/** @example popupExample.cpp Shows how to create popup windows in a client like MobileEyes
+ *
+ * This example server program connects to a robot, and sends a message to clients (e.g. MobileEyes) to display
+ * in a dialog box when a sensor reading is detected in front of the robot
+ * within 1 meter. It also checks to see if that obstacle is not at the same
+ * angle as the previous detected obstacle -- it's probably the same one,
+ * unmoved -- to avoid sending repeated popups. The popup offers three choices,
+ * acknowlege and do nothing, turn the robot around 180 degrees, or exit the server.
+ */
+
+
+class SensorDetectPopup
+{
+public:
+ SensorDetectPopup(ArRobot *robot, ArServerHandlerPopup *popupServer);
+protected:
+ ArRobot *myRobot;
+ ArServerHandlerPopup *myPopupServer;
+ bool myPopupDisplayed;
+ double myPrevObstacleAngle;
+ bool myPrevObstacleAngleValid;
+ ArFunctor2C *myPopupClosedCB;
+
+ void popupClosed(ArTypes::Byte4 popupID, int button);
+ void sensorTask(void) ;
+};
+
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ ArRobot robot;
+ ArSonarDevice sonar;
+ ArSick sick;
+ robot.addRangeDevice(&sonar);
+ ArServerBase server;
+
+ // Argument parser:
+ ArArgumentParser parser(&argc, argv);
+ parser.loadDefaultArguments();
+
+ // Connector and server opener:
+ ArRobotConnector robotConnector(&parser, &robot);
+ if(!robotConnector.connectRobot())
+ {
+ ArLog::log(ArLog::Terse, "popupExample: Could not connect to the robot.");
+ if(parser.checkHelpAndWarnUnparsed())
+ {
+ Aria::logOptions();
+ }
+ Aria::exit(1);
+ }
+
+ ArLaserConnector laserConnector(&parser, &robot, &robotConnector);
+
+ ArServerSimpleOpener simpleOpener(&parser);
+
+ // Get command-line and other parameters
+ if(!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed())
+ {
+ Aria::logOptions();
+ Aria::exit(1);
+ }
+
+ robot.runAsync(true);
+
+ // connect to the laser
+ if(!laserConnector.connectLasers())
+ {
+ ArLog::log(ArLog::Normal, "popupExample: Warning: Could not connect to lasers.");
+ }
+
+
+ // Open the server
+ if(!simpleOpener.open(&server))
+ {
+ ArLog::log(ArLog::Terse, "popupExample: Error, could not open server.");
+ return 1;
+ }
+ server.runAsync();
+ ArLog::log(ArLog::Normal, "popupExample: Server running. Press control-C to exit.");
+ ArLog::log(ArLog::Normal, "popupExample: Each time an obstacle is detected near the robot, a new popup message will be created. Connect with MobileEyes to see them.");
+
+ // Sends robot position etc.
+ ArServerInfoRobot robotInfoServer(&server, &robot);
+
+ // This service sends drawings e.g. showing range device positions
+ ArServerInfoDrawings drawingsServer(&server);
+ drawingsServer.addRobotsRangeDevices(&robot);
+
+ // This service can send messages to clients to display as popup dialogs:
+ ArServerHandlerPopup popupServer(&server);
+
+ // This object contains the robot sensor interpretation task and creates
+ // popups:
+ SensorDetectPopup(&robot, &popupServer);
+
+ robot.enableMotors();
+ robot.waitForRunExit();
+
+ Aria::exit(0);
+}
+
+SensorDetectPopup::SensorDetectPopup(ArRobot *robot, ArServerHandlerPopup *popupServer) :
+ myRobot(robot),
+ myPopupServer(popupServer),
+ myPopupDisplayed(false),
+ myPrevObstacleAngleValid(false)
+{
+ myRobot->lock();
+ myRobot->addSensorInterpTask("sensorDetectPopup", 50, new ArFunctorC(this, &SensorDetectPopup::sensorTask));
+ myPopupClosedCB = new ArFunctor2C(this, &SensorDetectPopup::popupClosed);
+ myRobot->unlock();
+}
+
+void SensorDetectPopup::sensorTask(void)
+{
+ // Basic obstacle detection
+
+ if (myPopupDisplayed) return;
+ double detectAngle, detectRange;
+ detectRange = myRobot->checkRangeDevicesCurrentPolar(-90, 90, &detectAngle);
+ if (detectRange > 0 && detectRange <= 500)
+ {
+ if(myPrevObstacleAngleValid && fabs(detectAngle - myPrevObstacleAngle) < 0.0001)
+ return;
+ ArLog::log(ArLog::Normal, "popupExample: New obstacle detected at range %f, angle %f. Displaying popup dialog on client...", detectRange, detectAngle);
+
+ ArServerHandlerPopupInfo info("popupExample", // ID
+ "Object Detected", // Title
+ "A range sensor detected a reading within 0.5 meters of the robot.", // Message
+ ArServerHandlerPopup::INFORMATION, // Type
+ 0, // Default button
+ 0, // Cancel/escape button
+ 5, // Timeout (sec.)
+ NULL, // Timeout String
+ "OK", "Acknowleged.", // Button 0 Label/Acknowlegement
+ "Turn Around", "Requested rotate...", // Button 1 Label/Acknowlegement
+ "Shut Down", "Shutting down server..." // Button 2 Label/Acknowlegement
+ );
+ int id = myPopupServer->createPopup(&info, myPopupClosedCB);
+ ArLog::log(ArLog::Normal, "\t...Created a popup with ID=%d", id);
+ myPopupDisplayed = true;
+ myPrevObstacleAngle = detectAngle;
+ myPrevObstacleAngleValid = true;
+ }
+}
+
+void SensorDetectPopup::popupClosed(ArTypes::Byte4 popupID, int button)
+{
+ // A client closed the popup
+ ArLog::log(ArLog::Normal, "popupExample: a client closed popup dialog window with id=%d. Button=%d...", popupID, button);
+ myPopupDisplayed = false;
+
+ if(button < 0)
+ {
+ ArLog::log(ArLog::Normal, "\t...popup timed out or closed due to an error.");
+ return;
+ }
+
+ if (button == 0)
+ {
+ ArLog::log(ArLog::Normal, "\t...OK pressed.");
+ return;
+ }
+
+ if(button == 1)
+ {
+ ArLog::log(ArLog::Normal, "\t...180 degree rotate requested.");
+ myRobot->lock();
+ myRobot->setDeltaHeading(180);
+ myRobot->unlock();
+ return;
+ }
+
+ if(button == 2)
+ {
+ ArLog::log(ArLog::Normal, "\t...exit requested.");
+ myRobot->stopRunning();
+ Aria::shutdown();
+ Aria::exit(0);
+ }
+}
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/ptzCameraClientExample.cpp b/Legacy/Aria/ArNetworking/examples/ptzCameraClientExample.cpp
new file mode 100644
index 0000000..54937b7
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/ptzCameraClientExample.cpp
@@ -0,0 +1,334 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+#include
+
+
+/** @example ptzCameraClientExample.cpp Example client showing how to control a Pan/Tilt/Zoom
+ * camera remotely.
+ *
+ * To use, serverDemo, arnlServer from ARNL, sonarnlServer from SONARNL, or
+ * your own server program that includes an ArServerHandlerCamera object.
+ * Then from another host, run ptzCameraClientExample with the -host argument.
+ * For example, if the hostname of the robot's onboard computer is "robot", run:
+ * ptzCameraClientExample -host robot
+ * Or use an IP address, for example, if the address is 10.0.126.32:
+ * ptzCameraClientExample -host 10.0.126.32
+ *
+ * This program connects to the server, gets a list of cameras if neccesary, and
+ * for each camera on the robot, it receives and prints out one information
+ * packet, then a continuous stream of data packets, and then sends requests
+ * to cycle through each of its pan and tilt limits.
+ *
+ * This program does not get any video images from the server. To do so, use
+ * a video server (e.g. SAV server or ACTS), and see getVideoExample for an
+ * example client.
+ */
+
+
+/** A request packet that is able to send a copy of itself, with data packed in,
+ * to a server.
+ */
+class ArNetCameraRequest : public ArNetPacket
+{
+ ArClientBase *myClient;
+ std::string myAbsReqName;
+public:
+ ArNetCameraRequest(ArClientBase *client, const char *cameraName = "") : myClient(client), myAbsReqName(std::string("setCameraAbs")+cameraName)
+ {}
+ void setCameraName(const char *name) {
+ myAbsReqName = std::string("setCameraAbs") + name;
+ }
+ bool requestPanTiltZoomAbs(double pan, double tilt, double zoom);
+ bool requestPanTiltAbs(double pan, double tilt);
+};
+
+
+/** Includes callbacks for receiving info and data packets from a
+ * camera server and storing the values parsed from them.
+ */
+class ArClientHandlerCamera {
+public:
+ std::string name;
+ std::string type;
+ std::string displayName;
+ std::string displayType;
+ double minPan, maxPan, minTilt, maxTilt, minZoom, maxZoom;
+ bool haveZoom;
+ double pan, tilt, zoom;
+
+ void handleCameraInfoReply(ArNetPacket *packet);
+ void handleCameraDataReply(ArNetPacket *packet);
+
+ ArClientBase *myClient;
+ ArNetCameraRequest request;
+ ArMutex myMutex;
+
+ ArFunctor1C myCameraInfoReplyFunc;
+ ArFunctor1C myCameraDataReplyFunc;
+
+ ArClientHandlerCamera(ArClientBase *client, const char *cameraName) :
+ name(cameraName), myClient(client), request(client, cameraName) ,
+ myCameraInfoReplyFunc(this, &ArClientHandlerCamera::handleCameraInfoReply),
+ myCameraDataReplyFunc(this, &ArClientHandlerCamera::handleCameraDataReply)
+ {
+ myClient->addHandler((std::string("getCameraInfo")+name).c_str(), &myCameraInfoReplyFunc);
+ myClient->addHandler((std::string("getCameraData")+name).c_str(), &myCameraDataReplyFunc);
+ }
+
+ void requestUpdates(int dataRequestFreq) {
+ myClient->request((std::string("getCameraInfo")+name).c_str(), -1);
+ myClient->request((std::string("getCameraData")+name).c_str(), 100);
+ }
+
+ void lock() { myMutex.lock(); }
+ void unlock() { myMutex.unlock(); }
+};
+
+
+/** Requests a list of cameras if neccesary, maintains a list of cameras, and implements example pan/tilt movements */
+class PtzCameraExample
+{
+ ArClientBase *myClient;
+
+ std::set myCameras;
+ ArMutex mutex;
+
+ ArFunctor1C myCameraListReplyFunc;
+
+ void handleCameraListReply(ArNetPacket *packet);
+
+
+public:
+ PtzCameraExample(ArClientBase *client) :
+ myClient(client),
+ myCameraListReplyFunc(this, &PtzCameraExample::handleCameraListReply)
+ {
+ }
+
+ bool init();
+ void run();
+};
+
+
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ ArClientBase client;
+
+ ArArgumentParser parser(&argc, argv);
+ ArClientSimpleConnector clientConnector(&parser);
+ parser.loadDefaultArguments();
+ if (!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed())
+ {
+ Aria::logOptions();
+ return 1;
+ }
+
+ if (!clientConnector.connectClient(&client))
+ {
+ if(client.wasRejected())
+ ArLog::log(ArLog::Terse, "Error, server '%s' rejected connection. Exiting.", client.getHost());
+ else
+ ArLog::log(ArLog::Terse, "Error, could not connect to server '%s'. Exiting.", client.getHost());
+ return 2;
+ }
+
+ client.setRobotName(client.getHost()); // include server hostname in log messages
+
+ client.runAsync();
+
+ PtzCameraExample example(&client);
+ if(!example.init())
+ return 1;
+
+ example.run();
+
+
+ Aria::shutdown();
+ return 0;
+}
+
+
+bool PtzCameraExample::init()
+{
+ // If the server has the "getCameraList" request, then it's using
+ // ArServerHandlerCameraCollection, and migth have multiple PTZs/cameras each with
+ // its own set of requests. So send a "getCameraList" request, and when its
+ // reply is received, the handler will send "getCameraInfo" requests for each.
+ // If the server does not have "getCameraList", it only has one PTZ camera, just
+ // send "getCameraInfo". The handler for that will send various control
+ // commands.
+ // If the server does not have "getCameraInfo", then it doesn't provide any
+ // access to PTZ cameras.
+ if(myClient->dataExists("getCameraList"))
+ {
+ ArLog::log(ArLog::Normal, "Server may have multiple cameras. Requesting list.");
+ myClient->addHandler("getCameraList", &myCameraListReplyFunc);
+ myClient->requestOnce("getCameraList");
+ }
+ else if(myClient->dataExists("getCameraInfo"))
+ {
+ ArLog::log(ArLog::Normal, "Server does not support multiple cameras. Requesting info for its camera.");
+ ArClientHandlerCamera *camClient = new ArClientHandlerCamera(myClient, "");
+ camClient->requestUpdates(100);
+ mutex.lock();
+ myCameras.insert(camClient);
+ mutex.unlock();
+ }
+ else
+ {
+ ArLog::log(ArLog::Terse, "Error, server does not have any camera control requests. (Was the server run with video features enabled or video forwarding active?)");
+ return false;
+ }
+ return true;
+}
+
+void PtzCameraExample::handleCameraListReply(ArNetPacket *pkt)
+{
+ ArTypes::Byte2 numCams = pkt->bufToByte2();
+ ArLog::log(ArLog::Normal, "%d cameras in list.", numCams);
+ char camName[128];
+ char camType[128];
+ char displayName[128];
+ char displayType[128];
+ char cmdDesc[128];
+ char cmdName[128];
+ ArTypes::Byte4 cmdFreq;
+ int dataReqFreq = 100;
+ for(ArTypes::Byte2 i = 0; i < numCams; ++i)
+ {
+ memset(camName, 0, 128);
+ memset(camType, 0, 128);
+ memset(displayName, 0, 128);
+ memset(displayType, 0, 128);
+ pkt->bufToStr(camName, 128); // name
+
+ ArClientHandlerCamera *cam = new ArClientHandlerCamera(myClient, camName);
+
+ pkt->bufToStr(camType, 128); // type
+ cam->type = camType;
+ pkt->bufToStr(displayName, 128); // description
+ cam->displayName = displayName;
+ pkt->bufToStr(displayType, 128); // description
+ cam->displayType = displayType;
+ ArTypes::Byte2 numCmds = pkt->bufToByte2();
+ ArLog::log(ArLog::Normal, "%d commands for camera \'%s\' (%s) / \'%s\' (%s)", numCmds, camName, camType, displayName, displayType);
+ for(ArTypes::Byte2 c = 0; c < numCmds; ++c)
+ {
+ memset(cmdDesc, 0, 128);
+ memset(cmdName, 0, 128);
+ char cmdDesc[128];
+ char cmdName[128];
+ pkt->bufToStr(cmdDesc, 128); // description
+ pkt->bufToStr(cmdName, 128); // request name
+ cmdFreq = pkt->bufToByte4(); // recommended request frequency
+ ArLog::log(ArLog::Normal, "Camera %s has %s command named %s with recommended request frequency %d.", camName, cmdDesc, cmdName, cmdFreq);
+
+ if(strcmp(cmdDesc, "getCameraData") == 0)
+ dataReqFreq = cmdFreq;
+ }
+ ArTypes::Byte2 numParams = pkt->bufToByte2();
+ ArLog::log(ArLog::Normal, "Camera %s has %d parameters.", camName, numParams);
+ for(ArTypes::Byte2 p = 0; p < numParams; ++p)
+ {
+ ArClientArg carg;
+ ArConfigArg arg;
+ if(!carg.bufToArgValue(pkt, arg))
+ ArLog::log(ArLog::Normal, "Hmm, error getting ArClientArg for camera %s's parameter #%d.", camName, p);
+ }
+
+ cam->requestUpdates(dataReqFreq);
+ mutex.lock();
+ myCameras.insert(cam);
+ mutex.unlock();
+ }
+}
+
+void ArClientHandlerCamera::handleCameraInfoReply(ArNetPacket *pkt)
+{
+ lock();
+ minPan = pkt->bufToByte2() / 1000.0;
+ maxPan = pkt->bufToByte2() / 1000.0;
+ minTilt = pkt->bufToByte2() / 1000.0;
+ maxTilt = pkt->bufToByte2() / 1000.0;
+ minZoom = pkt->bufToByte2() / 1000.0;
+ maxZoom = pkt->bufToByte2() / 1000.0;
+ haveZoom = pkt->bufToByte();
+ ArLog::log(ArLog::Normal, "Got getCameraInfo reply with pan range (%f, %f), tilt range (%f, %f), zoom range (%f, %f), zoom valid %d.", minPan, maxPan, minTilt, maxTilt, minZoom, maxZoom, haveZoom);
+ unlock();
+}
+
+void ArClientHandlerCamera::handleCameraDataReply(ArNetPacket *pkt)
+{
+ lock();
+ pan = pkt->bufToByte2() / 1000.0;
+ tilt = pkt->bufToByte2() / 1000.0;
+ zoom = pkt->bufToByte2() /1000.0;
+ ArLog::log(ArLog::Normal, "Got camera data from camera %s with current pan=%f, tilt=%f, zoom=%f.", name.c_str(), pan, tilt, zoom);
+ unlock();
+}
+
+bool ArNetCameraRequest::requestPanTiltAbs(double pan, double tilt)
+{
+ empty();
+ byte2ToBuf((ArTypes::Byte2)(pan * 1000.0));
+ byte2ToBuf((ArTypes::Byte2)(tilt * 1000.0));
+ finalizePacket();
+ return myClient->requestOnce(myAbsReqName.c_str(), this);
+}
+
+bool ArNetCameraRequest::requestPanTiltZoomAbs(double pan, double tilt, double zoom)
+{
+ empty();
+ byte2ToBuf((ArTypes::Byte2)(pan * 1000.0));
+ byte2ToBuf((ArTypes::Byte2)(tilt * 1000.0));
+ byte2ToBuf((ArTypes::Byte2)(zoom * 1000.0));
+ finalizePacket();
+ return myClient->requestOnce(myAbsReqName.c_str(), this);
+}
+
+
+void PtzCameraExample::run()
+{
+ enum { MinPan, MaxPan, Center1, MinTilt, MaxTilt, Center2} stage;
+ stage = MinPan;
+ while(myClient->isConnected())
+ {
+ mutex.lock();
+ for(std::set::const_iterator i = myCameras.begin(); i != myCameras.end(); ++i)
+ {
+ ArClientHandlerCamera* c = (*i);
+ c->lock();
+ switch(stage)
+ {
+ case MinPan:
+ c->request.requestPanTiltAbs(c->minPan, 0);
+ stage = MaxPan;
+ break;
+ case MaxPan:
+ c->request.requestPanTiltAbs(c->maxPan, 0);
+ stage = Center1;
+ break;
+ case Center1:
+ c->request.requestPanTiltAbs(0, 0);
+ stage = MinTilt;
+ break;
+ case MinTilt:
+ c->request.requestPanTiltAbs(0, c->minTilt);
+ stage = MaxTilt;
+ break;
+ case MaxTilt:
+ c->request.requestPanTiltAbs(0, c->maxTilt);
+ stage = Center2;
+ break;
+ case Center2:
+ c->request.requestPanTiltAbs(0, 0);
+ stage = MinPan;
+ }
+ c->unlock();
+ }
+ mutex.unlock();
+ ArUtil::sleep(3000);
+ }
+}
diff --git a/Legacy/Aria/ArNetworking/examples/serverDemo-vc2003.vcproj b/Legacy/Aria/ArNetworking/examples/serverDemo-vc2003.vcproj
new file mode 100644
index 0000000..9cb5df0
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/serverDemo-vc2003.vcproj
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/serverDemo-vc2008.vcproj b/Legacy/Aria/ArNetworking/examples/serverDemo-vc2008.vcproj
new file mode 100644
index 0000000..bb5f55b
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/serverDemo-vc2008.vcproj
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/serverDemo-vc2010.vcxproj b/Legacy/Aria/ArNetworking/examples/serverDemo-vc2010.vcxproj
new file mode 100644
index 0000000..4568514
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/serverDemo-vc2010.vcxproj
@@ -0,0 +1,152 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ serverDemo
+ {B9C37E51-E357-4019-B4B5-71C42E1FCD11}
+
+
+
+ Application
+ false
+ MultiByte
+
+
+ Application
+ false
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ ../../bin/
+ ../../obj/$(ProjectName)-$(Configuration)-VC10/
+ false
+ ../../bin/
+ ../../obj/$(ProjectName)-$(Configuration)-VC10/
+ false
+ serverDemoDebug
+ $(ProjectName)
+
+
+
+ $(IntDir)$(ProjectName)BuildLog.htm
+
+
+ .\../../bin/serverDemo.tlb
+
+
+
+
+ Disabled
+ ..\include;..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ Default
+ MultiThreadedDebugDLL
+ false
+ false
+ true
+ true
+ Level3
+ true
+ ProgramDatabase
+ Default
+ true
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ AriaDebugVC10.lib;ArNetworkingDebugVC10.lib
+ $(OutDir)$(TargetFileName)
+ 1.0
+ true
+ ..\..\lib;%(AdditionalLibraryDirectories)
+ true
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ $(IntDir)$(ProjectName)BuildLog.htm
+
+
+ .\../../bin/serverDemo.tlb
+
+
+
+
+ MaxSpeed
+ OnlyExplicitInline
+ ..\include;..\..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ Default
+ MultiThreadedDLL
+ false
+ false
+ true
+ Level3
+ true
+ Default
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ AriaVC10.lib;ArNetworkingVC10.lib
+ $(OutDir)$(TargetFileName)
+ 1.0
+ true
+ ..\..\lib;%(AdditionalLibraryDirectories)
+ Console
+ false
+
+
+ MachineX86
+
+
+
+
+ Disabled
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+ EnableFastChecks
+ true
+ MaxSpeed
+ %(AdditionalIncludeDirectories)
+ %(PreprocessorDefinitions)
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Legacy/Aria/ArNetworking/examples/serverDemo.cpp b/Legacy/Aria/ArNetworking/examples/serverDemo.cpp
new file mode 100644
index 0000000..150ca87
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/serverDemo.cpp
@@ -0,0 +1,257 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+
+/** @example serverDemo.cpp Example ArNetworking server providing teleoperation,
+ * sonar data, control the camera, etc.
+ *
+ * This is a basic ArNetworking server. It connects to a robot or simulator,
+ * including, if available, IRs, gyro, and bumpers. Give the option
+ * "-connectLaser" on the command line to enable the laser rangefinder,
+ * if available.
+ *
+ * Run "./serverDemo -help" for a full list of command line options.
+ *
+ * Once running, connect to this server with a a client such as
+ * MobileEyes.
+ *
+ * This server provides the following services:
+ * - User login (optional)
+ * - Basic robot telemetry information
+ * - Range sensor data values (not used by MobileEyes)
+ * - Graphics representing range sensor reading positions
+ * - Teleoperation modes (including safe/unsafe drive modes)
+ * - Wander mode
+ * - Various advanced "custom" commands to control logging, debugging, etc.
+ * - If an ACTS or SAV server is running, forward the video stream
+ * - Camera control (pan/tilt/zoom) if cameras are available
+ *
+ * Note that this program requires a terminal to run -- i.e. you can't run
+ * it in the background in Linux. To modify it to allow that, remove the key
+ * handler code in main().
+ */
+
+int main(int argc, char **argv)
+{
+ // mandatory init
+ Aria::init();
+
+ //ArLog::init(ArLog::StdOut, ArLog::Verbose);
+
+ // set up our parser
+ ArArgumentParser parser(&argc, argv);
+
+ // load the default arguments
+ parser.loadDefaultArguments();
+
+ // robot
+ ArRobot robot;
+ // set up our simple connector
+ ArRobotConnector robotConnector(&parser, &robot);
+
+
+ // add a gyro, it'll see if it should attach to the robot or not
+ ArAnalogGyro gyro(&robot);
+
+
+ // set up the robot for connecting
+ if (!robotConnector.connectRobot())
+ {
+ printf("Could not connect to robot... exiting\n");
+ Aria::exit(1);
+ }
+
+ ArDataLogger dataLogger(&robot, "dataLog.txt");
+ dataLogger.addToConfig(Aria::getConfig());
+
+ // our base server object
+ ArServerBase server;
+
+ ArLaserConnector laserConnector(&parser, &robot, &robotConnector);
+ ArServerSimpleOpener simpleOpener(&parser);
+
+
+ ArClientSwitchManager clientSwitchManager(&server, &parser);
+
+ // parse the command line... fail and print the help if the parsing fails
+ // or if the help was requested
+ if (!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed())
+ {
+ Aria::logOptions();
+ Aria::exit(1);
+ }
+
+ // Set up where we'll look for files such as user/password
+ char fileDir[1024];
+ ArUtil::addDirectories(fileDir, sizeof(fileDir), Aria::getDirectory(),
+ "ArNetworking/examples");
+
+ // first open the server up
+ if (!simpleOpener.open(&server, fileDir, 240))
+ {
+ if (simpleOpener.wasUserFileBad())
+ printf("Bad user/password/permissions file\n");
+ else
+ printf("Could not open server port\n");
+ exit(1);
+ }
+
+ // Range devices:
+
+
+ ArSonarDevice sonarDev;
+ robot.addRangeDevice(&sonarDev);
+
+ ArIRs irs;
+ robot.addRangeDevice(&irs);
+
+ ArBumpers bumpers;
+ robot.addRangeDevice(&bumpers);
+
+ // attach services to the server
+ ArServerInfoRobot serverInfoRobot(&server, &robot);
+ ArServerInfoSensor serverInfoSensor(&server, &robot);
+ ArServerInfoDrawings drawings(&server);
+
+ // modes for controlling robot movement
+ ArServerModeStop modeStop(&server, &robot);
+ ArServerModeRatioDrive modeRatioDrive(&server, &robot);
+ ArServerModeWander modeWander(&server, &robot);
+ modeStop.addAsDefaultMode();
+ modeStop.activate();
+
+ // set up the simple commands
+ ArServerHandlerCommands commands(&server);
+ ArServerSimpleComUC uCCommands(&commands, &robot); // send commands directly to microcontroller
+ ArServerSimpleComMovementLogging loggingCommands(&commands, &robot); // control debug logging
+ ArServerSimpleComGyro gyroCommands(&commands, &robot, &gyro); // configure gyro
+ ArServerSimpleComLogRobotConfig configCommands(&commands, &robot); // control more debug logging
+ ArServerSimpleServerCommands serverCommands(&commands, &server); // control ArNetworking debug logging
+ ArServerSimpleLogRobotDebugPackets logRobotDebugPackets(&commands, &robot, "."); // debugging tool
+
+ // ArServerModeDrive is an older drive mode. ArServerModeRatioDrive is newer and generally performs better,
+ // but you can use this for old clients if neccesary.
+ //ArServerModeDrive modeDrive(&server, &robot);
+ //modeDrive.addControlCommands(&commands); // configure the drive modes (e.g. enable/disable safe drive)
+
+ ArServerHandlerConfig serverHandlerConfig(&server, Aria::getConfig()); // make a config handler
+ ArLog::addToConfig(Aria::getConfig()); // let people configure logging
+
+ modeRatioDrive.addToConfig(Aria::getConfig(), "Teleop settings"); // able to configure teleop settings
+ modeRatioDrive.addControlCommands(&commands);
+
+ // Forward video if either ACTS or SAV server are running.
+ // You can find out more about SAV and ACTS on our website
+ // http://robots.activmedia.com. ACTS is for color tracking and is
+ // a separate product. SAV just does software A/V transmitting and is
+ // free to all our customers. Just run ACTS or SAV server before you
+ // start this program and this class here will forward video from the
+ // server to the client.
+ ArHybridForwarderVideo videoForwarder(&server, "localhost", 7070);
+
+ // Control a pan/tilt/zoom camera, if one is installed, and the video
+ // forwarder was enabled above.
+ ArPTZ *camera = NULL;
+ ArServerHandlerCamera *handlerCamera = NULL;
+ ArCameraCollection *cameraCollection = NULL;
+ if (videoForwarder.isForwardingVideo())
+ {
+ bool invertedCamera = false;
+ camera = new ArVCC4(&robot, invertedCamera,
+ ArVCC4::COMM_UNKNOWN, true, true);
+ camera->init();
+
+ cameraCollection = new ArCameraCollection();
+ cameraCollection->addCamera("Cam1", "VCC4", "Camera", "VCC4");
+ handlerCamera = new ArServerHandlerCamera("Cam1",
+ &server,
+ &robot,
+ camera,
+ cameraCollection);
+ }
+
+ // You can use this class to send a set of arbitrary strings
+ // for MobileEyes to display, this is just a small example
+ ArServerInfoStrings stringInfo(&server);
+ Aria::getInfoGroup()->addAddStringCallback(stringInfo.getAddStringFunctor());
+ Aria::getInfoGroup()->addStringInt(
+ "Motor Packet Count", 10,
+ new ArConstRetFunctorC(&robot,
+ &ArRobot::getMotorPacCount));
+ /*
+ Aria::getInfoGroup()->addStringInt(
+ "Laser Packet Count", 10,
+ new ArRetFunctorC(&sick,
+ &ArSick::getSickPacCount));
+ */
+
+ // start the robot running, true means that if we lose connection the run thread stops
+ robot.runAsync(true);
+
+
+ // connect the laser(s) if it was requested
+ if (!laserConnector.connectLasers())
+ {
+ printf("Could not connect to lasers... exiting\n");
+ Aria::exit(2);
+ }
+
+
+ drawings.addRobotsRangeDevices(&robot);
+
+ // log whatever we wanted to before the runAsync
+ simpleOpener.checkAndLog();
+ // now let it spin off in its own thread
+ server.runAsync();
+
+ printf("Server is now running...\n");
+
+ // Add a key handler so that you can exit by pressing
+ // escape. Note that a key handler prevents you from running
+ // a program in the background on Linux, since it expects an
+ // active terminal to read keys from; remove this if you want
+ // to run it in the background.
+ ArKeyHandler *keyHandler;
+ if ((keyHandler = Aria::getKeyHandler()) == NULL)
+ {
+ keyHandler = new ArKeyHandler;
+ Aria::setKeyHandler(keyHandler);
+ robot.lock();
+ robot.attachKeyHandler(keyHandler);
+ robot.unlock();
+ printf("To exit, press escape.\n");
+ }
+
+ // Read in parameter files.
+ std::string configFile = "serverDemoConfig.txt";
+ Aria::getConfig()->setBaseDirectory("./");
+ if (Aria::getConfig()->parseFile(configFile.c_str(), true, true))
+ {
+ ArLog::log(ArLog::Normal, "Loaded config file %s", configFile.c_str());
+ }
+ else
+ {
+ if (ArUtil::findFile(configFile.c_str()))
+ {
+ ArLog::log(ArLog::Normal,
+ "Trouble loading configuration file %s, continuing",
+ configFile.c_str());
+ }
+ else
+ {
+ ArLog::log(ArLog::Normal,
+ "No configuration file %s, will try to create if config used",
+ configFile.c_str());
+ }
+ }
+
+ clientSwitchManager.runAsync();
+
+ robot.lock();
+ robot.enableMotors();
+ robot.unlock();
+
+ robot.waitForRunExit();
+ Aria::exit(0);
+}
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/serverDemo.userInfo b/Legacy/Aria/ArNetworking/examples/serverDemo.userInfo
new file mode 100644
index 0000000..b36409f
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/serverDemo.userInfo
@@ -0,0 +1,8 @@
+; You'll want to change the . below to the actual password you want
+; used for the different accounts, also note you can start up serverDemo
+; with this information by giving it the '-userInfo '
+; argument on the command line
+UserInfoVersion1
+user user . CustomCommands Movement RobotInfo SensorInfo Stop UnsafeMovement
+user guest . CustomCommands Movement RobotInfo SensorInfo Stop UnsafeMovement
+user administrator . all
diff --git a/Legacy/Aria/ArNetworking/examples/serverDemoStatic-vc2003.vcproj b/Legacy/Aria/ArNetworking/examples/serverDemoStatic-vc2003.vcproj
new file mode 100644
index 0000000..ec45845
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/serverDemoStatic-vc2003.vcproj
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/serverDemoStatic-vc2008.vcproj b/Legacy/Aria/ArNetworking/examples/serverDemoStatic-vc2008.vcproj
new file mode 100644
index 0000000..2446a63
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/serverDemoStatic-vc2008.vcproj
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Legacy/Aria/ArNetworking/examples/serverDemoStatic-vc2010.vcxproj b/Legacy/Aria/ArNetworking/examples/serverDemoStatic-vc2010.vcxproj
new file mode 100644
index 0000000..cc93bf5
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/serverDemoStatic-vc2010.vcxproj
@@ -0,0 +1,143 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ serverDemoStatic
+ {EEF9FE4C-34C4-4C76-94C4-D11930C88DE1}
+ serverDemoStatic
+ ManagedCProj
+
+
+
+ Application
+ MultiByte
+ false
+ v100
+
+
+ Application
+ MultiByte
+ false
+ v100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ ..\..\bin\
+ ../../obj/$(ProjectName)-$(Configuration)-VC10/
+ true
+ ..\..\bin\
+ ../../obj/$(ProjectName)-$(Configuration)-VC10/
+ false
+ serverDemoStaticDebug
+ $(ProjectName)
+
+
+
+ $(IntDir)$(ProjectName)BuildLog.htm
+
+
+ Disabled
+ ..\..\include;..\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;ARIA_STATIC;%(PreprocessorDefinitions)
+ false
+ Default
+ MultiThreadedDebug
+ false
+
+
+ Level3
+ ProgramDatabase
+ true
+
+
+ false
+
+
+ AriaStaticDebugVC10.lib;ws2_32.lib;winmm.lib;advapi32.lib;ArNetworkingStaticDebugVC10.lib
+ $(OutDir)$(TargetFileName)
+ true
+ ..\..\lib;%(AdditionalLibraryDirectories)
+ %(IgnoreSpecificDefaultLibraries)
+ true
+ true
+ false
+
+
+ NotSet
+
+
+
+
+ $(IntDir)$(ProjectName)BuildLog.htm
+
+
+ AnySuitable
+ true
+ ..\..\include;..\include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;ARIA_STATIC;%(PreprocessorDefinitions)
+ false
+ MultiThreaded
+ false
+ true
+ NotUsing
+ Level3
+ ProgramDatabase
+ true
+
+
+ AriaStaticVC10.lib;ArNetworkingStaticVC10.lib;winmm.lib;ws2_32.lib;%(AdditionalDependencies)
+ $(OutDir)$(TargetFileName)
+ true
+ ..\..\lib;%(AdditionalLibraryDirectories)
+ %(IgnoreSpecificDefaultLibraries)
+ false
+ false
+
+
+
+
+ NotSet
+
+
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Legacy/Aria/ArNetworking/examples/simpleServerExample.cpp b/Legacy/Aria/ArNetworking/examples/simpleServerExample.cpp
new file mode 100644
index 0000000..0d0f911
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/examples/simpleServerExample.cpp
@@ -0,0 +1,129 @@
+#include "Aria.h"
+#include "ArNetworking.h"
+
+
+/** @example simpleServerExample.cpp This is a simple example of an ArNetworking server.
+ * This server provides range sensor data to the client, and teleoperation
+ * controls. It also includes an example of a custom command (using
+ * ArServerHandlerCommands).
+ *
+ * For a more complete server, see serverDemo.cpp.
+ */
+
+
+/* This function is called ArServerHandlerCommands when our custom command is
+ * recieved. */
+void customCommandHandler(ArArgumentBuilder *args)
+{
+ if(args && args->getArg(0))
+ ArLog::log(ArLog::Normal, "Recieved custom command with argument \"%s\".", args->getArg(0));
+ else
+ ArLog::log(ArLog::Normal, "Recieved custom command with no arguments.");
+}
+
+
+int main(int argc, char **argv)
+{
+ Aria::init();
+ ArRobot robot;
+ ArArgumentParser parser(&argc, argv);
+ ArSimpleConnector simpleConnector(&parser);
+
+ // The base server object, manages all connections to clients.
+ ArServerBase server;
+
+ // This object simplifies configuration and opening of the ArServerBase
+ // object.
+ ArServerSimpleOpener simpleOpener(&parser);
+
+ // parse the command line. fail and print the help if the parsing fails
+ // or if the help was requested with -help
+ parser.loadDefaultArguments();
+ if (!simpleConnector.parseArgs() || !simpleOpener.parseArgs() ||
+ !parser.checkHelpAndWarnUnparsed())
+ {
+ simpleConnector.logOptions();
+ simpleOpener.logOptions();
+ exit(1);
+ }
+
+ // Use the ArSimpleOpener to open the server port
+ if (!simpleOpener.open(&server))
+ {
+ ArLog::log(ArLog::Terse, "Error: Could not open server on port %d", simpleOpener.getPort());
+ exit(1);
+ }
+
+
+ //
+ // Create services attached to the base server:
+ //
+
+ // Robot position etc.:
+ ArServerInfoRobot serverInfoRobot(&server, &robot);
+
+ // Robot control modes (only one mode can be active at once):
+ ArServerModeStop modeStop(&server, &robot);
+ // old ArServerModeDrive modeDrive(&server, &robot);
+ ArServerModeRatioDrive modeRatioDrive(&server, &robot);
+ ArServerModeWander modeWander(&server, &robot);
+ modeStop.addAsDefaultMode();
+ modeStop.activate();
+
+ // This provides a simple way to add new commands.
+ ArServerHandlerCommands commands(&server);
+
+ // Add our custom command. ArServerHandlerCommands also has other methods
+ // for adding commands taht take different kinds of arguments, or no
+ // arguments.
+ ArGlobalFunctor1 customCommandFunctor(&customCommandHandler);
+ commands.addStringCommand("ExampleCustomCommand", "Example of a custom command. simpleServerExample will print out the text sent with the command.", &customCommandFunctor);
+
+ // These objects provide various debugging and diagnostic custom commands:
+ ArServerSimpleComUC uCCommands(&commands, &robot); // Get information about the robot
+ ArServerSimpleComMovementLogging loggingCommands(&commands, &robot); // Control logging
+ modeRatioDrive.addControlCommands(&commands); // Drive mode diagnostics
+
+ // This provides the client (e.g. MobileEyes) with a simple table of string values
+ // (called an InfoGroup). An InfoGroup is kept globally by Aria.
+ // The values in the table sent to clients are retrieved periodically by calling a
+ // functor.
+ ArServerInfoStrings stringInfo(&server);
+ Aria::getInfoGroup()->addAddStringCallback(stringInfo.getAddStringFunctor());
+
+ // Here are some example entries in the InfoGroup:
+ Aria::getInfoGroup()->addStringInt(
+ "Motor Packet Count", 10,
+ new ArConstRetFunctorC(&robot,
+ &ArRobot::getMotorPacCount));
+
+ //
+ // Connect to the robot:
+ //
+
+ if (!simpleConnector.connectRobot(&robot))
+ {
+ printf("Error: Could not connect to robot... exiting\n");
+ Aria::shutdown();
+ return 1;
+ }
+
+
+ robot.enableMotors();
+ robot.runAsync(true);
+
+ // The simple opener might have information to display right before starting
+ // the server thread:
+ simpleOpener.checkAndLog();
+
+ // now let the server base run in a new thread, accepting client connections.
+ server.runAsync();
+
+ ArLog::log(ArLog::Normal, "Server is now running... Press Ctrl-C to exit.");
+
+ robot.waitForRunExit();
+ Aria::shutdown();
+ exit(0);
+}
+
+
diff --git a/Legacy/Aria/ArNetworking/include/ArCentralForwarder.h b/Legacy/Aria/ArNetworking/include/ArCentralForwarder.h
new file mode 100644
index 0000000..d62f62b
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArCentralForwarder.h
@@ -0,0 +1,168 @@
+#ifndef ARCENTRALFORWARDER_H
+#define ARCENTRALFORWARDER_H
+
+#include "Aria.h"
+#include "ArServerBase.h"
+#include "ArClientBase.h"
+
+/**
+ Class for forwarding... You sould use the commands on this instead
+ of the ones on the server and client it holds.
+
+ requestStop is missing since that'd only cause problems.
+
+ request doesn't take a packet since that'd cause problems with the
+ proxying, other than that everything should be like the client.
+
+ Talk to MattL if there's questions.
+**/
+class ArCentralForwarder
+{
+public:
+ AREXPORT ArCentralForwarder(
+ ArServerBase *mainServer, ArSocket *socket,
+ const char *robotName, int startingPort,
+ std::map *usedPorts,
+ ArFunctor2 *notifyServerClientRemovedCB,
+ const char *enforceProtocolVersion,
+ ArServerCommands::Type enforceType
+ );
+ AREXPORT ~ArCentralForwarder();
+
+ /// Gets the robot name
+ const char *getRobotName(void) { return myRobotName.c_str(); }
+
+ /// Adds a functor for some particular data
+ AREXPORT bool addHandler(const char *name,
+ ArFunctor1 *functor);
+
+ /// Removes a functor for some particular data by name
+ AREXPORT bool remHandler(const char *name, ArFunctor1 *functor);
+
+ /// Request some data every @a mSec milliseconds
+ AREXPORT bool request(const char *name, long mSec);
+
+ /// Request some data (or send a command) just once
+ AREXPORT bool requestOnce(const char *name,
+ ArNetPacket *packet = NULL,
+ bool quiet = false);
+
+ /// Request some data (or send a command) just once by UDP
+ AREXPORT bool requestOnceUdp(const char *name,
+ ArNetPacket *packet = NULL,
+ bool quiet = false);
+
+ /// Request some data (or send a command) just once with a string as argument
+ AREXPORT bool requestOnceWithString(const char *name, const char *str);
+
+ /// Sees if this data exists
+ AREXPORT bool dataExists(const char *name);
+
+
+
+ /// Gets the server (shouldn't need to be used by anyone)
+ ArServerBase *getServer(void) { return myServer; }
+ /// Gets the client (shouldn't need to be used by anyone)
+ ArClientBase *getClient(void) { return myClient; }
+ /// Gets the port (shouldn't need to be used by anyone)
+ int getPort(void) { return myPort; }
+ AREXPORT bool callOnce(
+ double heartbeatTimeout, double udpHeartbeatTimeout,
+ double robotBackupTimeout, double clientBackupTimeout);
+ AREXPORT bool isConnected(void) { return myState == STATE_CONNECTED; }
+ AREXPORT void willReplace(void) { myBeingReplaced = true; }
+protected:
+ AREXPORT void netCentralHeartbeat(ArNetPacket *packet);
+
+ void robotServerClientRemoved(ArServerClient *client);
+ void clientServerClientRemoved(ArServerClient *client);
+ void receiveData(ArNetPacket *packet);
+ void internalRequestChanged(long interval, unsigned int command);
+ bool internalRequestOnce(ArServerClient *client, ArNetPacket *packet,
+ bool tcp);
+
+ AREXPORT bool startingCallOnce(
+ double heartbeatTimeout, double udpHeartbeatTimeout,
+ double robotBackupTimeout, double clientBackupTimeout);
+ AREXPORT bool connectingCallOnce(
+ double heartbeatTimeout, double udpHeartbeatTimeout,
+ double robotBackupTimeout, double clientBackupTimeout);
+ AREXPORT bool gatheringCallOnce(
+ double heartbeatTimeout, double udpHeartbeatTimeout,
+ double robotBackupTimeout, double clientBackupTimeout);
+ AREXPORT bool connectedCallOnce(
+ double heartbeatTimeout, double udpHeartbeatTimeout,
+ double robotBackupTimeout, double clientBackupTimeout);
+
+ std::string myEnforceProtocolVersion;
+ ArServerCommands::Type myEnforceType;
+
+ ArServerBase *myMainServer;
+ ArSocket *mySocket;
+ std::string myRobotName;
+ std::string myPrefix;
+ int myStartingPort;
+ std::map *myUsedPorts;
+ ArFunctor2 *myForwarderServerClientRemovedCB;
+
+ enum State
+ {
+ STATE_STARTING,
+ STATE_CONNECTING,
+ STATE_GATHERING,
+ STATE_CONNECTED
+ };
+ bool myBeingReplaced;
+
+
+ ArServerBase *myServer;
+ ArClientBase *myClient;
+ State myState;
+ int myPort;
+ ArServerBase *server;
+ ArClientBase *client;
+
+ bool myRobotHasCentralServerHeartbeat;
+ ArTime myLastSentCentralServerHeartbeat;
+
+ enum ReturnType
+ {
+ RETURN_NONE,
+ RETURN_SINGLE,
+ RETURN_VIDEO,
+ RETURN_UNTIL_EMPTY,
+ RETURN_COMPLEX,
+ RETURN_VIDEO_OPTIM,
+ };
+
+ std::map myReturnTypes;
+ std::map *> myRequestOnces;
+ std::map myLastRequest;
+ std::map myLastBroadcast;
+
+ ReturnType getReturnType(int command);
+ void checkRequestOnces(unsigned int command);
+ void setLastRequest(unsigned int command);
+ void setLastBroadcast(unsigned int command);
+
+ ArTime myLastTcpHeartbeat;
+ ArTime myLastUdpHeartbeat;
+
+ ArFunctor1C myReceiveDataFunctor;
+ ArFunctor2C myInternalRequestChangedFunctor;
+ ArRetFunctor3C myInternalRequestOnceFunctor;
+ ArFunctor1C myRobotServerClientRemovedCB;
+ ArFunctor1C myNetCentralHeartbeatCB;
+ ArFunctor1C myClientServerClientRemovedCB;
+
+};
+
+
+#endif // ARSERVERSWITCHFORWARDER
diff --git a/Legacy/Aria/ArNetworking/include/ArCentralManager.h b/Legacy/Aria/ArNetworking/include/ArCentralManager.h
new file mode 100644
index 0000000..2df9dfd
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArCentralManager.h
@@ -0,0 +1,88 @@
+#ifndef ARCENTRALMANAGER
+#define ARCENTRALMANAGER
+
+#include "Aria.h"
+#include "ArServerBase.h"
+#include "ArCentralForwarder.h"
+
+class ArCentralManager : public ArASyncTask
+{
+public:
+ /// Constructor
+ AREXPORT ArCentralManager(ArServerBase *robotServer, ArServerBase *clientServer);
+ /// Destructor
+ AREXPORT virtual ~ArCentralManager();
+ /// Logs all the connection information
+ void logConnections(void);
+ /// Enforces that everything is using this protocol version
+ AREXPORT void enforceProtocolVersion(const char *protocolVersion);
+ /// Enforces that the robots that connect are this type
+ AREXPORT void enforceType(ArServerCommands::Type type);
+ /// Adds a callback for when a new forwarder is added
+ AREXPORT void addForwarderAddedCallback(
+ ArFunctor1 *functor, int priority = 0);
+ /// Removes a callback for when a new forwarder is added
+ AREXPORT void remForwarderAddedCallback(
+ ArFunctor1 *functor);
+ /// Adds a callback for when a new forwarder is destroyed
+ AREXPORT void addForwarderRemovedCallback(
+ ArFunctor1 *functor, int priority = 0);
+ /// Removes a callback for when a new forwarder is destroyed
+ AREXPORT void remForwarderRemovedCallback(
+ ArFunctor1 *functor);
+ /// Networking command to get the list of clients
+ AREXPORT void netClientList(ArServerClient *client, ArNetPacket *packet);
+ /// A callback so we can tell the main connection happened when a
+ /// client is removed
+ AREXPORT void forwarderServerClientRemovedCallback(
+ ArCentralForwarder *forwarder, ArServerClient *client);
+ /// A callback so we can close down other connetions when a main
+ /// client loses connection
+ AREXPORT void mainServerClientRemovedCallback(ArServerClient *client);
+ /// Networking command to switch the direction of a connection
+ AREXPORT void netServerSwitch(ArServerClient *client, ArNetPacket *packet);
+ AREXPORT virtual void *runThread(void *arg);
+protected:
+ void close(void);
+ bool processFile(void);
+
+ bool removePendingDuplicateConnections(const char *robotName);
+
+ ArServerBase *myRobotServer;
+ ArServerBase *myClientServer;
+ double myHeartbeatTimeout;
+ double myUdpHeartbeatTimeout;
+ double myRobotBackupTimeout;
+ double myClientBackupTimeout;
+
+ std::string myEnforceProtocolVersion;
+ ArServerCommands::Type myEnforceType;
+
+ int myMostForwarders;
+ int myMostClients;
+
+ ArTypes::UByte4 myClosingConnectionID;
+ std::list myClientSockets;
+ std::list myClientNames;
+ std::list myForwarders;
+ std::map myUsedPorts;
+ ArMutex myCallbackMutex;
+ std::multimap *> myForwarderAddedCBList;
+ std::multimap *> myForwarderRemovedCBList;
+ ArMutex myDataMutex;
+ int myOnSocket;
+ ArFunctor2C myNetSwitchCB;
+ ArFunctor2C myNetClientListCB;
+ ArFunctorC myAriaExitCB;
+ ArRetFunctorC myProcessFileCB;
+ ArFunctor2C myForwarderServerClientRemovedCB;
+ ArFunctor1C myMainServerClientRemovedCB;
+};
+
+
+#endif // ARSERVERSWITCHMANAGER
diff --git a/Legacy/Aria/ArNetworking/include/ArClientArgUtils.h b/Legacy/Aria/ArNetworking/include/ArClientArgUtils.h
new file mode 100644
index 0000000..65607d5
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArClientArgUtils.h
@@ -0,0 +1,170 @@
+/*!
+ * \brief Defines the ArClientArg class.
+ * \date 05/01/05
+ * \author K. Cunningham
+ *
+**/
+#ifndef ARCLIENTARGUTILS_H
+#define ARCLIENTARGUTILS_H
+
+#include "Aria.h"
+
+class ArNetPacket;
+class ArConfigArg;
+
+/// Small helper class for sending/receiving an ArConfigArg in an ArNetPacket.
+/**
+ * ArClientArg defines methods for packing/unpacking an ArConfigArg into/from
+ * an ArNetPacket. (The name of the class is a slight misnomer since it may
+ * be used both on the server and client sides.)
+ *
+ * The structure of the network packet information is as follows:
+ *
+ * string: arg.getName()
+ * string: arg.getDescription()
+ * byte: arg.getConfigPriority()
+ * byte: arg type ('B' == BOOL | 'I' == INT | 'D' == DOUBLE | 'S' == STRING | 'L' == LIST)
+ * <arg values>
+ * string: arg.getDisplayHint() -- only if isDisplayHintParsed is set to true
+ * string: arg.getExtraExplanation() -- only if version >= 2
+ * byte: arg.getRestartLevel() -- only if version >= 2
+ *
+ * <arg values> varies by arg type:
+ *
+ * if BOOL, then:
+ * byte: arg.getBool()
+ * if INT, then:
+ * byte4: arg.getInt()
+ * byte4: arg.getMinInt()
+ * byte4: arg.getMaxInt()
+ * if DOUBLE, then:
+ * byte4: arg.getDouble()
+ * byte4: arg.getMinDouble()
+ * byte4: arg.getMaxDouble()
+ * byte4: arg.getDoublePrecision() -- only if version >= 2
+ * if STRING, then:
+ * string: arg.getString()
+ * if LIST, then:
+ * byte4: arg.getArgCount()
+ * <list contents>
+ *
+ *
+ *
+ *
+ *
+ * ArClientArg also defines methods to send an "abbreviated" ArConfigArg
+ * (i.e. just value). The short packet structure is as follows:
+ *
+ * <arg value> varies by arg type:
+ * if BOOL, then:
+ * byte: arg.getBool()
+ * if INT, then:
+ * byte4: arg.getInt()
+ * if DOUBLE, then:
+ * byte4: arg.getDouble()
+ * if STRING, then:
+ * string: arg.getString()
+ * if LIST, then:
+ *
+ * <list contents>
+ *
+ * Lastly, it defines a method to send an "abbreviated" ArConfigArg in a
+ * text format.
+**/
+class ArClientArg
+{
+public:
+
+ /// Constructor
+ AREXPORT ArClientArg(bool isDisplayHintParsed = false,
+ ArPriority::Priority lastPriority = ArPriority::LAST_PRIORITY,
+ int version = 1);
+
+ /// Destructor
+ AREXPORT virtual ~ArClientArg();
+
+ /// Returns whether the given parameter can be sent in a network packet.
+ /**
+ * Currently, a parameter can only be sent if it is of type INT, DOUBLE,
+ * STRING, BOOL, LIST, or a SEPARATOR.
+ **/
+ AREXPORT virtual bool isSendableParamType(const ArConfigArg &arg);
+
+ /// Unpacks the given network packet and stores the data in the config arg.
+ /**
+ * @param packet the ArNetPacket * from which data is extracted
+ * @param argOut the ArConfigArg in which to set the data
+ * @return bool set to true if the data was successfully extracted from
+ * the packet; false if an error occurred and argOut is invalid
+ **/
+ AREXPORT virtual bool createArg(ArNetPacket *packet,
+ ArConfigArg &argOut);
+
+
+ /// Stores the given config arg into the network packet.
+ /**
+ * @param arg the ArConfigArg from which to retrieve the data
+ * @param packet the ArNetPacket * to which data is added
+ * @return bool set to true if the data was successfully stored in
+ * the packet; false if an error occurred and the packet is invalid
+ **/
+ AREXPORT virtual bool createPacket(const ArConfigArg &arg,
+ ArNetPacket *packet);
+
+
+
+ /// Unpacks the abbreviated arg value and stores the data in the config arg.
+ /**
+ * @param packet the ArNetPacket * from which data is extracted
+ * @param arg the ArConfigArg in which to set the value
+ * @return bool set to true if the data was successfully extracted from
+ * the packet; false if an error occurred and arg is invalid
+ **/
+ AREXPORT virtual bool bufToArgValue(ArNetPacket *packet,
+ ArConfigArg &arg);
+
+ /// Stores the abbreviated arg value into the network packet.
+ /**
+ * @param arg the ArConfigArg from which to retrieve the data
+ * @param packet the ArNetPacket * to which data is added
+ * @return bool set to true if the data was successfully stored in
+ * the packet; false if an error occurred and the packet is invalid
+ **/
+ AREXPORT virtual bool argValueToBuf(const ArConfigArg &arg,
+ ArNetPacket *packet);
+
+
+
+ /// Stores the arg value into the network packet as a text string.
+ /**
+ * The stored text string is suitable for parsing by an ArArgumentBuilder.
+ *
+ * @param arg the ArConfigArg from which to retrieve the data
+ * @param packet the ArNetPacket * to which data is added
+ * @return bool set to true if the data was successfully stored in
+ * the packet; false if an error occurred and the packet is invalid
+ **/
+ AREXPORT virtual bool argTextToBuf(const ArConfigArg &arg,
+ ArNetPacket *packet);
+
+
+ AREXPORT virtual bool addArgTextToPacket(const ArConfigArg &arg,
+ ArNetPacket *packet);
+
+protected:
+
+ enum {
+ BUFFER_LENGTH = 1024
+ };
+
+ bool myIsDisplayHintParsed;
+ ArPriority::Priority myLastPriority;
+ int myVersion;
+
+ char myBuffer[BUFFER_LENGTH];
+ char myDisplayBuffer[BUFFER_LENGTH];
+ char myExtraBuffer[BUFFER_LENGTH];
+
+}; // end class ArClientArgUtils
+
+#endif //ARCLIENTARGUTILS_H
diff --git a/Legacy/Aria/ArNetworking/include/ArClientBase.h b/Legacy/Aria/ArNetworking/include/ArClientBase.h
new file mode 100644
index 0000000..0981c4f
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArClientBase.h
@@ -0,0 +1,424 @@
+#ifndef NLCLIENTBASE_H
+#define NLCLIENTBASE_H
+
+#include "Aria.h"
+#include "ArClientCommands.h"
+#include "ArServerCommands.h"
+#include "ArNetPacket.h"
+#include "ArNetPacketSenderTcp.h"
+#include "ArNetPacketReceiverTcp.h"
+#include "ArNetPacketReceiverUdp.h"
+#include "ArClientData.h"
+
+/**
+ @brief The base client class
+
+ You need to connect a client to a server using blockingConnect() with
+ the address for the server. Then you should add handlers to
+ the client to receive information from the server (with addHandler(),
+ request(), and requestOnce()). Then call run() or runAsync()
+ (or loopOnce() if you really know what you're doing).
+ You can also add a callback that will get called every cycle of the
+ client.
+
+ User and password information may be required by the server.
+ For details on that see ArServerBase. The most important thing is
+ the modification to blockingConnect(), it can now take a user and
+ password argument and upon failure you'll want to check wasRejected()
+ to determine whether the client couldn't find the server or if the user and
+ password were rejected. Another relevant function is setServerKey()
+ to set the key (string of text) we need to connect to the server.
+
+ This class should be thread safe... The only thing you cannot do is
+ call 'addHandler' or 'remHandler' from within a handler for that
+ specific piece of data.
+ **/
+
+class ArClientBase : public ArASyncTask
+{
+public:
+
+ /// The state of the connection
+ enum ClientState {
+ STATE_NO_CONNECTION, ///< The client has not connected
+ STATE_FAILED_CONNECTION, ///< The client tried to connect and failed
+ STATE_OPENED_SOCKET, ///< Client opened socket, waiting for intro from srvr
+ STATE_EXCHANGED_INTROS, ///< Client and server have exchanged introductions
+ STATE_REJECTED, ///< Client was rejected by server
+ STATE_WAITING_LIST, ///< Client was connected to server, waiting for list
+ STATE_CONNECTED, ///< Client is connected to server
+ STATE_LOST_CONNECTION ///< Client lost connection to server
+ };
+
+ enum {
+ CLIENT_KEY_LENGTH = 16
+ };
+
+ enum NonBlockingConnectReturn
+ {
+ NON_BLOCKING_CONTINUE, ///< Client didn't connect or fail to connect yet
+ NON_BLOCKING_CONNECTED, ///< Client connected
+ NON_BLOCKING_FAILED ///< Client couldn't connect
+ };
+
+ /// Constructor
+ AREXPORT ArClientBase();
+ /// Destructor
+ AREXPORT virtual ~ArClientBase();
+
+ /// Sets the optional name of the connected robot for debugging purposes.
+ AREXPORT virtual void setRobotName(const char *name,
+ bool debugLogging = false,
+ int robotId = 0);
+
+ /// Returns the optional name of the connected robot for debugging purposes.
+ AREXPORT virtual const char *getRobotName() const;
+
+ /// Returns the entire string used to prefix log entries for this client base.
+ AREXPORT virtual const char *getLogPrefix() const;
+
+ /// Returns if we're doing debug logging or not
+ AREXPORT bool getDebugLogging(void);
+
+ /// Connect to a server
+ AREXPORT bool blockingConnect(const char *host, int port, bool log = true,
+ const char *user = NULL,
+ const char *password = NULL,
+ const char *openOnIP = NULL);
+
+ /// Disconnect from a server
+ /**
+ * This method blocks while the connection is being shutdown.
+ **/
+ AREXPORT bool disconnect(void);
+
+ /// Disconnect from a server next time through the loop
+ /**
+ * This method does not block while the connection is being
+ * shutdown, and the disconnect only happens the next time the
+ * client base is in its loop
+ **/
+ AREXPORT void disconnectSoon(void);
+
+ /** @return true if we're connected to a server */
+ AREXPORT bool isConnected(void) { return myState == STATE_CONNECTED;}
+
+ /** @return true if a server connection attempt failed because the server rejected the username or password, false if the connection failed for another reason, or the username/password were accepted. */
+ AREXPORT bool wasRejected(void) { return myState == STATE_REJECTED; }
+
+ /// Gets the state of the client
+ AREXPORT ClientState getState(void) { return myState; }
+
+ /// Adds a functor for some particular data
+ AREXPORT bool addHandler(const char *name,
+ ArFunctor1 *functor);
+
+ /// Removes a functor for some particular data by name
+ AREXPORT bool remHandler(const char *name, ArFunctor1 *functor);
+
+ /// Request some data every @a mSec milliseconds
+ AREXPORT bool request(const char *name, long mSec,
+ ArNetPacket *packet = NULL);
+
+ /// Don't want this data anymore
+ AREXPORT bool requestStop(const char *name);
+
+ /// Request some data (or send a command) just once
+ AREXPORT bool requestOnce(const char *name,
+ ArNetPacket *packet = NULL,
+ bool quiet = false);
+
+ /// Request some data (or send a command) just once by UDP
+ AREXPORT bool requestOnceUdp(const char *name,
+ ArNetPacket *packet = NULL,
+ bool quiet = false);
+
+ /// Request some data (or send a command) just once with a string as argument
+ AREXPORT bool requestOnceWithString(const char *name, const char *str);
+
+ /// Sees if this data exists
+ AREXPORT bool dataExists(const char *name);
+
+ /// Gets the name of the host we tried to connect to
+ AREXPORT const char *getHost(void);
+
+
+ /// Sets the 'key' needed to connect to the server
+ AREXPORT void setServerKey(const char *serverKey, bool log = true);
+
+ /// Enforces the that the server is using this protocol version
+ AREXPORT void enforceProtocolVersion(const char *protocolVersion,
+ bool log = true);
+
+ /// Enforces that the robots that connect are this type
+ AREXPORT void enforceType(ArServerCommands::Type type, bool log = true);
+
+ /// Gets the last time a packet was received
+ AREXPORT ArTime getLastPacketReceived(void);
+
+ /// Sets the backup timeout
+ AREXPORT void setBackupTimeout(double timeoutInMins);
+
+ /// Runs the client in this thread
+ AREXPORT virtual void run(void);
+
+ /// Runs the client in its own thread
+ AREXPORT virtual void runAsync(void);
+
+ /// Stops the thread and sets the stopped flag
+ AREXPORT virtual void stopRunning(void);
+
+ /// Returns whether the client has been stopped (regardless of whether its in its own thread)
+ AREXPORT virtual bool isStopped();
+
+ /// Print out or data with descriptions
+ AREXPORT void logDataList(void);
+
+ /// Adds a functor to call every cycle
+ AREXPORT void addCycleCallback(ArFunctor *functor);
+
+ /// Removes a functor called every cycle
+ AREXPORT void remCycleCallback(ArFunctor *functor);
+
+ /// Send a packet over TCP
+ AREXPORT bool sendPacketTcp(ArNetPacket *packet);
+ /// Send a packet over UDP (unless client only wants tcp then sends over tcp)
+ AREXPORT bool sendPacketUdp(ArNetPacket *packet);
+
+ /// Sets the time to allow for connection (default 3)
+ AREXPORT void setConnectTimeoutTime(int sec);
+
+ /// Gets the time allowed for connection
+ AREXPORT int getConnectTimeoutTime(void);
+
+ /// Logs the tracking information (packet and byte counts)
+ AREXPORT void logTracking(bool terse);
+
+ /// Clears the tracking information (resets counters)
+ AREXPORT void resetTracking(void);
+
+ /// Adds a call for when the server shuts down
+ AREXPORT void addServerShutdownCB(ArFunctor *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+
+ /// Removes a call for when the server shuts down
+ AREXPORT void remServerShutdownCB(ArFunctor *functor);
+
+ /// Adds a call for when a disconnection has occured because of error
+ AREXPORT void addDisconnectOnErrorCB(ArFunctor *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+
+ /// Removes a call for when a disconnection has occured because of error
+ AREXPORT void remDisconnectOnErrorCB(ArFunctor *functor);
+
+ /// Run the loop once
+ AREXPORT void loopOnce(void);
+
+ /// Process the packet wherever it came from
+ AREXPORT void processPacket(ArNetPacket *packet, bool tcp);
+
+ /// Process a packet from udp (just hands off to processPacket)
+ AREXPORT void processPacketUdp(ArNetPacket *packet,
+ struct sockaddr_in *sin);
+
+ /// Sets it so we only get TCP data from the server not UDP
+ AREXPORT void setTcpOnlyFromServer(void);
+ /// Sets it so we only send TCP data to the server
+ AREXPORT void setTcpOnlyToServer(void);
+
+ /// Returns whether we only get TCP data from the server not UDP
+ AREXPORT bool isTcpOnlyFromServer(void);
+ /// Returns whether we only send TCP data to the server
+ AREXPORT bool isTcpOnlyToServer(void);
+ /// Gets a (probably) unique key that can be used to identify the client (after connection)
+ AREXPORT void getClientKey(unsigned char key[CLIENT_KEY_LENGTH]);
+
+
+ /// Starts the process of disconnecting from the server.
+ /**
+ * This method should be called in threads that should not block
+ * (such as the main GUI thread). The call should be followed by
+ * a delay of one second, followed by a call to
+ * finishNonBlockingDisconnect().
+ **/
+ AREXPORT bool startNonBlockingDisconnect();
+
+ /// Finishes the process of disconnecting from the server.
+ /**
+ * This method should be used in conjunction with
+ * startNonBlockingDisconnect in threads that should not block
+ * (such as the main GUI thread).
+ **/
+ AREXPORT void finishNonBlockingDisconnect();
+
+ /// Gets the name of the data a packet is for
+ AREXPORT const char *getName(ArNetPacket *packet, bool internalCall = false);
+ /// Gets the name of the data a command is
+ AREXPORT const char *getName(unsigned int command, bool internalCall = false);
+ // the function for the thread
+ AREXPORT virtual void * runThread(void *arg);
+ /// Internal function to get the socket (no one should need this)
+ AREXPORT struct in_addr *getTcpAddr(void) { return myTcpSocket.inAddr(); }
+ /// Internal function that'll do the connection (mainly for switch connections)
+ AREXPORT bool internalBlockingConnect(
+ const char *host, int port, bool log, const char *user,
+ const char *password, ArSocket *tcpSocket,
+ const char *openOnIP = NULL);
+ /// Internal function that'll start the non blocking connection (mainly for switch connections)
+ AREXPORT NonBlockingConnectReturn internalNonBlockingConnectStart(
+ const char *host, int port, bool log, const char *user,
+ const char *password, ArSocket *tcpSocket,
+ const char *openOnIP = NULL);
+ /// Internal function that'll start the non blocking connection (mainly for switch connections)
+ AREXPORT NonBlockingConnectReturn internalNonBlockingConnectContinue(void);
+ /// Internal function to get the tcp socket
+ AREXPORT ArSocket *getTcpSocket(void) { return &myTcpSocket; }
+ /// Internal function to get the udp socket
+ AREXPORT ArSocket *getUdpSocket(void) { return &myUdpSocket; }
+ /// Internal function get get the data map
+ AREXPORT const std::map *getDataMap(void)
+ { return &myIntDataMap; }
+ /// Returns the command number from the name
+ AREXPORT unsigned int findCommandFromName(const char *name);
+ /// Request some data every mSec milliseconds by command not name
+ AREXPORT bool requestByCommand(unsigned int command, long mSec,
+ ArNetPacket *packet = NULL);
+ /// Don't want this data anymore, by command not name
+ AREXPORT bool requestStopByCommand(unsigned int command);
+
+ /// Request some data (or send a command) just once by command not name
+ AREXPORT bool requestOnceByCommand(unsigned int command,
+ ArNetPacket *packet = NULL);
+ /// Request some data (or send a command) just once by command not name
+ AREXPORT bool requestOnceByCommandUdp(unsigned int command,
+ ArNetPacket *packet = NULL);
+ /// Gets if we received the list of commands
+ bool getReceivedDataList(void) { return myReceivedDataList; }
+ /// Gets if we received the list of arguments and
+ bool getReceivedArgRetList(void) { return myReceivedArgRetList; }
+ /// Gets if we received the list of commands
+ bool getReceivedGroupAndFlagsList(void) { return myReceivedGroupAndFlagsList; }
+ /// Tells us the reason the connection was rejected (see ArServerCommands for details)
+ int getRejected(void) { return myRejected; }
+ /// Tells us the reason the connection was rejected (see ArServerCommands for details)
+ const char *getRejectedString(void) { return myRejectedString; }
+protected:
+
+ /// Optional robot name for logging
+ std::string myRobotName;
+ /// Optional prefix to be inserted at the start of log messages
+ std::string myLogPrefix;
+ /// If we're enforcing the version of the protocol or not
+ std::string myEnforceProtocolVersion;
+ /// if we're a particular type
+ ArServerCommands::Type myEnforceType;
+
+ AREXPORT bool setupPacket(ArNetPacket *packet);
+ ArTime myLastPacketReceived;
+ std::list myServerShutdownCBList;
+ std::list myDisconnectOnErrorCBList;
+ std::list myCycleCallbacks;
+ void clear(void);
+ // does the first part of connection
+ bool internalConnect(const char *host, int port, bool obsolete,
+ const char *openOnIP);
+ void internalStartUdp(void);
+ void buildList(ArNetPacket *packet);
+ void internalSwitchState(ClientState state);
+ bool myReceivedDataList;
+ bool myReceivedArgRetList;
+ bool myReceivedGroupAndFlagsList;
+ ClientState myState;
+ ArTime myStateStarted;
+ bool myUdpConfirmedFrom;
+ bool myUdpConfirmedTo;
+ // if we only send tcp
+ bool myTcpOnlyTo;
+ // if we only receive tcp from the server
+ bool myTcpOnlyFrom;
+
+ bool myIsRunningAsync;
+ bool myDisconnectSoon;
+ bool myIsStartedDisconnect;
+ bool myIsStopped;
+
+ bool myQuiet;
+ bool myDebugLogging;
+ ArLog::LogLevel myVerboseLogLevel;
+ std::string myHost;
+ std::string myUser;
+ std::string myPassword;
+ // the time we allow for connections
+ int myTimeoutTime;
+ // the time we started our connection
+ ArTime myStartedConnection;
+ ArTime myStartedUdpConnection;
+ ArTime myStartedShutdown;
+
+ enum NonBlockingConnectState
+ {
+ NON_BLOCKING_STATE_NONE,
+ NON_BLOCKING_STATE_TCP,
+ NON_BLOCKING_STATE_UDP
+ };
+
+ NonBlockingConnectState myNonBlockingConnectState;
+
+
+ ArMutex myDataMutex;
+ ArMutex myClientMutex;
+ ArMutex myMapsMutex;
+ ArMutex myStateMutex;
+ ArMutex myCallbackMutex;
+ ArMutex myCycleCallbackMutex;
+ ArMutex myPacketTrackingMutex;
+ // our map of names to ints
+ std::map myNameIntMap;
+ // our map of ints to functors
+ std::map myIntDataMap;
+
+ struct sockaddr_in myUdpSin;
+ bool myUdpSinValid;
+ // the port the server said it was using
+ unsigned int myServerReportedUdpPort;
+ // the port the server actually is using
+ unsigned int myServerSentUdpPort;
+ unsigned int myUdpPort;
+ long myAuthKey;
+ long myIntroKey;
+ std::string myServerKey;
+ double myBackupTimeout;
+ // this is a key we have for identifying ourselves moderately uniquely
+ unsigned char myClientKey[16];
+ ArNetPacketSenderTcp myTcpSender;
+ ArNetPacketReceiverTcp myTcpReceiver;
+ ArNetPacketReceiverUdp myUdpReceiver;
+ ArSocket myTcpSocket;
+ ArSocket myUdpSocket;
+ ArFunctor2C myProcessPacketCB;
+ ArFunctor2C myProcessPacketUdpCB;
+
+ int myRejected;
+ char myRejectedString[32000];
+
+ ArTime myTrackingStarted;
+ class Tracker
+ {
+ public:
+ Tracker() { reset(); }
+ virtual ~Tracker() {}
+ void reset(void)
+ { myPacketsTcp = 0; myBytesTcp = 0; myPacketsUdp = 0; myBytesUdp = 0; }
+ long myPacketsTcp;
+ long myBytesTcp;
+ long myPacketsUdp;
+ long myBytesUdp;
+ };
+ AREXPORT void trackPacketSent(ArNetPacket *packet, bool tcp);
+ AREXPORT void trackPacketReceived(ArNetPacket *packet, bool tcp);
+ std::map myTrackingSentMap;
+ std::map myTrackingReceivedMap;
+
+};
+
+#endif // NLCLIENTBASE_H
diff --git a/Legacy/Aria/ArNetworking/include/ArClientCommands.h b/Legacy/Aria/ArNetworking/include/ArClientCommands.h
new file mode 100644
index 0000000..2a5497c
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArClientCommands.h
@@ -0,0 +1,24 @@
+#ifndef NLCLIENTCOMMANDS_H
+#define NLCLIENTCOMMANDS_H
+
+/**
+ The commands from the client to the server
+**/
+
+class ArClientCommands
+{
+public:
+ enum ClientCommands {
+ SHUTDOWN = 1, ///< Closes the connection
+ INTRODUCTION = 2, ///< Introduces the client to the server
+ UDP_INTRODUCTION = 3, ///< Udp introduction of the client to the server
+ UDP_CONFIRMATION = 4, ///< Confirmation Udp was received from server
+ TCP_ONLY = 5, ///< Client tells server to only send TCP
+ LIST = 128, ///< Lists the types that can be handled
+ REQUEST = 129, ///< Requests packet of a certain type
+ REQUESTSTOP = 130 ///< Requests that the server stop sending the given type
+ /// You can request any other command once if you know its number just by sending that number
+ };
+};
+
+#endif // NLCLIENTCOMMANDS_H
diff --git a/Legacy/Aria/ArNetworking/include/ArClientData.h b/Legacy/Aria/ArNetworking/include/ArClientData.h
new file mode 100644
index 0000000..c8e206a
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArClientData.h
@@ -0,0 +1,86 @@
+#ifndef ARCLIENTDATA_H
+#define ARCLIENTDATA_H
+
+#include "Aria.h"
+class ArNetPacket;
+
+/// class to hold information about the different data the client has
+/**
+ This class is mostly just for holding all the information about one
+ of the client data entires in one convenient spot
+
+ Information about the data flags held here... The recognized ones
+ right now are just for return values so some forwarding can be done
+ intelligently, you should only have one return value, they are:
+ RETURN_NONE (There are no return packets), RETURN_SINGLE (There is
+ exactly one return packet), RETURN_UNTIL_EMPTY (There return goes
+ until an empty packet), RETURN_VIDEO (this is the special case for
+ video where basically its something thats always requested at an
+ interval and everyone'll want it after we've transfered it),
+ RETURN_COMPLEX (The return is more complex (so you'll need a helper
+ class))
+**/
+
+class ArClientData
+{
+public:
+ /// Constructor
+ AREXPORT ArClientData(const char *name, const char *description,
+ unsigned int command,
+ ArFunctor1 *functor);
+ /// Destructor
+ AREXPORT virtual ~ArClientData();
+ /// Gets the name
+ const char *getName(void) { return myName.c_str(); }
+ /// Gets the description
+ const char *getDescription(void) { return myDescription.c_str(); }
+ unsigned int getCommand(void) { return myCommand; }
+ /// Gets the argument description
+ const char *getArgumentDescription(void)
+ { return myArgumentDescription.c_str(); }
+ /// Gets the return description
+ const char *getReturnDescription(void)
+ { return myReturnDescription.c_str(); }
+ /// Gets the command group
+ const char *getCommandGroup(void) { return myCommandGroup.c_str(); }
+ AREXPORT bool hasDataFlag(const char *dataFlag);
+ const char *getDataFlagsString(void)
+ { return myDataFlagsBuilder.getFullString(); }
+ /// Gets the list of functors
+ const std::list *> *getFunctorList(void) const
+ { return &myFunctorList; };
+ /// Locks the functor list so we can walk it without it changing
+ AREXPORT int lockFunctorList(void) { return myMutex.lock(); }
+ /// Tries to lock the functor list so we can walk it without it changing
+ AREXPORT int tryLockFunctorList(void) { return myMutex.tryLock(); }
+ /// Unlocks the functor list so we can walk it without it changing
+ AREXPORT int unlockFunctorList(void) { return myMutex.unlock(); }
+
+ /// Adds a new functor the end of the list
+ void addFunctor(ArFunctor1 *functor)
+ { myFunctorList.push_back(functor); }
+ /// Removes a functor from the list all together
+ void remFunctor(ArFunctor1 *functor)
+ { myFunctorList.remove(functor); }
+ /// Sets the argument and return descriptions
+ void setArgRetDescs(const char *argDesc, const char *retDesc)
+ { myArgumentDescription = argDesc; myReturnDescription = retDesc; }
+ /// Sets the command group
+ void setCommandGroup(const char *commandGroup)
+ { myCommandGroup = commandGroup; }
+ /// Sets the data flags
+ AREXPORT void addDataFlags(const char *dataFlags);
+protected:
+ std::string myName;
+ std::string myDescription;
+ unsigned int myCommand;
+ std::string myArgumentDescription;
+ std::string myReturnDescription;
+ std::string myCommandGroup;
+ ArMutex myDataMutex;
+ ArArgumentBuilder myDataFlagsBuilder;
+ ArMutex myMutex;
+ std::list *> myFunctorList;
+};
+
+#endif // ARCLIENTDATA_H
diff --git a/Legacy/Aria/ArNetworking/include/ArClientFileUtils.h b/Legacy/Aria/ArNetworking/include/ArClientFileUtils.h
new file mode 100644
index 0000000..de77fef
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArClientFileUtils.h
@@ -0,0 +1,367 @@
+#ifndef ARCLIENTFILEUTILS_H
+#define ARCLIENTFILEUTILS_H
+
+#include "Aria.h"
+#include "ArClientBase.h"
+
+/// The item type that the ArCLientFileLister gets back
+class ArClientFileListerItem
+{
+public:
+ /// Constructor
+ ArClientFileListerItem(const char *name, time_t atime, time_t mtime,
+ ArTypes::UByte4 size)
+ { myName = name; myATime = atime; myMTime = mtime; mySize = size; }
+ /// Copy Constructor
+ ArClientFileListerItem(const ArClientFileListerItem &item)
+ { myName = item.myName; myATime = item.myATime; myMTime = item.myMTime;
+ mySize = item.mySize; }
+ /// Assignment operator
+ AREXPORT ArClientFileListerItem &operator=(const
+ ArClientFileListerItem &item)
+ {
+ if (this != &item)
+ {
+ myName = item.myName; myATime = item.myATime; myMTime = item.myMTime;
+ mySize = item.mySize;
+ }
+ return *this;
+ }
+ /// Destructor
+ virtual ~ArClientFileListerItem() {}
+ /// Gets the name of the list item
+ const char *getName(void) const { return myName.c_str(); }
+ /// Gets the time this list item was last accessed in seconds from 1970
+ time_t getLastAccessedTime(void) const { return myATime; }
+ /// Gets the time this list item was last modified in seconds from 1970
+ time_t getLastModifiedTime(void) const { return myMTime; }
+ /// Gets the size of this list item in bytes
+ ArTypes::UByte4 getSize(void) const { return mySize; }
+protected:
+ std::string myName;
+ time_t myATime;
+ time_t myMTime;
+ ArTypes::UByte4 mySize;
+};
+
+/// Class for getting file list information from the server
+/**
+ This class will interact with the ArServerFileLister and find out
+ whats in directories and change directories and such. This class
+ is all that should be used to get the information from
+ ArServerFileLister, the API between the two is fairly volatile and
+ will remain so. If you need more functionality let us know and
+ we'll add it if its reasonable.
+
+ When you change directories or change to the top dir it doesn't
+ happen right away, but when it happens the update callbacks will be
+ called, 0 as the int for the callback means everything is good,
+ positive error messages are from the server (1 == tried to go
+ outside allowed area, 2 == no such directory), negative are from
+ this class (-1 == got directory but it wasn't what we wanted (if
+ you wait the right one might come in, like if someone selects one
+ dir then the other)).
+**/
+class ArClientFileLister
+{
+public:
+ /// Constructor
+ AREXPORT ArClientFileLister(ArClientBase *client);
+ /// Destructor
+ AREXPORT virtual ~ArClientFileLister();
+ /// Sees if the server supports what this class needs
+ AREXPORT bool isAvailable(void);
+ /// Goes to the top directory
+ AREXPORT void changeToTopDir(void);
+ /// Goes to this directory in the current directory
+ AREXPORT void changeToDir(const char *dir);
+ /// Goes up one directory from current directory
+ AREXPORT void upOneDir(void);
+ /// Goes to this absolute directory
+ AREXPORT void changeToAbsDir(const char *dir);
+ /// Gets the name of the directory we're in
+ AREXPORT const char *getCurrentDir(void) const;
+ /// Gets the name of the directory that we're currently waiting for
+ AREXPORT const char *getWaitingForDir(void) const;
+
+ /// Gets the directories in the current directory
+ AREXPORT std::list getDirectories(void) const;
+ /// Gets the files in the current directory
+ AREXPORT std::list getFiles(void) const;
+ /// Adds a callback for when we get the desired directory info
+ AREXPORT void addUpdatedCallback(ArFunctor1 *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+ /// Removes a callback for when we get the desired directory info
+ AREXPORT void remUpdatedCallback(ArFunctor1 *functor);
+ /// Gets the last time we were updated
+ AREXPORT ArTime getLastUpdated(void);
+ /// Gets the last time we requested an update
+ AREXPORT ArTime getLastRequested(void);
+ /// Logs the current directory
+ AREXPORT void log(bool withTimes);
+protected:
+ AREXPORT void netGetDirListing(ArNetPacket *packet);
+ AREXPORT void netGetDirListingMultiplePackets(ArNetPacket *packet);
+ AREXPORT void callUpdatedCallbacks(int val);
+ AREXPORT void logList(
+ std::list *logThis,
+ bool withTimes);
+ void getDirListing(const char *dir);
+ ArMutex myDataMutex;
+ ArMutex myCallbackMutex;
+ ArClientBase *myClient;
+ char myCurrentDir[2048];
+ char myWaitingForDir[2048];
+ bool myLastDirMatched;
+ bool myNewDirListing;
+ ArTime myLastRequested;
+ ArTime myLastUpdated;
+ std::list myDirectories;
+ std::list myFiles;
+ std::list *> myUpdatedCallbacks;
+ ArFunctor1C myGetDirListingCB;
+ ArFunctor1C myGetDirListingMultiplePacketsCB;
+};
+
+
+/// Class for getting files from the server
+/**
+ This class will interact with the ArServerFileToClient and get a
+ file on the server. If you want to find out what files are on the
+ server use ArClientFileLister.
+
+ When get a file it doesn't happen right away, but when the file is
+ received (or failes) the fileGotten callbacks will be called, 0 as
+ the int for the callback means everything is good, positive error
+ messages are from the server (1 == tried to go outside allowed
+ area, 2 == no such directory, 3 == empty file name, 4 == problem
+ reading file), negative are from this class (-1 == got directory
+ but it wasn't what we wanted (if you wait the right one might come
+ in, like if someone selects one dir then the other), -2 == can't
+ open file to put result into).
+**/
+class ArClientFileToClient
+{
+public:
+ /// Constructor
+ AREXPORT ArClientFileToClient(ArClientBase *client);
+ /// Destructor
+ AREXPORT virtual ~ArClientFileToClient();
+ /// Sees if the server supports what this class needs
+ AREXPORT bool isAvailable(void);
+
+ AREXPORT bool isAvailableSetTimestamp(void);
+
+ /// Get the file from a directory
+ AREXPORT bool getFileFromDirectory(const char *directory,
+ const char *fileName,
+ const char *clientFileName,
+ bool isSetTimestamp = false);
+ /// Cancels getting a file
+ AREXPORT void cancelGet(void);
+ /// If we're getting a file now
+ AREXPORT bool isWaitingForFile(void);
+ /// Gets the directory we're getting from
+ AREXPORT const char *getDirectory(void);
+ /// Gets the filename we're getting
+ AREXPORT const char *getFileName(void);
+ /// Gets the filename we'll save the gotten file in
+ AREXPORT const char *getClientFileName(void);
+ /// Adds a callback for when we get the desired file (or fail)
+ AREXPORT void addFileReceivedCallback(ArFunctor1 *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+ /// Removes a callback for when we get the desired file (or fail)
+ AREXPORT void remFileReceivedCallback(ArFunctor1 *functor);
+
+
+ /// Gets the last time we finished getting a file
+ AREXPORT ArTime getLastReceived(void);
+ /// Gets the last time we asked for a file
+ AREXPORT ArTime getLastRequested(void);
+
+protected:
+
+ AREXPORT void netGetFile(ArNetPacket *packet);
+ AREXPORT void netGetFileWithTimestamp(ArNetPacket *packet);
+ AREXPORT void doGetFile(ArNetPacket *packet,
+ bool isSetTimestamp);
+ AREXPORT void callFileReceivedCallbacks(int val);
+
+
+protected:
+
+ ArMutex myDataMutex;
+ ArMutex myCallbackMutex;
+ ArClientBase *myClient;
+ bool myIsWaitingForFile;
+ std::string myDirectory;
+ std::string myFileName;
+ std::string myWholeFileName;
+ std::string myClientFileName;
+ FILE *myFile;
+
+ ArTime myLastRequested;
+ ArTime myLastReceived;
+
+ std::list *> myFileReceivedCallbacks;
+
+ ArFunctor1C myGetFileCB;
+ ArFunctor1C myGetFileWithTimestampCB;
+};
+
+/// Class for putting files to the server
+/**
+ This class will interact with the ArServerFileFromClient and put a
+ file on to the server. If you want to find out what files are on
+ the server use ArClientFileLister.
+
+ When get a file it doesn't happen right away, but when the file is
+ received (or failes) the fileGotten callbacks will be called, 0 as
+ the int for the callback means everything is good, positive error
+ messages are from the server (0 = good (got file), 1 = getting
+ file, 2 = tried to go outside allowed area, 3 = bad directory, 4 =
+ empty file name (or other problem with fileName), 5 = can't write
+ temp file, 6 = error moving file from temp to perm, 7 = another
+ client putting file, 8 = timeout (no activity for 15 seconds) and
+ another client wanted to put the file, 9 = client adding to,
+ finishing, or canceling a file the server doesn't have), negative
+ would be from this class but there aren't any of those yet
+**/
+class ArClientFileFromClient
+{
+public:
+ /// Constructor
+ AREXPORT ArClientFileFromClient(ArClientBase *client);
+ /// Destructor
+ AREXPORT virtual ~ArClientFileFromClient();
+ /// Sees if the server supports what this class needs
+ AREXPORT bool isAvailable(void);
+ /// Sees if the server supports what this class needs to send slowly
+ AREXPORT bool isAvailableSlow(void);
+ /// Sees if the server supports what this class needs to send fast
+ AREXPORT bool isAvailableFast(void);
+ /// Sees if the server supports the ability to set the file timestamp
+ AREXPORT bool isAvailableSetTimestamp(void);
+
+ /// Enum that describes the speed to send at
+ enum SendSpeed
+ {
+ SPEED_AUTO, ///< Send it fast if available, if not then send it slow
+ SPEED_FAST, ///< Send it fast
+ SPEED_SLOW ///< Send it slow
+ };
+ /// Puts the specified client file on the server in the given directory and file
+ AREXPORT bool putFileToDirectory(const char *directory,
+ const char *fileName,
+ const char *clientFileName,
+ SendSpeed sendSpeed = SPEED_AUTO,
+ bool isSetTimestamp = false);
+ /// Cancels putting a file
+ AREXPORT void cancelPut(void);
+
+ /// If we're waiting for completion now
+ AREXPORT bool isWaitingForReturn(void);
+ /// Gets the directory we're putting to
+ AREXPORT const char *getDirectory(void);
+ /// Gets the filename we're putting
+ AREXPORT const char *getFileName(void);
+ /// Gets the filename we're taking from the client
+ AREXPORT const char *getClientFileName(void);
+ /// Adds a callback for when we get the desired file (or fail)
+ AREXPORT void addFileSentCallback(ArFunctor1 *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+ /// Removes a callback for when we get the desired file (or fail)
+ AREXPORT void remFileSentCallback(ArFunctor1 *functor);
+ /// Gets the last time we finished putting a file
+ AREXPORT ArTime getLastCompletedSend(void);
+ /// Gets the last time we started putting a file
+ AREXPORT ArTime getLastStartedSend(void);
+protected:
+ AREXPORT void netPutFile(ArNetPacket *packet);
+ AREXPORT void callFileSentCallbacks(int val);
+
+ ArMutex myDataMutex;
+ ArMutex myCallbackMutex;
+ ArClientBase *myClient;
+ bool myIsWaitingForReturn;
+ bool myInterleaved;
+ bool myTimestamp;
+ std::string myCommandName;
+ std::string myDirectory;
+ std::string myFileName;
+ std::string myWholeFileName;
+ std::string myClientFileName;
+
+ bool myReadyForNextPacket;
+ FILE *myFile;
+ ArTime myLastStartedSend;
+ ArTime myLastCompletedSend;
+ std::list *> myFileSentCallbacks;
+ ArFunctor1C myPutFileCB;
+};
+
+
+/// Class for deleting a file on the server
+/**
+ This class will interact with the ArServerFileFromClient and put a
+ file on to the server. If you want to find out what files are on
+ the server use ArClientFileLister.
+
+ When get a file it doesn't happen right away, but when the file is
+ received (or failes) the fileGotten callbacks will be called, 0 as
+ the int for the callback means everything is good, positive error
+ messages are from the server (0 = good (got file), 1 = getting
+ file, 2 = tried to go outside allowed area, 3 = bad directory, 4 =
+ empty file name (or other problem with fileName), 5 = can't write
+ temp file, 6 = error moving file from temp to perm, 7 = another
+ client putting file, 8 = timeout (no activity for 15 seconds) and
+ another client wanted to put the file, 9 = client adding to,
+ finishing, or canceling a file the server doesn't have), negative
+ would be from this class but there aren't any of those yet
+**/
+class ArClientDeleteFileOnServer
+{
+public:
+ /// Constructor
+ AREXPORT ArClientDeleteFileOnServer(ArClientBase *client);
+ /// Destructor
+ AREXPORT virtual ~ArClientDeleteFileOnServer();
+ /// Sees if the server supports what this class needs
+ AREXPORT bool isAvailable(void);
+ /// Get the file from a directory
+ AREXPORT bool deleteFileFromDirectory(const char *directory,
+ const char *fileName);
+ /// If we're waiting for completion now
+ AREXPORT bool isWaitingForReturn(void);
+ /// Gets the directory we're putting to
+ AREXPORT const char *getDirectory(void);
+ /// Gets the filename we're putting
+ AREXPORT const char *getFileName(void);
+ /// Adds a callback for when we get the desired file (or fail)
+ AREXPORT void addFileDeletedCallback(ArFunctor1 *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+ /// Removes a callback for when we get the desired file (or fail)
+ AREXPORT void remFileDeletedCallback(ArFunctor1 *functor);
+ /// Gets the last time we finished putting a file
+ AREXPORT ArTime getLastCompletedSend(void);
+ /// Gets the last time we started putting a file
+ AREXPORT ArTime getLastStartedSend(void);
+protected:
+ AREXPORT void netDeleteFile(ArNetPacket *packet);
+ AREXPORT void callFileDeletedCallbacks(int val);
+ ArMutex myDataMutex;
+ ArMutex myCallbackMutex;
+ ArClientBase *myClient;
+ bool myIsWaitingForReturn;
+ std::string myDirectory;
+ std::string myFileName;
+ std::string myWholeFileName;
+ FILE *myFile;
+ ArTime myLastStartedSend;
+ ArTime myLastCompletedSend;
+ std::list *> myFileDeletedCallbacks;
+ ArFunctor1C myDeleteFileCB;
+};
+
+#endif //ARCLIENTFILEUTILS_H
diff --git a/Legacy/Aria/ArNetworking/include/ArClientHandlerConfig.h b/Legacy/Aria/ArNetworking/include/ArClientHandlerConfig.h
new file mode 100644
index 0000000..7d4d1f3
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArClientHandlerConfig.h
@@ -0,0 +1,223 @@
+#ifndef ARCLIENTCONFIGHANDLER_H
+#define ARCLIENTCONFIGHANDLER_H
+
+#include "Aria.h"
+#include "ArClientBase.h"
+
+/// Client handler for receiving and updating ArConfig data via ArNetworking.
+/**
+ * ArClientHandlerConfig processes the network packets that describe a
+ * robot's ArConfig. It also provides a means to save the modified
+ * configuration data to the robot server. This class is designed to
+ * work in conjunction with the ArServerHandlerConfig. See the server
+ * handler documentation for a complete description of the networking
+ * interface.
+ *
+ * This class should be thread safe, with the exception of
+ * unThreadSafeGetConfig. (If you want to use this method, surround it
+ * with calls to lock() and unlock().)
+ *
+ * Note that you can't add callbacks or remove callbacks from within a
+ * callback function.
+**/
+class ArClientHandlerConfig
+{
+public:
+ /// Constructor
+ AREXPORT ArClientHandlerConfig(ArClientBase *client,
+ bool ignoreBounds = false,
+ const char *robotName = NULL,
+ const char *logPrefix = NULL);
+ /// Destructor
+ AREXPORT virtual ~ArClientHandlerConfig(void);
+
+ /// Requests the config from the server
+ AREXPORT void requestConfigFromServer(void);
+ /// Tells the server to reload the configuration
+ AREXPORT void reloadConfigOnServer(void);
+
+ /// Threadsafe way to get the config to play with
+ AREXPORT ArConfig getConfigCopy(void);
+
+ /// Adds a gotConfig callback
+ AREXPORT void addGotConfigCB(ArFunctor *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+ /// Removes a gotConfig callback
+ AREXPORT void remGotConfigCB(ArFunctor *functor);
+ /// Adds a save config to server succeeded callback
+ AREXPORT void addSaveConfigSucceededCB(ArFunctor *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+ /// Removes a save config to server succeeded callback
+ AREXPORT void remSaveConfigSucceededCB(ArFunctor *functor);
+ /// Adds a save config to server failed callback
+ AREXPORT void addSaveConfigFailedCB(ArFunctor1 *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+ /// Removes a save config to server failed callback
+ AREXPORT void remSaveConfigFailedCB(ArFunctor1 *functor);
+
+ /// Returns true if config gotten
+ AREXPORT bool haveGottenConfig(void);
+ /// Sends the config back to the server
+ AREXPORT void saveConfigToServer(void);
+ /// Sends the config back to the server
+ AREXPORT void saveConfigToServer(
+ ArConfig *config,
+ const std::set *ignoreTheseSections = NULL);
+
+ /// Returns if we've requested some defaults
+ AREXPORT bool haveRequestedDefaults(void);
+ /// Returns if we've gotten our requested defaults
+ AREXPORT bool haveGottenDefaults(void);
+
+ /// Sees if we can request defaults (both types)
+ AREXPORT bool canRequestDefaults(void);
+
+ AREXPORT bool requestDefaultConfigFromServer(void);
+ AREXPORT ArConfig *getDefaultConfig();
+
+ /// Requests defaults for all sections from the server; modifies the config
+ AREXPORT bool requestConfigDefaults(void);
+ /// Requests defaults for one section from the server; modifies the config
+ AREXPORT bool requestSectionDefaults(const char *section);
+
+
+ /// Adds a got config defaults callback
+ AREXPORT void addGotConfigDefaultsCB(ArFunctor *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+ /// Removes a got config defaults callback
+ AREXPORT void remGotConfigDefaultsCB(ArFunctor *functor);
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Last Editable Priority
+ //
+ // This value designates the last priority (highest numerical value) for
+ // which parameters may be edited. For example, when this value is set to
+ // EXPERT, then the user may not edit FACTORY parameters.
+ //
+ // If editable priority levels are supported and the client wishes to
+ // receive parameters of ineditable priorities, then the method
+ // requestLastEditablePriority should be called (and completed) before
+ // requestConfigFromServer is called.
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ /// Returns whether the server supports the last editable priority request.
+ AREXPORT bool isLastEditablePriorityAvailable();
+
+ /// Requests the last editable priority from the server
+ AREXPORT bool requestLastEditablePriorityFromServer();
+
+ /// Returns whether the last editable priority has been received from the server
+ AREXPORT bool haveGottenLastEditablePriority();
+ /// Returns the last editable priority of the config
+ AREXPORT ArPriority::Priority getLastEditablePriority();
+
+ /// Adds callback invoked when the last editable priority packet is received
+ AREXPORT void addGotLastEditablePriorityCB
+ (ArFunctor *functor,
+ int position = 50);
+ /// Removes the specified callback from the list of last editable priority callbacks
+ AREXPORT void remGotLastEditablePriorityCB(ArFunctor *functor);
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ /// Unthreadsafe way to get the config to play with (see long docs)
+ AREXPORT ArConfig *getConfig(void);
+ /// Locks the config for if you're using the unthreadsafe getConfig
+ AREXPORT int lock(void);
+ /// Try to lock for the config for if you're using the unthreadsafe getConfig
+ AREXPORT int tryLock(void);
+ /// Unlocks the config for if you're using the unthreadsafe getConfig
+ AREXPORT int unlock(void);
+
+ /// Turn on this flag to reduce the number of verbose log messages.
+ AREXPORT void setQuiet(bool isQuiet);
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Packet Handlers
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ /// Handles the packet from the GetConfigBySectionsV3
+ AREXPORT void handleGetConfigBySectionsV3(ArNetPacket *packet);
+
+ /// Handles the packet from the GetConfigBySectionsV2
+ AREXPORT void handleGetConfigBySectionsV2(ArNetPacket *packet);
+
+ /// Handles the packet from the GetConfigBySections
+ AREXPORT void handleGetConfigBySections(ArNetPacket *packet);
+
+ /// Handles the packet from the GetConfigSectionFlags
+ AREXPORT void handleGetConfigSectionFlags(ArNetPacket *packet);
+
+ /// Handles the packet from the getConfig
+ AREXPORT void handleGetConfig(ArNetPacket *packet);
+
+ /// Handles the return packet from the setConfig (saveConfigToServer)
+ AREXPORT void handleSetConfig(ArNetPacket *packet);
+
+ /// Handles the return packet from the setConfigBySections (saveConfigToServer)
+ AREXPORT void handleSetConfigBySections(ArNetPacket *packet);
+
+ /// Handles the return packet from the setConfigBySectionsV2 (saveConfigToServer)
+ AREXPORT void handleSetConfigBySectionsV2(ArNetPacket *packet);
+
+ /// Handles the return packet from getConfigDefaults
+ AREXPORT void handleGetConfigDefaults(ArNetPacket *packet);
+
+ /// Handles the return packet from getLastEditablePriority
+ AREXPORT void handleGetLastEditablePriority(ArNetPacket *packet);
+
+protected:
+
+ AREXPORT void handleGetConfigData(ArNetPacket *packet,
+ bool isMultiplePackets,
+ int version);
+
+
+protected:
+
+ std::string myRobotName;
+ std::string myLogPrefix;
+
+ std::list myGotConfigCBList;
+ std::list mySaveConfigSucceededCBList;
+ std::list *> mySaveConfigFailedCBList;
+ std::list myGotConfigDefaultsCBList;
+ ArCallbackList myGotLastEditablePriorityCBList;
+
+ ArClientBase *myClient;
+
+ ArConfig myConfig;
+ ArConfig *myDefaultConfig;
+ ArPriority::Priority myLastEditablePriority;
+
+ ArMutex myDataMutex;
+ ArMutex myCallbackMutex;
+
+ bool myHaveRequestedLastEditablePriority;
+ bool myHaveGottenLastEditablePriority;
+ bool myHaveRequestedConfig;
+ bool myHaveGottenConfig;
+ bool myHaveRequestedDefaults;
+ bool myHaveGottenDefaults;
+ bool myHaveRequestedDefaultCopy;
+
+ bool myIsQuiet;
+
+ ArFunctor1C myHandleGetConfigBySectionsV3CB;
+ ArFunctor1C myHandleGetConfigBySectionsV2CB;
+ ArFunctor1C myHandleGetConfigBySectionsCB;
+ ArFunctor1C myHandleGetConfigCB;
+ ArFunctor1C myHandleSetConfigCB;
+ ArFunctor1C myHandleSetConfigBySectionsCB;
+ ArFunctor1C myHandleSetConfigBySectionsV2CB;
+ ArFunctor1C myHandleGetConfigDefaultsCB;
+ ArFunctor1C myHandleGetDefaultConfigCB;
+ ArFunctor1C myHandleGetConfigSectionFlagsCB;
+ ArFunctor1C myHandleGetLastEditablePriorityCB;
+};
+
+#endif
diff --git a/Legacy/Aria/ArNetworking/include/ArClientSimpleConnector.h b/Legacy/Aria/ArNetworking/include/ArClientSimpleConnector.h
new file mode 100644
index 0000000..84adfea
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArClientSimpleConnector.h
@@ -0,0 +1,71 @@
+#ifndef ARCLIENTSIMPLECONNECTOR_H
+#define ARCLIENTSIMPLECONNECTOR_H
+
+#include "Aria.h"
+#include "ArClientBase.h"
+
+/**
+ This will let you connect to different hosts, ports, and with
+ different users and passwords more easily.
+
+ Some program command line options affect behavior:
+ @verbinclude ArClientSimpleConnector_options
+
+ To set the host the client will connect to use '-hosthostName'
+ in the command line parameters
+ (no abbreviation for this since -h is for help and it's only 4
+ letters). To set the port the client will connect to use '-port
+ portNumber' or '-pportNumber'.
+ To set the user to connect with
+ use '-useruserName' or '-uuserName'.
+ To set the password to
+ connect with use '-passwordpassword' or
+ '-pwdpassword'. To
+ use no password use '-nopassword' or '-np'.
+ Note that for using
+ passwords you should NOT use that option on the command line since
+ that can show everyone what the password is (especially in Linux),
+ it's there only for testing. If you give it a username without a
+ password it'll ask you for a password, if you don't have a password
+ just use the -nopassword or let it ask you for a password and hit
+ enter. To set the server key (string we need to connect to the
+ server) use '-setServerKeyserverKey' or
+ '-sskserverKey'.
+ **/
+class ArClientSimpleConnector
+{
+public:
+ /// Constructor that takes argument parser (prefered)
+ AREXPORT ArClientSimpleConnector(ArArgumentParser *parser);
+ /// Constructor that takes args from main (not prefered)
+ AREXPORT ArClientSimpleConnector(int *argc, char **argv);
+ /// Constructor that takes argument builder (not prefered)
+ AREXPORT ArClientSimpleConnector(ArArgumentBuilder *arguments);
+ /// Destructor
+ AREXPORT ~ArClientSimpleConnector(void);
+ /// Connects the client with the options given
+ AREXPORT bool connectClient(ArClientBase *client, bool log = true);
+ /// Parses the arguments
+ AREXPORT bool parseArgs(void);
+ /// Parses the arguments
+ AREXPORT bool parseArgs(ArArgumentParser *parser);
+ /// Logs the options the connector has
+ AREXPORT void logOptions(void) const;
+protected:
+ void reset(void);
+ const char *myHost;
+ const char *myUser;
+ const char *myPassword;
+ const char *myServerKey;
+ int myPort;
+ bool myNoPassword;
+ bool myLogDataList;
+ // our parser
+ ArArgumentParser *myParser;
+ bool myOwnParser;
+
+ ArRetFunctorC myParseArgsCB;
+ ArConstFunctorC myLogOptionsCB;
+};
+
+#endif // ARCLIENTSIMPLECONNECTOR_H
diff --git a/Legacy/Aria/ArNetworking/include/ArClientSwitchManager.h b/Legacy/Aria/ArNetworking/include/ArClientSwitchManager.h
new file mode 100644
index 0000000..7019eb5
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArClientSwitchManager.h
@@ -0,0 +1,187 @@
+#ifndef ARCLIENTSWITCH_H
+#define ARCLIENTSWITCH_H
+
+#include "Aria.h"
+#include "ArServerBase.h"
+#include "ArClientBase.h"
+
+/**
+ The serverInfoFile takes the form of a config file roughly, there
+ are 3 things you can put in it now. 'user user', 'password
+ password' and 'serverKey serverKey'. Note that it loads these
+ files sequentially so if you pass it 5 files it'll read them in the
+ order they were passed in. If you give it just the keyword but not
+ the value (ie 'user') then it'll clear out that value.
+
+ Some program command line options can be used to configure this class:
+ @verbinclude ArClientSwitchManager_options
+**/
+class ArClientSwitchManager : public ArASyncTask
+{
+public:
+ AREXPORT ArClientSwitchManager(
+ ArServerBase *serverBase,
+ ArArgumentParser *parser,
+ const char *serverDescription = "Central Server",
+ const char *clientSoftwareDescription = "Software");
+ AREXPORT virtual ~ArClientSwitchManager();
+ /// Returns if we're connected or not
+ AREXPORT bool isConnected(void);
+ /// Function to parse the arguments given in the constructor
+ AREXPORT bool parseArgs(void);
+ /// Log the options the simple connector has
+ AREXPORT void logOptions(void) const;
+ /// Gets the hostname we're using for the central server (NULL means we're not trying to sue the central server)
+ AREXPORT const char *getCentralServerHostName(void);
+ /// Gets the identifier we're using
+ AREXPORT const char *getIdentifier(void);
+ /// Sets the identifier we're using
+ AREXPORT void setIdentifier(const char *identifier)
+ { myIdentifier = identifier; }
+
+ /// Enforces the that the server is using this protocol version
+ AREXPORT void enforceProtocolVersion(const char *protocolVersion);
+ /// Enforces that the robots that connect are this type
+ AREXPORT void enforceType(ArServerCommands::Type type);
+
+ /// Gets the config display hint items dependent on the central
+ /// server should use (still check getCentralServerHostName to see
+ /// if it's being used)
+ const char *getConfigDisplayHint(void)
+ { return myConfigDisplayHint.c_str(); }
+
+ /// The handler for the response to the switch command
+ AREXPORT void clientSwitch(ArNetPacket *packet);
+ /// The handler for the packet to let the server know we're still talking to it
+ AREXPORT void netCentralHeartbeat(ArServerClient *client,
+ ArNetPacket *packet);
+ /// The handler for the packet that comes from the server so we know
+ /// we're getting these
+ AREXPORT void netCentralServerHeartbeat(ArServerClient *client,
+ ArNetPacket *packet);
+
+ /// Parses the file for holding the user, password, and server key
+ AREXPORT bool parseFile(const char *fileName);
+ AREXPORT virtual void *runThread(void *arg);
+
+ /// Sets debug logging
+ AREXPORT void setDebugLogging(bool debugLogging = false)
+ { myDebugLogging = debugLogging; }
+ /// Gets if this is using debug logging
+ AREXPORT bool getDebugLogging(void) { return myDebugLogging; }
+
+ /// Gets the server client the forwarder is using (internal)
+ /**
+ @internal
+ **/
+ AREXPORT ArServerClient* getServerClient(void)
+ { return myServerClient; }
+
+ /// Adds central server or identifier not passed into the config
+ AREXPORT void addToConfig(const char *configSection,
+ const char *connectName, const char *connectDesc,
+ const char *addressName, const char *addressDesc);
+
+ /// Adds a callback when we switch states while starting
+ AREXPORT void addFailedConnectCB(
+ ArFunctor1 *functor, int position = 50)
+ { myFailedConnectCBList.addCallback(functor, position); }
+ /// Removes a callback when we switch to running
+ AREXPORT void remFailedConnectCB(ArFunctor1 *functor)
+ { myFailedConnectCBList.remCallback(functor); }
+
+ /// Adds a callback when we switch states while starting
+ AREXPORT void addConnectedCB(
+ ArFunctor1 *functor, int position = 50)
+ { myConnectedCBList.addCallback(functor, position); }
+ /// Removes a callback when we switch to running
+ AREXPORT void remConnectedCB(ArFunctor1 *functor)
+ { myConnectedCBList.remCallback(functor); }
+
+
+protected:
+ AREXPORT void socketClosed(void);
+ ArServerBase *myServer;
+ ArArgumentParser *myParser;
+ std::string myServerDesc;
+ std::string myClientSoftwareDesc;
+
+ ArServerClient *myServerClient;
+ ArTime myLastTcpHeartbeat;
+ ArTime myLastUdpHeartbeat;
+
+ ArFileParser myFileParser;
+
+ bool myServerHasHeartbeat;
+ double myServerHeartbeatTimeout;
+ double myServerUdpHeartbeatTimeout;
+ double myServerBackupTimeout;
+
+ bool fileUserCallback(ArArgumentBuilder *arg);
+ bool filePasswordCallback(ArArgumentBuilder *arg);
+ bool fileServerKeyCallback(ArArgumentBuilder *arg);
+
+ enum State
+ {
+ IDLE, ///< Don't want to connect
+ TRYING_CONNECTION, ///< If we're trying to connect
+ CONNECTING, ///< If we're waiting for the response from the server
+ CONNECTED, ///< If we're connected
+ LOST_CONNECTION ///< If we lost a connection... wait a bit and try again
+ };
+ State myState;
+ ArTime myStartedState;
+ ArTime myLastConnectionAttempt;
+ //bool myGaveTimeWarning;
+
+ bool processFile(void);
+ AREXPORT void switchState(State state);
+
+ ArMutex myDataMutex;
+
+ bool myTryConnection;
+ ArClientBase *myClient;
+
+ std::string myUser;
+ std::string myPassword;
+ std::string myServerKey;
+
+ std::string myCentralServer;
+ int myCentralServerPort;
+ std::string myIdentifier;
+
+ std::string myEnforceProtocolVersion;
+ ArServerCommands::Type myEnforceType;
+
+ bool myConfigFirstProcess;
+ bool myConfigConnectToCentralServer;
+ char myConfigCentralServer[1024];
+ char myConfigIdentifier[1024];
+ std::string myConfigDisplayHint;
+
+ ArCallbackList1 myFailedConnectCBList;
+ ArCallbackList1 myConnectedCBList;
+
+ bool myDebugLogging;
+
+ ArRetFunctorC myParseArgsCB;
+ ArConstFunctorC myLogOptionsCB;
+ ArFunctorC mySocketClosedCB;
+ ArFunctor1C mySwitchCB;
+ ArFunctor2C myNetCentralHeartbeatCB;
+ ArFunctor2C myNetCentralServerHeartbeatCB;
+ ArRetFunctor1C myFileUserCB;
+ ArRetFunctor1C myFilePasswordCB;
+ ArRetFunctor1C myFileServerKeyCB;
+ ArRetFunctorC myProcessFileCB;
+
+};
+
+
+#endif // ARCLIENTSWITCH_H
+
diff --git a/Legacy/Aria/ArNetworking/include/ArHybridForwarderVideo.h b/Legacy/Aria/ArNetworking/include/ArHybridForwarderVideo.h
new file mode 100644
index 0000000..63f9312
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArHybridForwarderVideo.h
@@ -0,0 +1,88 @@
+#ifndef ARHYBRIDFORWARDERVIDEO_H
+#define ARHYBRIDFORWARDERVIDEO_H
+
+#include "Aria.h"
+#include "ArServerBase.h"
+#include "ArClientBase.h"
+
+/// This class takes video another source and serves it back up
+class ArHybridForwarderVideo : public ArCameraCollectionItem
+{
+public:
+ /// Constructor that takes a client
+ AREXPORT ArHybridForwarderVideo(ArServerBase *server, ArClientBase *client);
+ /// Constructor that just takes a host and port and makes its own client
+ AREXPORT ArHybridForwarderVideo(ArServerBase *server,
+ const char *hostname = "localhost",
+ int port = 7070);
+ /// Destructor
+ AREXPORT virtual ~ArHybridForwarderVideo();
+
+ /// Returns if we're forwarding video or not
+ AREXPORT bool isForwardingVideo(void) const;
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // ArCameraCollectionItem methods
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ /// Returns the name of the camera handled by this item.
+ AREXPORT virtual const char *getCameraName();
+
+ /// Sets the name of the camera handled by this item.
+ /**
+ * This method must be called before addToCameraCollection().
+ **/
+ AREXPORT virtual void setCameraName(const char *cameraName);
+
+ /// Adds this item to the given camera collection.
+ AREXPORT virtual void addToCameraCollection(ArCameraCollection &collection);
+
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Packet methods
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ /// Sends the last received video size (just gets this once)
+ AREXPORT void sendVideoSize(ArServerClient *client, ArNetPacket *packet);
+ /// Sends the last received video
+ AREXPORT void sendVideo(ArServerClient *client, ArNetPacket *packet);
+ /// Receives the video size (just gets this once)
+ AREXPORT void receiveVideoSize(ArNetPacket *packet);
+ /// Receives the video (and sets a timer to wait a bit and get it again)
+ AREXPORT void receiveVideo(ArNetPacket *packet);
+ /// Our callback that requests more video
+ AREXPORT void clientCycleCallback(void);
+ /// Sets how often after getting video we ask for it again
+ void setVideoRequestTime(int ms) { myVideoRequestTime = ms; }
+ /// Gets how often after getting video we ask for it again
+ int setVideoRequestTime(void) const { return myVideoRequestTime; }
+protected:
+ AREXPORT void finishConstructor(void);
+
+ std::string myCameraName;
+
+ ArMutex myMutex;
+ bool myForwardingVideo;
+ ArNetPacket myReceivedVideoSize;
+ ArNetPacket myReceivedVideo;
+ ArNetPacket mySendVideoArgument;
+ ArTime myLastReceivedVideo;
+ ArTime myLastReqSent;
+ bool myReqSent;
+ int myVideoRequestTime;
+ ArServerBase *myServer;
+ ArClientBase *myClient;
+ ArFunctor2C *mySendVideoSizeCB;
+ ArFunctor2C *mySendVideoCB;
+ ArFunctor1C *myReceiveVideoSizeCB;
+ ArFunctor1C *myReceiveVideoCB;
+ ArFunctorC *myClientCycleCB;
+
+ bool myIsSendVideoAvailable;
+};
+
+
+#endif
diff --git a/Legacy/Aria/ArNetworking/include/ArMapChanger.h b/Legacy/Aria/ArNetworking/include/ArMapChanger.h
new file mode 100644
index 0000000..aa052e7
--- /dev/null
+++ b/Legacy/Aria/ArNetworking/include/ArMapChanger.h
@@ -0,0 +1,557 @@
+#ifndef ARMAPCHANGER_H
+#define ARMAPCHANGER_H
+
+#include "ariaTypedefs.h"
+#include "ariaUtil.h"
+
+#include
+
+#include
+#include
+#include
+
+#include "ArNetPacket.h"
+#include "ArCentralForwarder.h"
+#include "ArClientBase.h"
+#include "ArClientSwitchManager.h"
+#include "ArServerBase.h"
+#include "ArServerClient.h"
+#include "ArMapChanger.h"
+
+/// Utility class used to apply incremental changes to an Aria map.
+/**
+ * ArMapChanger is a helper class that can send and receive ArMapChangeDetails
+ * over the network and apply them to an associated Aria map. An instance of
+ * ArMapChanger must be instantiated on both the client and the server side.
+ * (Note that there are two different versions of the constructors for this.)
+ *
+ * TODO: Possibly subclass this into ArClientMapChanger and ArServerMapChanger?
+ *
+ * @see ArMapChangeDetails
+**/
+class ArMapChanger
+{
+public:
+
+ /// Reply status for a map change request
+ enum MapChangeReplyType {
+ CHANGE_FAILED = 0,
+ CHANGE_SUCCESS = 10
+ };
+
+ /// Name of the network packet that contains the incremental map changes.
+ static const char *PROCESS_CHANGES_PACKET_NAME;
+
+ /// Name of the network packet that contains incremental map changes originated by the robot.
+ static const char *PROCESS_ROBOT_CHANGES_PACKET_NAME;
+
+ /// Name of a network packet that is broadcast when the map is being changed.
+ static const char *CHANGES_IN_PROGRESS_PACKET_NAME;
+
+ /// Name of the network packet that is broadcast when map changes originated by the robot are complete.
+ static const char *ROBOT_CHANGES_COMPLETE_PACKET_NAME;
+
+ // ---------------------------------------------------------------------------
+ // Constructors, Destructor
+ // ---------------------------------------------------------------------------
+
+ /// Constructs a server map changer.
+ /**
+ * The map changer will automatically apply the received map change details
+ * to the given map.
+ *
+ * @param server the ArServerBase * that receives the network packets
+ * @param map the ArMapInterface * to which to apply the map changes
+ **/
+ AREXPORT ArMapChanger(ArServerBase *server,
+ ArMapInterface *map);
+
+ /// Constructs a server map changer that can also originate changes (to the EM).
+ /**
+ * The map changer will automatically apply the received map change details
+ * to the given map.
+ *
+ * @param clientSwitch the ArClientSwitchManager * that communicates to the EM
+ * @param server the ArServerBase * that receives the network packets
+ * @param map the ArMapInterface * to which to apply the map changes
+ **/
+ AREXPORT ArMapChanger(ArClientSwitchManager *clientSwitch,
+ ArServerBase *server,
+ ArMapInterface *map);
+
+
+ /// Constructs a client map changer.
+ /**
+ * The map changer will send map change details to the server. The application
+ * must request this by calling sendMapChanges.
+ *
+ * @param client the ArClientBase * which is used to send the map change details
+ * @param infoNames the list of info names included in the map
+ **/
+ AREXPORT ArMapChanger(ArClientBase *client,
+ const std::list &infoNames);
+
+ /// Constructs a stand-alone map changer that will apply changes to the given map.
+ /**
+ * This method is primarily used for debugging.
+ *
+ * @param map the ArMapInterface * to which to apply the map changes
+ **/
+ AREXPORT ArMapChanger(ArMapInterface *map);
+
+ /// Destructor
+ AREXPORT virtual ~ArMapChanger();
+
+ // ---------------------------------------------------------------------------
+ // Main Methods
+ // ---------------------------------------------------------------------------
+
+ /// Sends the given map changes from the client to the server.
+ AREXPORT virtual bool sendMapChanges(ArMapChangeDetails *changeDetails);
+
+ /// Sends the given map changes from the robot to the central server.
+ AREXPORT virtual bool sendRobotMapChanges(ArMapChangeDetails *changeDetails);
+
+ /// Applies the given map changes received from the client to the associated Aria map.
+ AREXPORT virtual bool applyMapChanges(ArMapChangeDetails *changeDetails);
+
+ /// Transmits the given map change packet list from the client to the server.
+ AREXPORT virtual bool sendPacketList(const std::list &packetList);
+
+ /// Transmit the given map change packet list from the robot to the central server.
+ AREXPORT virtual bool sendRobotPacketList(const std::list &packetList);
+
+ // ---------------------------------------------------------------------------
+ // Callback Methods
+ // ---------------------------------------------------------------------------
+
+ /// Adds a callback to be invoked after the map has been changed on the server.
+ /**
+ * This method is primarily used on the central server. After the map changes
+ * are successfully applied to its map, they are propagated to all of the
+ * connected robots.
+ **/
+ AREXPORT virtual bool addChangeCB
+ (ArFunctor2 *> *functor);
+
+ /// Removes a callback from the map change list.
+ AREXPORT virtual bool remChangeCB
+ (ArFunctor2 *> *functor);
+
+ /// Adds a callback to be invoked after the remote reply has been received.
+ /**
+ * This method is primarily used on the robot. After the ARCL originated
+ * changes have been applied by the Enterprise Manager, this callback list
+ * is invoked for other interested parties.
+ **/
+ AREXPORT virtual bool addRobotChangeReplyCB
+ (ArFunctor2 *functor);
+
+ /// Removes a callback from the remote reply list.
+ AREXPORT virtual bool remRobotChangeReplyCB
+ (ArFunctor2 *functor);
+
+ /// Adds a callback to be invoked before the map file is written.
+ /**
+ * This method is primarily used to temporarily make the server's directory
+ * writeable, if necessary.
+ **/
+ AREXPORT virtual void addPreWriteFileCB(ArFunctor *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+
+ /// Removes a callback from the pre-write file list.
+ AREXPORT virtual void remPreWriteFileCB(ArFunctor *functor);
+
+ /// Adds a callback to be invoked after the map file has been written.
+ /**
+ * This method is primarily used to restore the server's directory write status,
+ * if necessary.
+ **/
+ AREXPORT virtual void addPostWriteFileCB(ArFunctor *functor,
+ ArListPos::Pos position = ArListPos::LAST);
+
+ /// Removes a callback from the post-write file list.
+ AREXPORT virtual void remPostWriteFileCB(ArFunctor *functor);
+
+// -----------------------------------------------------------------------------
+
+protected:
+
+ /// Indicates the current stage of the map change network packets.
+ enum MapChangeCommand {
+ START_CHANGES = 0, ///< First packet that contains changes to be applied to the map
+ CONTINUE_CHANGES = 1, ///< Request to continue applying changes to the map
+ FINISH_CHANGES = 2, ///< Last packet that contains changes to be applied to the map
+ CANCEL_CHANGES = 3, ///< Cancel the request to change the map
+ LAST_CHANGE_COMMAND = CANCEL_CHANGES ///< Last value in the enumeration
+ };
+
+ /// Type of data contained in the map change network packet
+ enum MapChangeDataType {
+ NO_CHANGE = 0, ///< No change data
+ SUMMARY_DATA = 1, ///< Summary data, e.g. min/max pos, number of points
+ INFO_DATA = 2, ///< Any of the info data, e.g. MapInfo, RouteInfo
+ SUPPLEMENT_DATA = 3, ///< Miscellaneous supplemental data such as origin lat/long/alt
+ OBJECTS_DATA = 4, ///< Map objects, i.e. Cairn lines
+ POINTS_DATA = 5, ///< Map data points
+ LINES_DATA = 6, ///< Map data lines
+ LAST_CHANGE_DATA_TYPE = LINES_DATA ///< Last value in the enumeration
+ };
+
+ /// Miscellaneous constants
+ enum {
+ CHANGE_DATA_TYPE_COUNT = LAST_CHANGE_DATA_TYPE + 1,
+ CHANGE_COMMAND_COUNT = LAST_CHANGE_COMMAND + 1,
+ MAX_POINTS_IN_PACKET = 1000,
+ MAX_LINES_IN_PACKET = 500
+ };
+
+
+ // ---------------------------------------------------------------------------
+ // Packet Handlers
+ // ---------------------------------------------------------------------------
+
+ /// Server handler for packets that contain map change details.
+ AREXPORT virtual void handleChangePacket(ArServerClient *client,
+ ArNetPacket *packet);
+
+ AREXPORT virtual void handleRobotChangeReplyPacket(ArServerClient *client,
+ ArNetPacket *packet);
+
+ /// Client handler for the results of applying the map changes on the server.
+ AREXPORT virtual void handleChangeReplyPacket(ArNetPacket *packet);
+
+ /// Client handler for the map-changes-in-progress broadcast packet
+ AREXPORT virtual void handleChangesInProgressPacket(ArNetPacket *packet);
+
+ /// Client handler for the server's idle-processing-pending broadcast packet
+ AREXPORT virtual void handleIdleProcessingPacket(ArNetPacket *packet);
+
+ /// Client handler for when the robot disconnects or is shutdown.
+ AREXPORT virtual void handleClientShutdown();
+
+protected:
+
+ // ---------------------------------------------------------------------------
+ // Helper Methods
+ // ---------------------------------------------------------------------------
+
+ // bool applyMapChanges(std::list &packetList);
+
+ /// Applies all scan data changes that are contained in the given change details.
+ /**
+ * Scan data include summary data, map data points, and map data lines.
+ * If the map contains scan data for multiple sources, then this method
+ * applies all of the applicable changes.
+ *
+ * An Aria map must have been previously associated with the map changer.
+ **/
+ bool applyScanChanges(ArMapChangeDetails *changeDetails);
+
+ /// Applies scan data changes for the specified scan type.
+ /**
+ * @param changeDetails the ArMapChangeDetails * that describes how the map should
+ * be modified; must be non-NULL
+ * @param scanType the char * identifier of the scan type to be updated
+ * @param parser the ArFileParser used to parse the changeDetails
+ **/
+ bool applyScanChanges(ArMapChangeDetails *changeDetails,
+ const char *scanType,
+ ArFileParser &parser);
+
+ /// Applies the given map changes to the supplemental data in the map.
+ /**
+ * @param changeDetails the ArMapChangeDetails * that describes how the map should
+ * be modified; must be non-NULL
+ **/
+ bool applySupplementChanges(ArMapChangeDetails *changeDetails);
+
+ /// Applies the given map changes to the object data in the map.
+ /**
+ * @param changeDetails the ArMapChangeDetails * that describes how the map should
+ * be modified; must be non-NULL
+ **/
+ bool applyObjectChanges(ArMapChangeDetails *changeDetails);
+
+ /// Applies the given map changes to the info data in the map.
+ /**
+ * @param changeDetails the ArMapChangeDetails * that describes how the map should
+ * be modified; must be non-NULL
+ **/
+ bool applyInfoChanges(ArMapChangeDetails *changeDetails);
+
+ /// Determines whether the two given map objects are the same object.
+ /**
+ * If the objects have a name, then the name must be identical. Otherwise, the type
+ * and position must be the same.
+ **/
+ bool isMatchingObjects(ArMapObject *obj1,
+ ArMapObject *obj2);
+ //ArMapChangeDetails *changeDetails);
+
+ /// Creates a list of network packets for the given map change details.
+ bool convertChangeDetailsToPacketList(ArMapChangeDetails *changeDetails,
+ std::list *packetListOut,
+ bool isRelay = false);
+
+ /// Unpacks the given network packet list and populates the given map change details.
+ bool convertPacketListToChangeDetails(std::list &packetList,
+ ArMapChangeDetails *changeDetailsOut);
+
+ /// Creates network packets for the specified map change data and adds them to the given list.
+ /**
+ * @param dataType the MapChangeDataType that specifies which map data is to be added
+ * @param changeType the MapLineChangeType that specifies the type of map change (lines
+ * added or deleted)
+ * @param scanType the char * identifier of the scan source to add; valid only when
+ * dataType is SUMMARY_DATA
+ * @param extra an optional const char * identifier that clarifies which data to add;
+ * when dataType is INFO_DATA, this is the info name; otherwise, ignored
+ * @param fileLineSet the ArMapFileLineSet * component of the map change details that
+ * is to be converted to network packets
+ * @param packetListOut the list of ArNetPackets to which new packets are added
+ **/
+ bool addFileLineSetPackets(MapChangeDataType dataType,
+ ArMapChangeDetails::MapLineChangeType changeType,
+ const char *scanType,
+ const char *extra,
+ ArMapFileLineSet *fileLineSet,
+ std::list *packetListOut);
+
+ /// Inserts header information into the given network packet.
+ /**
+ * @param command the MapChangeCommand that specifies which command identifier to add to this packet
+ * @param dataType the MapChangeDataType that specifies which map data is to be added
+ * @param changeType the MapLineChangeType that specifies the type of map change (lines
+ * added or deleted)
+ * @param scanType the char * identifier of the scan source to add; valid only when
+ * dataType is SUMMARY_DATA
+ * @param packet the ArNetPacket * to be modified; must be non-NULL
+ **/
+ void addHeaderToPacket(MapChangeCommand command,
+ MapChangeDataType dataType,
+ ArMapChangeDetails::MapLineChangeType changeType,
+ const char *scanType,
+ ArNetPacket *packet);
+
+ /// Creates network packets for the specified file line group and adds them to the given list.
+ bool addGroupToPacketList(MapChangeDataType dataType,
+ ArMapChangeDetails::MapLineChangeType changeType,
+ const char *scanType,
+ ArMapFileLineGroup &group,
+ std::list *packetListOut);
+
+ /// Creates network packets for the specified file line and adds them to the given list.
+ bool addFileLineToPacketList(MapChangeDataType dataType,
+ ArMapChangeDetails::MapLineChangeType changeType,
+ const char *scanType,
+ const ArMapFileLine &fileLine,
+ std::list *packetListOut);
+
+ /// Creates network packets for the given map data points and adds them to the given list.
+ bool addPointsPackets(ArMapChangeDetails::MapLineChangeType changeType,
+ const char *scanType,
+ std::vector *pointList,
+ std::list *packetListOut);
+
+ /// Creates network packets for the given map data lines and adds them to the given list.
+ bool addLinesPackets(ArMapChangeDetails::MapLineChangeType changeType,
+ const char *scanType,
+ std::vector *lineSegmentList,
+ std::list *packetListOut);
+
+ /// Unpacks the header data from the given network packet.
+ /**
+ * @param packet the ArNetPacket * from which to extract the header information;
+ * must be non-NULL
+ * @param commandOut the MapChangeCommand * extracted from the packet
+ * @param origMapIdOut the original ArMapId * extracted from the packet
+ * @param newMapIdOut the optional new ArMapId * extracted from the packet
+ * @param dataTypeOut the optional MapChangeDataType * extracted from the packet
+ * @param changeTypeOut the optional MapLineChangeType * extracted from the packet
+ * @param scanTypeOut the optional std::string * extracted from the packet
+ * @return bool true if all of the header information was succesfully extracted;
+ * false, otherwise
+ **/
+ bool unpackHeader(ArNetPacket *packet,
+ MapChangeCommand *commandOut,
+ ArMapId *origMapIdOut,
+ ArMapId *newMapIdOut = NULL,
+ MapChangeDataType *dataTypeOut = NULL,
+ ArMapChangeDetails::MapLineChangeType *changeTypeOut = NULL,
+ std::string *scanTypeOut = NULL);
+
+ /// Unpacks the specified file line set from the given network packet.
+ /**
+ * The file line set is added to the given change details.
+ **/
+ bool unpackFileLineSet(ArNetPacket *packet,
+ MapChangeDataType dataType,
+ ArMapChangeDetails::MapLineChangeType changeType,
+ const char *scanType,
+ int *numGroups,
+ int *numChildren,
+ ArMapChangeDetails *changeDetails);
+
+ /// Unpacks the map data points for the specified scan from the given network packet.
+ /**
+ * The data points are added to the given change details.
+ **/
+ bool unpackPoints(ArNetPacket *packet,
+ ArMapChangeDetails::MapLineChangeType changeType,
+ const char *scanType,
+ int *numPoints,
+ ArMapChangeDetails *changeDetails);
+
+ /// Unpacks the map data lines for the specified scan from the given network packet.
+ /**
+ * The data lines are added to the given change details.
+ **/
+ bool unpackLines(ArNetPacket *packet,
+ ArMapChangeDetails::MapLineChangeType changeType,
+ const char *scanType,
+ int *numLines,
+ ArMapChangeDetails *changeDetails);
+
+ /// Resets all of the network packets in the given list so that they can be read again.
+ void resetPacketList(std::list *packetList);
+
+ /// Waits for a reply from the server.
+ /**
+ * If a reply is not received within 30 seconds, this method will timeout and return
+ * false.
+ *
+ * @return bool true if the reply was received; false otherwise
+ **/
+ bool waitForReply(ArTime &started);
+
+ bool waitForCentralServerReply(ArTime &started);
+
+ /// Determines whether idle processing is pending on the server.
+ bool isIdleProcessingPending();
+
+ /// Adds the given functor to the given callback list.
+ AREXPORT void addToCallbackList(ArFunctor *functor,
+ ArListPos::Pos position,
+ std::list *cbList);
+
+ /// Removes the given functor from the given callback list.
+ AREXPORT void remFromCallbackList(ArFunctor *functor,
+ std::list *cbList);
+
+private:
+ /// Disabled copy constructor
+ ArMapChanger(const ArMapChanger &other);
+
+ /// Disabled assignment operator
+ ArMapChanger &operator=(const ArMapChanger &other);
+
+protected:
+
+ /// Accumulates the packet list that describes map changes received from a specified client.
+ struct ClientChangeInfo
+ {
+ public:
+ /// Constructor for changes received from a client
+ ClientChangeInfo(ArServerClient *client);
+
+ /// Constructor for changes received from a robot on the CS
+ ClientChangeInfo(ArCentralForwarder *forwarder);
+
+ /// Destructor
+ ~ClientChangeInfo();
+
+ /// Adds the given packet to the list
+ void addPacket(ArNetPacket *packet);
+
+ /// Server client which sent the map changes...
+ ArServerClient *myClient;
+
+ /// Or the forwarder that sent the map changes
+ ArCentralForwarder *myForwarder;
+
+ /// Time at which the first packet in this list was received
+ ArTime myStartTime;
+ /// Time at which the most recent packet in this list was received
+ ArTime myLastActivityTime;
+ /// List of network packets received from the client for these map changes
+ std::list myPacketList;
+ }; // end struct ClientChangeInfo
+
+
+ /// Aria map currently in use
+ ArMapInterface *myMap;
+ /// Copy of the current Aria map, used to make sure the changes can be successfully made
+ ArMapInterface *myWorkingMap;
+
+ /// Change details to apply to the Aria map
+ ArMapChangeDetails *myChangeDetails;
+ /// Number of info types in the associated Aria map
+ //int myInfoCount;
+
+ /// List of info types in the associated info map
+ std::list myInfoNames;
+
+ /// Associated server base; non-NULL only when changer instantiated on the server
+ ArServerBase *myServer;
+
+ /// Associated client switch manager; non-NULL when changer instantiated on robot with EM
+ ArClientSwitchManager *myClientSwitch;
+
+ /// Whether the client switch manager's serverClient has been initialized with a handler (for EM)
+ bool myIsServerClientInit;
+
+
+ /// Mutex that protects access to the myClient member
+ ArMutex myClientMutex;
+ /// Associated client base; non-NULL only when changer instantiated on the client
+ ArClientBase *myClient;
+
+ /// Mutex that protects access to the myClientInfo member
+ ArMutex myClientInfoMutex;
+ /// Information regarding the server client that is currently sending map changes
+ ClientChangeInfo *myClientInfo;
+
+ /// Mutex that protects access to the interleave data
+ ArMutex myInterleaveMutex;
+ /// Whether the client is ready to send another packet
+ bool myReadyForNextPacket;
+ /// Whether the client is waiting for a reply from the server
+ bool myIsWaitingForReturn;
+
+ /// Mutex that protects access to the myIsIdleProcessingPending member
+ ArMutex myIdleProcessingMutex;
+ /// Whether the server has data to process once it becomes idle
+ bool myIsIdleProcessingPending;
+
+ /// List of callbacks to be invoked before the changed map file is written
+ std::list myPreWriteCBList;
+ /// List of callbacks to be invoked after the changed map file is written
+ std::list myPostWriteCBList;
+
+ /// List of server client callbacks to be invoked after the map has been changed
+ std::list< ArFunctor2 *> *>
+ myChangeCBList;
+
+ /// List of server client callbacks to be invoked after the map has been changed
+ std::list< ArFunctor2 *> myRobotChangeReplyCBList;
+
+ /// Server handler for the network packets that describe map changes.
+ ArFunctor2C myHandleChangePacketCB;
+
+ ArFunctor2C