Changed layout for organizational coherence.

This commit is contained in:
2018-01-25 15:49:32 -08:00
parent 32d3b6b7cb
commit fc1b41178c
190 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
</component>
</module>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" autoUpload="Always" serverName="ssh://rover@192.168.1.148:22/usr/bin/python3" autoUploadExternalChanges="true">
<serverData>
<paths name="ssh://rover@192.168.1.148:22/usr/bin/python3">
<serverdata>
<mappings>
<mapping deploy="/tmp/pycharm_project_346" local="$PROJECT_DIR$" />
</mappings>
</serverdata>
</paths>
</serverData>
<option name="myAutoUpload" value="ALWAYS" />
</component>
</project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Remote Python 3.5.2 (ssh://rover@192.168.1.148:22/usr/bin/python3)" project-jdk-type="Python SDK" />
</project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/DualScreenTest.iml" filepath="$PROJECT_DIR$/.idea/DualScreenTest.iml" />
</modules>
</component>
</project>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteMappingsManager">
<list>
<list>
<remote-mappings server-id="python@ssh://rover@192.168.1.148:22/usr/bin/python3" />
</list>
</list>
</component>
</project>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebServers">
<option name="servers">
<webServer id="ssh://rover@192.168.1.148:22/usr/bin/python3" name="ssh://rover@192.168.1.148:22/usr/bin/python3">
<fileTransfer host="192.168.1.148" port="22" accessType="SFTP">
<option name="port" value="22" />
</fileTransfer>
</webServer>
</option>
</component>
</project>

View File

@@ -0,0 +1,271 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="f3448608-b6b3-45db-bb70-037358c0a144" name="Default" comment="" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="CoverageDataManager">
<SUITE FILE_PATH="coverage/DualScreenTest$Remote_Launch.coverage" NAME="Remote Launch Coverage Results" MODIFIED="1510122626619" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="main.py" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="697">
<caret line="41" column="0" lean-forward="true" selection-start-line="41" selection-start-column="0" selection-end-line="41" selection-end-column="0" />
<folding>
<element signature="e#260#270#0" expanded="true" />
<marker date="1510122614784" expanded="true" signature="2647:2900" ph="..." />
</folding>
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Python Script" />
</list>
</option>
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/main.py" />
</list>
</option>
</component>
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsGulpfileManager">
<detection-done>true</detection-done>
<sorting>DEFINITION_ORDER</sorting>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="2577" />
<option name="y" value="62" />
<option name="width" value="2072" />
<option name="height" value="1347" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
<manualOrder />
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="Scratches" />
<pane id="Scope" />
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="DualScreenTest" type="b2602c69:ProjectViewProjectNode" />
<item name="DualScreenTest" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="DualScreenTest" type="b2602c69:ProjectViewProjectNode" />
<item name="DualScreenTest" type="462c0819:PsiDirectoryNode" />
<item name="Resources" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="DualScreenTest" type="b2602c69:ProjectViewProjectNode" />
<item name="DualScreenTest" type="462c0819:PsiDirectoryNode" />
<item name="Resources" type="462c0819:PsiDirectoryNode" />
<item name="UI" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/main.py" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
<property name="restartRequiresConfirmation" value="false" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\Corwin Perren\PycharmProjects\DualScreenTest\Resources\UI" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="RunManager" selected="Python.Remote Launch">
<configuration name="Remote Launch" type="PythonConfigurationType" factoryName="Python" singleton="true">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="DISPLAY" value=":0" />
</envs>
<option name="SDK_HOME" value="ssh://rover@192.168.1.148:22/usr/bin/python3" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="DualScreenTest" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/main.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
</configuration>
</component>
<component name="ShelveChangesManager" show_recycled="false">
<option name="remove_strategy" value="false" />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="f3448608-b6b3-45db-bb70-037358c0a144" name="Default" comment="" />
<created>1510038952879</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1510038952879</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="2552" y="-8" width="2576" height="1426" extended-state="6" />
<editor active="true" />
<layout>
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
<window_info id="File Transfer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32945737" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2511628" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32945737" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.07750397" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Data View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager />
<watches-manager />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="e#260#270#0" expanded="true" />
<marker date="1510122614784" expanded="true" signature="2647:2900" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="e#260#270#0" expanded="true" />
<marker date="1510122614784" expanded="true" signature="2647:2900" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="e#260#270#0" expanded="true" />
<marker date="1510122614784" expanded="true" signature="2647:2900" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://Y:/Temp and Unsorted/Lenovo Laptop Backup/PycharmProjects/RoverBaseStationMockup/RoverBaseStation.py" />
<entry file="file://$PROJECT_DIR$/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="e#260#270#0" expanded="true" />
<marker date="1510122614784" expanded="true" signature="2647:2900" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://Y:/Temp and Unsorted/Lenovo Laptop Backup/PycharmProjects/RoverBaseStationMockup/RoverBaseStation.py" />
<entry file="file://$PROJECT_DIR$/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="e#260#270#0" expanded="true" />
<marker date="1510122614784" expanded="true" signature="2647:2900" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://Y:/Temp and Unsorted/Lenovo Laptop Backup/PycharmProjects/RoverBaseStationMockup/RoverBaseStation.py" />
<entry file="file://Y:/Temp and Unsorted/Lenovo Laptop Backup/PycharmProjects/RoverBaseStationMockup/RoverBaseStation.py" />
<entry file="file://$PROJECT_DIR$/Resources/UI/RoverGui.ui">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/main.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="697">
<caret line="41" column="0" lean-forward="true" selection-start-line="41" selection-start-column="0" selection-end-line="41" selection-end-column="0" />
<folding>
<element signature="e#260#270#0" expanded="true" />
<marker date="1510122614784" expanded="true" signature="2647:2900" ph="..." />
</folding>
</state>
</provider>
</entry>
</component>
</project>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1920</width>
<height>1080</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1920</width>
<height>1080</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1920</width>
<height>1080</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="windowOpacity">
<double>1.000000000000000</double>
</property>
<property name="styleSheet">
<string notr="true">background-color: #201F1D;
color: #DCDCDC;</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>74</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>UI File 1 (Left Screen)</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1920</width>
<height>1080</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1920</width>
<height>1080</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1920</width>
<height>1080</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="windowOpacity">
<double>1.000000000000000</double>
</property>
<property name="styleSheet">
<string notr="true">background-color: #201F1D;
color: #DCDCDC;</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>74</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>UI File 2 (Right Screen)</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env python
"""
Main file used to launch the Rover Base Station
No other files should be used for launching this application.
"""
#####################################
# Imports
#####################################
# Python native imports
import sys
from PyQt5 import QtWidgets, QtCore, uic
import signal
# Custom Imports
#####################################
# Global Variables
#####################################
UI_FILE_LEFT = "Resources/UI/RoverGui.ui"
UI_FILE_RIGHT = "Resources/UI/RoverGui2.ui"
FORM_LEFT, BASE_UI_LEFT = uic.loadUiType(UI_FILE_LEFT)
FORM_RIGHT, BASE_UI_RIGHT = uic.loadUiType(UI_FILE_RIGHT)
LEFT_SCREEN_ID = 0
RIGHT_SCREEN_ID = 1
#####################################
# Application Class Definition
#####################################
class LeftWindow(BASE_UI_LEFT, FORM_LEFT):
kill_threads_signal = QtCore.pyqtSignal()
def __init__(self, parent=None):
# noinspection PyArgumentList
super(BASE_UI_LEFT, self).__init__(parent)
self.setupUi(self)
#####################################
# Application Class Definition
#####################################
class RightWindow(BASE_UI_RIGHT, FORM_RIGHT):
kill_threads_signal = QtCore.pyqtSignal()
def __init__(self, parent=None):
# noinspection PyArgumentList
super(BASE_UI_RIGHT, self).__init__(parent)
self.setupUi(self)
#####################################
# Main Definition
#####################################
if __name__ == "__main__":
signal.signal(signal.SIGINT, signal.SIG_DFL) # This allows the keyboard interrupt kill to work properly
application = QtWidgets.QApplication(sys.argv) # Create the base qt gui application
system_desktop = QtWidgets.QDesktopWidget() # This gets us access to the desktop geometry
app_window = LeftWindow() # Make a window in this application
app_window.setWindowTitle("Rover Control") # Sets the window title
app_window.setWindowFlags(app_window.windowFlags() | # Sets the windows flags to:
QtCore.Qt.FramelessWindowHint | # remove the border and frame on the application,
QtCore.Qt.WindowStaysOnTopHint | # and makes the window stay on top of all others
QtCore.Qt.X11BypassWindowManagerHint) # This is needed to show fullscreen in gnome
app_window.setGeometry(system_desktop.screenGeometry(LEFT_SCREEN_ID)) # Sets the window to be on the first screen
app_window.showFullScreen() # Shows the window in full screen mode
app_window2 = RightWindow()
app_window2.setWindowTitle("Rover Video")
app_window2.setWindowFlags(app_window.windowFlags() |
QtCore.Qt.FramelessWindowHint |
QtCore.Qt.WindowStaysOnTopHint |
QtCore.Qt.X11BypassWindowManagerHint)
app_window2.setGeometry(system_desktop.screenGeometry(RIGHT_SCREEN_ID))
app_window2.showFullScreen()
application.exec_() # Execute launching of the application

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1920"
height="1080"
viewBox="0 0 1920 1080"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="left_screen.svg"
inkscape:export-filename="/home/caperren/caperren@gmail.com/_School/Capstone/1. Fall/left_screen.svg.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="805.69335"
inkscape:cy="664.4128"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="2560"
inkscape:window-height="1375"
inkscape:window-x="1920"
inkscape:window-y="1080"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,27.637808)">
<rect
style="fill:#ffb380;fill-rule:evenodd;stroke:none;stroke-width:1.28854847px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3355"
width="1280"
height="720"
x="640"
y="-27.637808" />
<rect
style="fill:#8080ff;fill-rule:evenodd;stroke:none;stroke-width:1.05599153px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3361"
width="640"
height="540"
x="0"
y="-27.637808" />
<rect
style="fill:#ffe680;fill-rule:evenodd;stroke:none;stroke-width:1.05599153px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3361-0"
width="640"
height="540"
x="2"
y="512.36218" />
<rect
style="fill:#de8787;fill-rule:evenodd;stroke:none;stroke-width:1.05599153px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3361-2"
width="320"
height="360"
x="1600"
y="692.36218" />
<rect
style="fill:#decd87;fill-rule:evenodd;stroke:none;stroke-width:1.05599153px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3361-2-3"
width="320"
height="360"
x="1282"
y="692.36218" />
<rect
style="fill:#cd87de;fill-rule:evenodd;stroke:none;stroke-width:1.05599153px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3361-2-5"
width="640"
height="360"
x="642"
y="692.36218" />
<flowRoot
xml:space="preserve"
id="flowRoot4195"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-757.78662,446.94237)"><flowRegion
id="flowRegion4197"><rect
id="rect4199"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">1</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-9"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(204.54248,537.53563)"><flowRegion
id="flowRegion4197-2"><rect
id="rect4199-2"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201-8"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">2</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-97"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-753.23779,986.89841)"><flowRegion
id="flowRegion4197-3"><rect
id="rect4199-6"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201-1"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">3</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-2"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-113.76514,1076.9424)"><flowRegion
id="flowRegion4197-9"><rect
id="rect4199-3"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201-19"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">4</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-4"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(365.86133,1076.3051)"><flowRegion
id="flowRegion4197-7"><rect
id="rect4199-8"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201-4"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">5</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-5"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(683.81738,1076.8545)"><flowRegion
id="flowRegion4197-0"><rect
id="rect4199-36"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201-10"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">6</flowPara></flowRoot> </g>
</svg>

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1920"
height="1080"
viewBox="0 0 1920 1080"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="right_screen.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="856.69335"
inkscape:cy="744.4128"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="2560"
inkscape:window-height="1375"
inkscape:window-x="1920"
inkscape:window-y="1080"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,27.637808)">
<rect
style="fill:#ffb380;fill-rule:evenodd;stroke:none;stroke-width:1.28854847px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3355"
width="1280"
height="720"
x="640"
y="-27.637808" />
<rect
style="fill:#cdde87;fill-rule:evenodd;stroke:none;stroke-width:0.92212087px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3357"
width="640"
height="360"
x="1280"
y="692.36218" />
<rect
style="fill:#ffe680;fill-rule:evenodd;stroke:none;stroke-width:0.6692487px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3359"
width="640"
height="360"
x="640"
y="692.36218" />
<rect
style="fill:#de8787;fill-rule:evenodd;stroke:none;stroke-width:1.05599153px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3361"
width="640"
height="720"
x="0"
y="-27.637808" />
<rect
style="fill:#aa87de;fill-rule:evenodd;stroke:none;stroke-width:0.47325671px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3359-3"
width="320"
height="360"
x="0"
y="692.36218" />
<rect
style="fill:#8080ff;fill-rule:evenodd;stroke:none;stroke-width:0.47325671px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3359-3-6"
width="320"
height="360"
x="320"
y="692.36218" />
<flowRoot
xml:space="preserve"
id="flowRoot4195"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-757.78662,536.94237)"><flowRegion
id="flowRegion4197"><rect
id="rect4199"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">1</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-7"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(204.54248,537.53563)"><flowRegion
id="flowRegion4197-5"><rect
id="rect4199-3"
width="72.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201-5"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">2</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-6"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-915.23779,1076.8984)"><flowRegion
id="flowRegion4197-2"><rect
id="rect4199-9"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'"
id="flowPara4275">3</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-2"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-595.76514,1076.9424)"><flowRegion
id="flowRegion4197-7"><rect
id="rect4199-0"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201-9"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">4</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-3"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(-116.13867,1076.3051)"><flowRegion
id="flowRegion4197-6"><rect
id="rect4199-06"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201-2"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">5</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot4195-61"
style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(523.81738,1076.8545)"><flowRegion
id="flowRegion4197-8"><rect
id="rect4199-7"
width="66.83252"
height="127.25128"
x="1044.4977"
y="-261.48257"
style="font-size:90px" /></flowRegion><flowPara
id="flowPara4201-92"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:90px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">6</flowPara></flowRoot> </g>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -0,0 +1,15 @@
# udevadm info -a -p $(udevadm info -q path -n /dev/video2)
# ATTRS{serial}=="B9A8A5FF", MODE="0660",GROUP="nvidia",
# SUBSYSTEM=="video4linux",ATTRS{idVendor}=="0x046d",ATTRS{idProduct}=="0x082d",NAME="videoext"
# The zed camera
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="2b03", ATTRS{idProduct}=="f580", SYMLINK+="rover/camera_zed"
# The first C920 Webcam
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="082d", ATTRS{serial}=="B9A8A5FF", SYMLINK+="rover/camera_undercarriage"
# The second C920 Webcam
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="082d", ATTRS{serial}=="A98AA5FF", SYMLINK+="rover/camera_chassis"
# The special main nav cam
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="05a3", ATTRS{idProduct}=="9422", ATTRS{serial}=="SN0001", ATTR{index}=="0", SYMLINK+="rover/camera_main_navigation"

View File

@@ -0,0 +1,7 @@
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", ATTRS{serial}=="FTU9EU0I", ENV{ID_USB_INTERFACE_NUM}=="00", SYMLINK+="rover/ttyDEV0"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", ATTRS{serial}=="FTU9EU0I", ENV{ID_USB_INTERFACE_NUM}=="01", SYMLINK+="rover/ttyDEV1"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", ATTRS{serial}=="FTU9EU0I", ENV{ID_USB_INTERFACE_NUM}=="02", SYMLINK+="rover/ttyCompass"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", ATTRS{serial}=="FTU9EU0I", ENV{ID_USB_INTERFACE_NUM}=="03", SYMLINK+="rover/ttyGPS"

View File

@@ -0,0 +1,3 @@
#!/bin/bash
sudo cp 99-rover-cameras.rules /etc/udev/rules.d/.
sudo cp 99-rover-usb-serial.rules /etc/udev/rules.d/.

View File

@@ -0,0 +1,86 @@
[LEFT_CAM_2K]
cx = 1103.74
cy = 663.956
fx = 1389.02
fy = 1389.02
k1 = -0.175403
k2 = 0.0278335
[LEFT_CAM_FHD]
cx = 959.74
cy = 582.956
fx = 1389.02
fy = 1389.02
k1 = -0.175403
k2 = 0.0278335
[LEFT_CAM_HD]
cx = 638.37
cy = 379.978
fx = 694.512
fy = 694.512
k1 = -0.175403
k2 = 0.0278335
[LEFT_CAM_VGA]
cx = 334.185
cy = 196.989
fx = 347.256
fy = 347.256
k1 = -0.175403
k2 = 0.0278335
[RIGHT_CAM_2K]
cx = 1152.59
cy = 667.942
fx = 1393.95
fy = 1393.95
k1 = -0.175501
k2 = 0.0279378
[RIGHT_CAM_FHD]
cx = 1008.59
cy = 586.942
fx = 1393.95
fy = 1393.95
k1 = -0.175501
k2 = 0.0279378
[RIGHT_CAM_HD]
cx = 662.797
cy = 381.971
fx = 696.977
fy = 696.977
k1 = -0.175501
k2 = 0.0279378
[RIGHT_CAM_VGA]
cx = 346.399
cy = 197.985
fx = 348.489
fy = 348.489
k1 = -0.175501
k2 = 0.0279378
[STEREO]
BaseLine = 120.098
CV_2K = 4.66838e-06
CV_FHD = 4.66838e-06
CV_HD = 4.66838e-06
CV_VGA = 4.66838e-06
RX_2K = 0.000518746
RX_FHD = 0.000518746
RX_HD = 0.000518746
RX_VGA = 0.000518746
RZ_2K = -0.00147751
RZ_FHD = -0.00147751
RZ_HD = -0.00147751
RZ_VGA = -0.00147751

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" autoUpload="Always" serverName="ssh://rover@192.168.1.15:22/usr/bin/python" autoUploadExternalChanges="true">
<serverData>
<paths name="ssh://rover@192.168.1.15:22/usr/bin/python">
<serverdata>
<mappings>
<mapping deploy="/ground_station" local="$PROJECT_DIR$" />
</mappings>
</serverdata>
</paths>
</serverData>
<option name="myAutoUpload" value="ALWAYS" />
</component>
</project>

View File

@@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="caperren">
<words>
<w>roscore</w>
</words>
</dictionary>
</component>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Remote Python 2.7.12 (ssh://rover@192.168.1.15:22/usr/bin/python)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@@ -0,0 +1,15 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="dict.exit_requested_signal" />
<option value="dict.primary_video_label" />
<option value="dict.secondary_video_label" />
<option value="dict.tertiary_video_label" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@@ -0,0 +1,7 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Project Default" />
<option name="USE_PROJECT_PROFILE" value="true" />
<version value="1.0" />
</settings>
</component>

4
software/ground_station/.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Remote Python 2.7.12 (ssh://rover@192.168.1.15:22/usr/bin/python)" project-jdk-type="Python SDK" />
</project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/ground_station.iml" filepath="$PROJECT_DIR$/.idea/ground_station.iml" />
</modules>
</component>
</project>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteMappingsManager">
<list>
<list>
<remote-mappings server-id="python@ssh://rover@192.168.1.15:22/usr/bin/python">
<settings>
<list>
<mapping local-root="$PROJECT_DIR$" remote-root="/home/rover/ground_station" />
</list>
</settings>
</remote-mappings>
</list>
</list>
</component>
</project>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebServers">
<option name="servers">
<webServer id="ssh://rover@192.168.1.15:22/usr/bin/python" name="ssh://rover@192.168.1.15:22/usr/bin/python">
<fileTransfer host="192.168.1.15" port="22" rootFolder="/home/rover" accessType="SFTP">
<option name="port" value="22" />
</fileTransfer>
</webServer>
</option>
</component>
</project>

View File

@@ -0,0 +1,699 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="a54e79f5-3dba-4e0c-9a8b-f98d636e1a48" name="Default" comment="" />
<ignored path=".idea/dataSources.local.xml" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="CoverageDataManager">
<SUITE FILE_PATH="coverage/ground_station$Remote_Launch.coverage" NAME="Remote Launch Coverage Results" MODIFIED="1510962565098" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
</component>
<component name="CreatePatchCommitExecutor">
<option name="PATCH_PATH" value="" />
</component>
<component name="DockManager">
<window id="1">
<content type="file-editors">
<state>
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="RoverVideoReceiver.py" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoReceiver.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1219">
<caret line="74" column="33" selection-start-line="74" selection-start-column="33" selection-end-line="74" selection-end-column="33" />
<folding>
<element signature="e#110#152#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf>
</state>
</content>
</window>
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
<component name="FavoritesManager">
<favorites_list name="ground_station" />
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="Logger.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/Framework/LoggingSystems/Logger.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="288">
<caret line="21" column="37" selection-start-line="21" selection-start-column="23" selection-end-line="21" selection-end-column="37" />
<folding>
<element signature="e#110#134#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="RoverVideoCoordinator.py" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoCoordinator.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="359">
<caret line="77" column="12" selection-start-line="77" selection-start-column="12" selection-end-line="77" selection-end-column="12" />
<folding>
<element signature="e#110#145#0" expanded="true" />
<marker date="1516923718211" expanded="false" signature="2739:4048" ph="..." />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="RoverGroundStation.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/RoverGroundStation.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2826">
<caret line="167" column="43" selection-start-line="167" selection-start-column="43" selection-end-line="167" selection-end-column="43" />
<folding>
<element signature="e#132#142#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="RoverVideoReceiverOld.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoReceiverOld.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1134">
<caret line="74" column="18" selection-start-line="74" selection-start-column="16" selection-end-line="74" selection-end-column="142" />
<folding>
<element signature="e#0#10#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Python Script" />
</list>
</option>
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/Framework/LoggingSystems/Logger.py" />
<option value="$PROJECT_DIR$/Framework/StartupSystems/ROSMasterChecker.py" />
<option value="$PROJECT_DIR$/RoverGroundStation.py" />
<option value="$PROJECT_DIR$/Framework/VideoSystems/RoverVideoReceiver.py" />
<option value="$PROJECT_DIR$/Framework/VideoSystems/RoverVideoCoordinator.py" />
</list>
</option>
</component>
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsGulpfileManager">
<detection-done>true</detection-done>
<sorting>DEFINITION_ORDER</sorting>
</component>
<component name="ProjectFrameBounds">
<option name="y" value="16" />
<option name="width" value="1920" />
<option name="height" value="1044" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
<manualOrder />
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ground_station" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ground_station" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ground_station" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ground_station" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ground_station" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Framework" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ground_station" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ground_station" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Framework" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="VideoSystems" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="ground_station" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="ground_station" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Framework" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="StartupSystems" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="Scope" />
<pane id="Scratches" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="js.eslint.eslintPackage" value="" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/RoverGroundStation.py" />
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
<property name="settings.editor.splitter.proportion" value="0.2" />
</component>
<component name="RunManager">
<configuration default="true" type="DjangoTestsConfigurationType" factoryName="Django tests">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="ground_station" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="TARGET" value="" />
<option name="SETTINGS_FILE" value="" />
<option name="CUSTOM_SETTINGS" value="false" />
<option name="USE_OPTIONS" value="false" />
<option name="OPTIONS" value="" />
<method />
</configuration>
<configuration default="true" type="JavascriptDebugType" factoryName="JavaScript Debug">
<method />
</configuration>
<configuration default="true" type="PyBehaveRunConfigurationType" factoryName="Behave">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="ground_station" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="ADDITIONAL_ARGS" value="" />
<method />
</configuration>
<configuration default="true" type="PyLettuceRunConfigurationType" factoryName="Lettuce">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="ground_station" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="ADDITIONAL_ARGS" value="" />
<method />
</configuration>
<configuration default="true" type="PythonConfigurationType" factoryName="Python">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="ground_station" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="SCRIPT_NAME" value="" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<method />
</configuration>
<configuration default="true" type="Tox" factoryName="Tox">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<module name="ground_station" />
<method />
</configuration>
<configuration default="true" type="js.build_tools.gulp" factoryName="Gulp.js">
<node-interpreter>project</node-interpreter>
<node-options />
<gulpfile />
<tasks />
<arguments />
<envs />
<method />
</configuration>
<configuration default="true" type="js.build_tools.npm" factoryName="npm">
<command value="run-script" />
<scripts />
<node-interpreter value="project" />
<envs />
<method />
</configuration>
<configuration default="true" type="tests" factoryName="Attests">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="ground_station" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="SCRIPT_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="FOLDER_NAME" value="" />
<option name="TEST_TYPE" value="TEST_SCRIPT" />
<option name="PATTERN" value="" />
<option name="USE_PATTERN" value="false" />
<method />
</configuration>
<configuration default="true" type="tests" factoryName="Doctests">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="ground_station" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="SCRIPT_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="FOLDER_NAME" value="" />
<option name="TEST_TYPE" value="TEST_SCRIPT" />
<option name="PATTERN" value="" />
<option name="USE_PATTERN" value="false" />
<method />
</configuration>
<configuration default="true" type="tests" factoryName="Nosetests">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="ground_station" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="SCRIPT_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="FOLDER_NAME" value="" />
<option name="TEST_TYPE" value="TEST_SCRIPT" />
<option name="PATTERN" value="" />
<option name="USE_PATTERN" value="false" />
<option name="PARAMS" value="" />
<option name="USE_PARAM" value="false" />
<method />
</configuration>
<configuration default="true" type="tests" factoryName="Unittests">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="ground_station" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="SCRIPT_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="FOLDER_NAME" value="" />
<option name="TEST_TYPE" value="TEST_SCRIPT" />
<option name="PATTERN" value="" />
<option name="USE_PATTERN" value="false" />
<option name="PUREUNITTEST" value="true" />
<option name="PARAMS" value="" />
<option name="USE_PARAM" value="false" />
<method />
</configuration>
<configuration default="true" type="tests" factoryName="py.test">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<module name="ground_station" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
<option name="SCRIPT_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="FOLDER_NAME" value="" />
<option name="TEST_TYPE" value="TEST_SCRIPT" />
<option name="PATTERN" value="" />
<option name="USE_PATTERN" value="false" />
<option name="testToRun" value="" />
<option name="keywords" value="" />
<option name="params" value="" />
<option name="USE_PARAM" value="false" />
<option name="USE_KEYWORD" value="false" />
<method />
</configuration>
</component>
<component name="ShelveChangesManager" show_recycled="false">
<option name="remove_strategy" value="false" />
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="a54e79f5-3dba-4e0c-9a8b-f98d636e1a48" name="Default" comment="" />
<created>1510962234686</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1510962234686</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="0" y="16" width="1920" height="1044" extended-state="6" />
<editor active="true" />
<layout>
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.134375" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32916668" sideWeight="0.50192416" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="File Transfer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.22399151" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32908705" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.18259023" sideWeight="0.49807587" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32960325" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Find" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32908705" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
</layout>
<layout-to-restore>
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32916668" sideWeight="0.50192416" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="File Transfer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32916668" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" />
<window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32960325" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.18259023" sideWeight="0.49807587" order="11" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.13468939" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
</layout-to-restore>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="processedProjectFiles" value="true" />
</component>
<component name="Vcs.Log.UiProperties">
<option name="RECENTLY_FILTERED_USER_GROUPS">
<collection />
</option>
<option name="RECENTLY_FILTERED_BRANCH_GROUPS">
<collection />
</option>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<option name="time" value="1" />
</breakpoint-manager>
<watches-manager />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/Framework/LoggingSystems/Logger.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="288">
<caret line="21" column="37" selection-start-line="21" selection-start-column="23" selection-end-line="21" selection-end-column="37" />
<folding>
<element signature="e#110#134#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoCoordinator.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="162">
<caret line="15" column="9" selection-start-line="15" selection-start-column="0" selection-end-line="15" selection-end-column="31" />
<folding>
<element signature="e#110#145#0" expanded="true" />
<marker date="1516923718211" expanded="false" signature="2739:4048" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/RoverGroundStation.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2826">
<caret line="167" column="43" selection-start-line="167" selection-start-column="43" selection-end-line="167" selection-end-column="43" />
<folding>
<element signature="e#132#142#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoReceiverOld.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1134">
<caret line="74" column="18" selection-start-line="74" selection-start-column="16" selection-end-line="74" selection-end-column="142" />
<folding>
<element signature="e#0#10#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/LoggingSystems/Logger.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="378">
<caret line="21" column="37" selection-start-line="21" selection-start-column="23" selection-end-line="21" selection-end-column="37" />
<folding>
<element signature="e#110#134#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoCoordinator.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="72">
<caret line="4" column="25" selection-start-line="4" selection-start-column="25" selection-end-line="4" selection-end-column="25" />
<folding>
<element signature="e#110#145#0" expanded="true" />
<marker date="1516923718211" expanded="false" signature="2739:4048" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/RoverGroundStation.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="e#132#142#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoReceiverOld.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1134">
<caret line="74" column="18" selection-start-line="74" selection-start-column="16" selection-end-line="74" selection-end-column="142" />
<folding>
<element signature="e#0#10#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/RoverGroundStation.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="e#132#142#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/RoverGroundStation.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding>
<element signature="e#132#142#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.PyCharm2016.3/system/remote_sources/-1418177152/1376253408/cv_bridge/core.py" />
<entry file="file://$USER_HOME$/.PyCharm2016.3/system/remote_sources/-1418177152/1376253408/rospy/topics.py" />
<entry file="file://$USER_HOME$/.PyCharm2016.2/system/remote_sources/-1418177152/1376253408/rospy/client.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="196">
<caret line="349" column="4" selection-start-line="349" selection-start-column="4" selection-end-line="349" selection-end-column="4" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/LoggingSystems/Logger.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="288">
<caret line="21" column="37" selection-start-line="21" selection-start-column="23" selection-end-line="21" selection-end-column="37" />
<folding>
<element signature="e#110#134#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/StartupSystems/ROSMasterChecker.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="774">
<caret line="43" column="38" selection-start-line="43" selection-start-column="38" selection-end-line="43" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/RoverGroundStation.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2826">
<caret line="167" column="43" selection-start-line="167" selection-start-column="43" selection-end-line="167" selection-end-column="43" />
<folding>
<element signature="e#132#142#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoReceiverOld.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1134">
<caret line="74" column="18" selection-start-line="74" selection-start-column="16" selection-end-line="74" selection-end-column="142" />
<folding>
<element signature="e#0#10#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoCoordinator.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="359">
<caret line="77" column="12" selection-start-line="77" selection-start-column="12" selection-end-line="77" selection-end-column="12" />
<folding>
<element signature="e#110#145#0" expanded="true" />
<marker date="1516923718211" expanded="false" signature="2739:4048" ph="..." />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoReceiver.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1219">
<caret line="74" column="33" selection-start-line="74" selection-start-column="33" selection-end-line="74" selection-end-column="33" />
<folding>
<element signature="e#110#152#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
<component name="webServersAuthStorage">
<data>AAAAsNHwc2N+8Zbshoe1tr2XDVkf8aGU/l0YnN7t0gOfSXYMOeQZo2dVv+GbvgrFH5EF+uviJzRPHArF3uX1Vb0CuhmnSE0NSLdGfSjyMrpWsoZyS3WBI979X8Y/8lSe/g2O65pafrceXlU4ySEbA9w/JNU42PtXijURL7sXfaZ8kxhE5bYQlRppUyBo5g/qgzvj275mbp6uuZ5w9ssFsOzrJGsGulioJmZ9L9P6O6PVj2sPT2AEw+jC8eGiiappc0lWOA==</data>
</component>
</project>

View File

@@ -0,0 +1,50 @@
import sys
from PyQt5 import QtWidgets, QtCore, QtGui, uic
import signal
import rospy
import time
from cv_bridge import CvBridge, CvBridgeError
import cv2
import qimage2ndarray
import numpy as np
from geometry_msgs.msg import Twist
from sensor_msgs.msg import CompressedImage
#from sensor_msgs.msg import Image, CompressedImage
class DriveTest(QtCore.QThread):
publish_message_signal = QtCore.pyqtSignal()
def __init__(self):
super(DriveTest, self).__init__()
self.not_abort = True
self.message = None
self.publisher = rospy.Publisher("/cmd_vel", Twist, queue_size=10)
rospy.init_node("test")
def run(self):
# TODO: Thread starting message here
while self.not_abort:
self.message = Twist()
self.message.linear.x = 1.0
self.message.angular.z = 1.0
self.publisher.publish(self.message)
self.msleep(100)
# TODO: Thread ending message here
def __publish_message(self):
pass
def setup_start_and_kill_signals(self, start_signal, signals_and_slots_signal, kill_signal):
start_signal.connect(self.start)
kill_signal.connect(self.on_kill_threads_requested__slot)
def on_kill_threads_requested__slot(self):
self.not_abort = False

View File

@@ -0,0 +1,127 @@
#####################################
# Imports
#####################################
# Python native imports
from PyQt5 import QtCore
from os import makedirs, rename, walk, unlink
from os.path import exists, getmtime
from os import environ
import logging
from datetime import datetime
#####################################
# Global Variables
#####################################
MAX_NUM_LOG_FILES = 30
#####################################
# Logger Definition
#####################################
class Logger(QtCore.QObject):
def __init__(self, console_output=True):
super(Logger, self).__init__()
# ########## Local class variables ##########
self.console_output = console_output
# ########## Get the settings instance ##########
self.settings = QtCore.QSettings()
# # ########## Get the Pick And Plate instance of the logger ##########
self.logger = logging.getLogger("groundstation")
# ########## Set variables with useful paths ##########
self.appdata_base_directory = environ["HOME"] + "/.groundstation"
self.log_directory = self.appdata_base_directory + "//logs"
self.log_file_path = self.log_directory + "//log.txt"
# ########## Cleanup old log files ##########
self.__cleanup_log_files()
# ########## Set up logger with desired settings ##########
self.__setup_logger()
# ########## Place divider in log file to see new program launch ##########
self.__add_startup_log_buffer_text()
def __setup_logger(self):
# Get the appdata directory and make the log path if it doesn't exist
if not exists(self.log_directory):
makedirs(self.log_directory)
# Set the debugging level
self.logger.setLevel(logging.DEBUG)
# Make a formatter with the log line format wanted
formatter = logging.Formatter(fmt='%(levelname)s : %(asctime)s : %(message)s', datefmt='%m/%d/%y %H:%M:%S')
# Set up a file handler so everything can be saved and attach it to the logger
file_handler = logging.FileHandler(filename=self.log_file_path)
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.DEBUG)
self.logger.addHandler(file_handler)
# Enable console output if requested
if self.console_output:
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
console_handler.setLevel(logging.DEBUG)
self.logger.addHandler(console_handler)
def __cleanup_log_files(self):
# This copies the existing log.txt file to an old version with a datetime stamp
# It then checks if there are too many log files, and if so, deletes the oldest
if exists(self.log_directory):
# Get the number of log files
num_log_files = self.__get_num_files_in_directory(self.log_directory)
# Check that we actually have log files
if num_log_files > 0:
date_time = datetime.now().strftime("%Y%m%d-%H%M%S")
# If we do, move the current logfile to a backup in the format old_log_datetime
if exists(self.log_file_path):
rename(self.log_file_path, self.log_directory + "\\old_log_" + date_time + ".txt")
# If we have more than the max log files delete the oldest one
if num_log_files >= MAX_NUM_LOG_FILES:
unlink(self.__get_name_of_oldest_file(self.log_directory))
def __add_startup_log_buffer_text(self):
# Prints a header saying when the program started
self.logger.info("########## Application Starting ##########")
@staticmethod
def __get_name_of_oldest_file(input_path):
oldest_file_path = None
previous_oldest_time = 0
# Walk the directory passed in to get all folders and files
for dir_path, dir_names, file_names in walk(input_path):
# Go through all of the filenames found
for file in file_names:
# Recreate the full path and get the modified time of the file
current_path = dir_path + "\\" + file
time = getmtime(current_path)
# Default case for if the variables above have not been initially set
if previous_oldest_time == 0:
previous_oldest_time = time
oldest_file_path = current_path
# Saves the oldest time and file path of the current file if it's older (lower timestamp) than the
# last file saved in the variables
if time < previous_oldest_time:
previous_oldest_time = time
oldest_file_path = current_path
# Returns the path to the oldest file after checking all the files
return oldest_file_path
@staticmethod
def __get_num_files_in_directory(input_path):
# Walk the directory passed in to get all the files
for _, _, file_names in walk(input_path):
# Return the number of files found in the directory
return len(file_names)

View File

@@ -0,0 +1,45 @@
#####################################
# Imports
#####################################
# Python native imports
from PyQt5 import QtCore, QtGui, QtWidgets
import time
import logging
import socket
import rospy
# Custom Imports
#####################################
# Global Variables
#####################################
#####################################
# RoverVideoReceiver Class Definition
#####################################
class ROSMasterChecker(QtCore.QThread):
def __init__(self):
super(ROSMasterChecker, self).__init__()
# ########## Class Variables ##########
self.ros_master_present = False
self.start_time = time.time()
self.start()
def run(self):
try:
master = rospy.get_master()
master.getPid()
self.ros_master_present = True
except socket.error:
return
def master_present(self, timeout):
while self.isRunning() and (time.time() - self.start_time) < timeout:
self.msleep(100)
return self.ros_master_present

View File

@@ -0,0 +1,187 @@
#####################################
# Imports
#####################################
# Python native imports
from PyQt5 import QtCore, QtWidgets
import logging
import rospy
# Custom Imports
import RoverVideoReceiver
#####################################
# Global Variables
#####################################
CAMERA_TOPIC_PATH = "/cameras/"
EXCLUDED_CAMERAS = ["zed"]
PRIMARY_LABEL_MAX = (640, 360)
SECONDARY_LABEL_MAX = (256, 144)
TERTIARY_LABEL_MAX = (256, 144)
#####################################
# RoverVideoCoordinator Class Definition
#####################################
class RoverVideoCoordinator(QtCore.QThread):
pixmap_ready_signal = QtCore.pyqtSignal(str)
def __init__(self, shared_objects):
super(RoverVideoCoordinator, self).__init__()
# ########## Reference to class init variables ##########
self.shared_objects = shared_objects
self.right_screen = self.shared_objects["screens"]["right_screen"]
self.primary_video_display_label = self.right_screen.primary_video_label # type:QtWidgets.QLabel
self.secondary_video_display_label = self.right_screen.secondary_video_label # type:QtWidgets.QLabel
self.tertiary_video_display_label = self.right_screen.tertiary_video_label # type:QtWidgets.QLabel
# ########## Get the settings instance ##########
self.settings = QtCore.QSettings()
# ########## Get the Pick And Plate instance of the logger ##########
self.logger = logging.getLogger("groundstation")
# ########## Thread Flags ##########
self.run_thread_flag = True
self.setup_cameras_flag = True
# ########## Class Variables ##########
# Camera variables
self.camera_threads = {}
self.valid_cameras = []
self.disabled_cameras = []
# Setup cameras
self.__get_cameras()
self.__setup_video_threads()
self.primary_label_current_setting = 0
self.secondary_label_current_setting = 0
self.tertiary_label_current_setting = 0
self.primary_label_max_resolution = -1
self.secondary_label_max_resolution = -1
self.tertiary_label_max_resolution = -1
def run(self):
self.logger.debug("Starting Video Coordinator Thread")
self.__set_max_resolutions() # Do this initially so we don't try to disable cameras before they're set up
self.msleep(500)
while self.run_thread_flag:
self.__set_max_resolutions()
# self.__toggle_background_cameras_if_needed()
self.msleep(10)
self.__wait_for_camera_threads()
self.logger.debug("Stopping Video Coordinator Thread")
def __set_max_resolutions(self):
self.primary_label_max_resolution = self.camera_threads[
self.valid_cameras[self.primary_label_current_setting]].current_max_resolution
self.secondary_label_max_resolution = self.camera_threads[
self.valid_cameras[self.secondary_label_current_setting]].current_max_resolution
self.tertiary_label_max_resolution = self.camera_threads[
self.valid_cameras[self.tertiary_label_current_setting]].current_max_resolution
if self.primary_label_max_resolution != PRIMARY_LABEL_MAX:
self.camera_threads[self.valid_cameras[self.primary_label_current_setting]].change_max_resolution_setting(
PRIMARY_LABEL_MAX)
if self.secondary_label_max_resolution != SECONDARY_LABEL_MAX and self.secondary_label_current_setting != self.primary_label_current_setting:
self.camera_threads[self.valid_cameras[self.secondary_label_current_setting]].change_max_resolution_setting(
SECONDARY_LABEL_MAX)
if self.tertiary_label_max_resolution != TERTIARY_LABEL_MAX and self.tertiary_label_current_setting != self.primary_label_current_setting:
self.camera_threads[self.valid_cameras[self.tertiary_label_current_setting]].change_max_resolution_setting(
TERTIARY_LABEL_MAX)
def __toggle_background_cameras_if_needed(self):
enabled = list({self.primary_label_current_setting, self.secondary_label_current_setting,
self.tertiary_label_current_setting})
for camera_index, camera_name in enumerate(self.valid_cameras):
if camera_index not in enabled:
self.camera_threads[camera_name].toggle_video_display()
self.disabled_cameras.append(camera_index)
elif camera_index in self.disabled_cameras:
self.camera_threads[camera_name].toggle_video_display()
self.disabled_cameras.remove(camera_index)
def __get_cameras(self):
topics = rospy.get_published_topics(CAMERA_TOPIC_PATH)
names = []
for topics_group in topics:
main_topic = topics_group[0]
camera_name = main_topic.split("/")[2]
names.append(camera_name)
names = set(names)
for camera in EXCLUDED_CAMERAS:
if camera in names:
names.remove(camera)
self.valid_cameras = list(names)
def __setup_video_threads(self):
for camera in self.valid_cameras:
self.camera_threads[camera] = RoverVideoReceiver.RoverVideoReceiver(camera)
def __wait_for_camera_threads(self):
for camera in self.camera_threads:
self.camera_threads[camera].wait()
def connect_signals_and_slots(self):
for thread in self.camera_threads:
self.camera_threads[thread].image_ready_signal.connect(self.pixmap_ready__slot)
self.primary_video_display_label.mousePressEvent = self.__change_display_source_primary_mouse_press_event
self.secondary_video_display_label.mousePressEvent = self.__change_display_source_secondary_mouse_press_event
self.tertiary_video_display_label.mousePressEvent = self.__change_display_source_tertiary_mouse_press_event
def setup_signals(self, start_signal, signals_and_slots_signal, kill_signal):
start_signal.connect(self.start)
signals_and_slots_signal.connect(self.connect_signals_and_slots)
kill_signal.connect(self.on_kill_threads_requested__slot)
for camera in self.camera_threads:
self.camera_threads[camera].setup_signals(start_signal, signals_and_slots_signal, kill_signal)
def __change_display_source_primary_mouse_press_event(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.primary_label_current_setting = (self.primary_label_current_setting + 1) % len(self.valid_cameras)
elif event.button() == QtCore.Qt.RightButton:
self.camera_threads[self.valid_cameras[self.primary_label_current_setting]].toggle_video_display()
def __change_display_source_secondary_mouse_press_event(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.secondary_label_current_setting = (self.secondary_label_current_setting + 1) % len(self.valid_cameras)
elif event.button() == QtCore.Qt.RightButton:
self.camera_threads[self.valid_cameras[self.secondary_label_current_setting]].toggle_video_display()
def __change_display_source_tertiary_mouse_press_event(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.tertiary_label_current_setting = (self.tertiary_label_current_setting + 1) % len(self.valid_cameras)
elif event.button() == QtCore.Qt.RightButton:
self.camera_threads[self.valid_cameras[self.tertiary_label_current_setting]].toggle_video_display()
def pixmap_ready__slot(self, camera):
if self.valid_cameras[self.primary_label_current_setting] == camera:
self.primary_video_display_label.setPixmap(self.camera_threads[camera].pixmap_1280x720_image)
if self.valid_cameras[self.secondary_label_current_setting] == camera:
self.secondary_video_display_label.setPixmap(self.camera_threads[camera].pixmap_640x360_image)
if self.valid_cameras[self.tertiary_label_current_setting] == camera:
self.tertiary_video_display_label.setPixmap(self.camera_threads[camera].pixmap_640x360_image)
def on_kill_threads_requested__slot(self):
self.run_thread_flag = False

View File

@@ -0,0 +1,233 @@
#####################################
# Imports
#####################################
# Python native imports
from PyQt5 import QtCore, QtGui, QtWidgets
import logging
import cv2
import numpy as np
import qimage2ndarray
import rospy
from cv_bridge import CvBridge
from sensor_msgs.msg import CompressedImage
# Custom Imports
#####################################
# Global Variables
#####################################
CAMERA_TOPIC_PATH = "/cameras/"
#####################################
# RoverVideoReceiver Class Definition
#####################################
class RoverVideoReceiver(QtCore.QThread):
image_ready_signal = QtCore.pyqtSignal(str)
def __init__(self, camera_name):
super(RoverVideoReceiver, self).__init__()
# ########## Reference to class init variables ##########
self.camera_name = camera_name
# ########## Get the settings instance ##########
self.settings = QtCore.QSettings()
# ########## Get the Pick And Plate instance of the logger ##########
self.logger = logging.getLogger("groundstation")
# ########## Thread Flags ##########
self.run_thread_flag = True
# ########## Class Variables ##########
self.camera_title_name = self.camera_name.replace("_", " ").title()
self.topic_base_path = CAMERA_TOPIC_PATH + self.camera_name
self.camera_topics = {}
self.current_max_resolution = None
self.current_camera_settings = {
"resolution": None,
"quality_setting": 80,
}
self.previous_camera_settings = self.current_camera_settings.copy()
self.temp_topic_path = CAMERA_TOPIC_PATH + self.camera_name + "/image_640x360/compressed"
# Subscription variables
self.video_subscriber = None # type: rospy.Subscriber
# Image variables
self.raw_image = None
self.opencv_1280x720_image = None
self.opencv_640x360_image = None
self.pixmap_1280x720_image = None
self.pixmap_640x360_image = None
# Processing variables
self.bridge = CvBridge() # OpenCV ROS Video Data Processor
self.video_enabled = True
self.new_frame = False
# Text Drawing Variables
self.font = cv2.FONT_HERSHEY_TRIPLEX
self.font_thickness = 1
self.font_baseline = 0
self.camera_name_opencv_1280x720_image = None
self.camera_name_opencv_640x360_image = None
self.__create_camera_name_opencv_images()
self.__get_camera_available_resolutions()
def run(self):
self.logger.debug("Starting \"%s\" Camera Thread" % self.camera_title_name)
while self.run_thread_flag:
if self.video_enabled:
self.__show_video_enabled()
else:
self.__show_video_disabled()
self.msleep(10)
self.logger.debug("Stopping \"%s\" Camera Thread" % self.camera_title_name)
def __get_camera_available_resolutions(self):
topics = rospy.get_published_topics(self.topic_base_path)
resolution_options = []
for topics_group in topics:
main_topic = topics_group[0]
camera_name = main_topic.split("/")[3]
resolution_options.append(camera_name)
resolution_options = list(set(resolution_options))
for resolution in resolution_options:
# Creates a tuple in (width, height) format that we can use as the key
group = int(resolution.split("image_")[1].split("x")[0]), int(resolution.split("image_")[1].split("x")[1])
self.camera_topics[group] = self.topic_base_path + "/" + resolution + "/compressed"
def __update_camera_subscription_and_settings(self):
if self.current_camera_settings["resolution"] != self.previous_camera_settings["resolution"]:
if self.video_subscriber:
self.video_subscriber.unregister()
new_topic = self.camera_topics[self.current_camera_settings["resolution"]]
self.video_subscriber = rospy.Subscriber(new_topic, CompressedImage, self.__image_data_received_callback)
self.new_frame = False
while not self.new_frame:
self.msleep(10)
self.previous_camera_settings["resolution"] = self.current_camera_settings["resolution"]
def __show_video_enabled(self):
self.__update_camera_subscription_and_settings()
if self.new_frame and self.current_camera_settings["resolution"]:
# if self.raw_image:
opencv_image = self.bridge.compressed_imgmsg_to_cv2(self.raw_image, "rgb8")
self.__create_final_pixmaps(opencv_image)
self.image_ready_signal.emit(self.camera_name)
self.new_frame = False
def __show_video_disabled(self):
blank_frame = np.zeros((720, 1280, 3), np.uint8)
self.__create_final_pixmaps(blank_frame)
self.image_ready_signal.emit(self.camera_name)
def __create_final_pixmaps(self, opencv_image):
height, width, _ = opencv_image.shape
if width != 1280 and height != 720:
self.opencv_1280x720_image = cv2.resize(opencv_image, (1280, 720))
else:
self.opencv_1280x720_image = opencv_image
if width != 640 and height != 360:
self.opencv_640x360_image = cv2.resize(opencv_image, (640, 360))
else:
self.opencv_640x360_image = opencv_image
self.__apply_camera_name(self.opencv_1280x720_image, self.camera_name_opencv_1280x720_image)
self.__apply_camera_name(self.opencv_640x360_image, self.camera_name_opencv_640x360_image)
self.pixmap_1280x720_image = QtGui.QPixmap.fromImage(qimage2ndarray.array2qimage(
self.opencv_1280x720_image))
self.pixmap_640x360_image = QtGui.QPixmap.fromImage(qimage2ndarray.array2qimage(
self.opencv_640x360_image))
def __image_data_received_callback(self, raw_image):
self.raw_image = raw_image
self.new_frame = True
def __create_camera_name_opencv_images(self):
camera_name_text_width, camera_name_text_height = \
cv2.getTextSize(self.camera_title_name, self.font, self.font_thickness, self.font_baseline)[0]
camera_name_width_buffered = camera_name_text_width + 10
camera_name_height_buffered = camera_name_text_height + 20
camera_name_opencv_image = np.zeros(
(camera_name_height_buffered, camera_name_width_buffered, 3), np.uint8)
cv2.putText(
camera_name_opencv_image,
self.camera_title_name,
((camera_name_width_buffered - camera_name_text_width) / 2, int((camera_name_height_buffered * 2) / 3)),
self.font,
1,
(255, 255, 255),
1,
cv2.LINE_AA)
self.camera_name_opencv_1280x720_image = \
cv2.resize(camera_name_opencv_image, (camera_name_width_buffered, camera_name_height_buffered))
self.camera_name_opencv_640x360_image = \
cv2.resize(camera_name_opencv_image, (camera_name_width_buffered / 2, camera_name_height_buffered / 2))
def change_max_resolution_setting(self, resolution_max):
self.current_max_resolution = resolution_max
self.current_camera_settings["resolution"] = resolution_max
def toggle_video_display(self):
if self.video_enabled:
if self.video_subscriber:
self.video_subscriber.unregister()
self.new_frame = True
self.video_enabled = False
else:
new_topic = self.camera_topics[self.current_camera_settings["resolution"]]
self.video_subscriber = rospy.Subscriber(new_topic, CompressedImage, self.__image_data_received_callback)
# self.video_subscriber = rospy.Subscriber(self.temp_topic_path, CompressedImage,
# self.__image_data_received_callback)
self.video_enabled = True
def connect_signals_and_slots(self):
pass
def setup_signals(self, start_signal, signals_and_slots_signal, kill_signal):
start_signal.connect(self.start)
signals_and_slots_signal.connect(self.connect_signals_and_slots)
kill_signal.connect(self.on_kill_threads_requested__slot)
def on_kill_threads_requested__slot(self):
self.run_thread_flag = False
@staticmethod
def __apply_camera_name(opencv_image, font_opencv_image):
opencv_image[0:0 + font_opencv_image.shape[0], 0:0 + font_opencv_image.shape[1]] = \
font_opencv_image

View File

@@ -0,0 +1,134 @@
import sys
from PyQt5 import QtWidgets, QtCore, QtGui, uic
import signal
import rospy
import time
from cv_bridge import CvBridge, CvBridgeError
import cv2
import qimage2ndarray
import numpy as np
from geometry_msgs.msg import Twist
from sensor_msgs.msg import CompressedImage
#from sensor_msgs.msg import Image, CompressedImage
class VideoTest(QtCore.QThread):
publish_message_signal = QtCore.pyqtSignal()
image_ready_signal = QtCore.pyqtSignal()
def __init__(self, shared_objects, screen_label, video_size=None, sub_path=None):
super(VideoTest, self).__init__()
self.not_abort = True
self.shared_objects = shared_objects
self.right_screen_label = screen_label # type: QtGui.QPixmap
self.video_size = video_size
self.message = None
self.publisher = rospy.Subscriber(sub_path, CompressedImage, self.__receive_message)
self.raw_image = None
self.cv_image = None
self.pixmap = None
self.bridge = CvBridge()
# self.bridge.com
self.new_frame = False
self.frame_count = 0
self.last_frame_time = time.time()
self.fps = 0
self.name = sub_path.split("/")[2].replace("_", " ").title()
self.font = cv2.FONT_HERSHEY_TRIPLEX
thickness = 1
baseline = 0
text_size = cv2.getTextSize(self.name, self.font, thickness, baseline)
print text_size
text_width, text_height = text_size[0]
width = text_width + 10
height = text_height + 20
self.blank_image = np.zeros((height, width, 3), np.uint8)
cv2.putText(self.blank_image, self.name, ((width - text_width) / 2, int((height * 2) / 3)), self.font, 1, (255, 255, 255), 1, cv2.LINE_AA)
self.blank_image = cv2.resize(self.blank_image, (width / 2, height / 2))
def run(self):
# TODO: Thread starting message here
y_offset = 0
x_offset = 0
while self.not_abort:
if self.raw_image and self.new_frame:
self.cv_image = self.bridge.compressed_imgmsg_to_cv2(self.raw_image, "rgb8")
self.cv_image = self.__show_fps(self.cv_image)
self.cv_image[y_offset:y_offset + self.blank_image.shape[0], x_offset:x_offset + self.blank_image.shape[1]] = self.blank_image
if self.video_size:
self.cv_image = cv2.resize(self.cv_image, self.video_size)
self.pixmap = QtGui.QPixmap.fromImage(qimage2ndarray.array2qimage(self.cv_image))
self.image_ready_signal.emit()
self.new_frame = False
if (time.time() - self.last_frame_time) >= 0.5:
self.fps = int(self.frame_count / (time.time() - self. last_frame_time))
self.last_frame_time = time.time()
self.frame_count = 0
self.msleep(18)
# TODO: Thread ending message here
def __show_fps(self, image):
thickness = 1
baseline = 0
fps_string = str(self.fps)
text_size = cv2.getTextSize(fps_string, self.font, thickness, baseline)
text_width, text_height = text_size[0]
width = text_width + 10
height = text_height + 20
fps_image = np.zeros((height, width, 3), np.uint8)
cv2.putText(fps_image, fps_string, ((width - text_width) / 2, int((height * 2) / 3)), self.font, 1, (255, 255, 255), 1, cv2.LINE_AA)
fps_image = cv2.resize(fps_image, (width / 2, height / 2))
y_offset = 0
x_offset = (image.shape[1] - fps_image.shape[1]) / 2
image[y_offset:y_offset + fps_image.shape[0], x_offset:x_offset + fps_image.shape[1]] = fps_image
return image
def __on_image_update_ready(self):
self.right_screen_label.setPixmap(self.pixmap)
def __receive_message(self, message):
self.raw_image = message
self.new_frame = True
self.frame_count += 1
def connect_signals_and_slots(self):
self.image_ready_signal.connect(self.__on_image_update_ready)
def setup_signals(self, start_signal, signals_and_slots_signal, kill_signal):
start_signal.connect(self.start)
signals_and_slots_signal.connect(self.connect_signals_and_slots)
kill_signal.connect(self.on_kill_threads_requested__slot)
def on_kill_threads_requested__slot(self):
self.not_abort = False

View File

@@ -0,0 +1,10 @@
# Ground Station Software
This code is for the ground station side of the Mars Rover project.
## Requirements
* Python 3.X
* PyQt5
* ROS (Version TBD)
## How to Launch
TBD

View File

@@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1920</width>
<height>1080</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1920</width>
<height>1080</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1920</width>
<height>1080</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="windowOpacity">
<double>1.000000000000000</double>
</property>
<property name="styleSheet">
<string notr="true">background-color: #201F1D;
color: #DCDCDC;</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget_4" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>640</width>
<height>540</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>640</width>
<height>540</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:lightgreen;</string>
</property>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>640</width>
<height>540</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>640</width>
<height>540</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Recording</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Settings</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1280</width>
<height>720</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1280</width>
<height>720</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:lightblue;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>640</width>
<height>360</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>640</width>
<height>360</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:salmon;</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_3" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>360</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<height>360</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:teal;</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>360</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<height>360</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:lightgreen</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,236 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1920</width>
<height>1080</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1920</width>
<height>1080</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1920</width>
<height>1080</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="windowOpacity">
<double>1.000000000000000</double>
</property>
<property name="styleSheet">
<string notr="true">background-color: #201F1D;
color: #DCDCDC;</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="arm_visualization_widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>640</width>
<height>720</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>640</width>
<height>720</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:orange;</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetNoConstraint</enum>
</property>
<item>
<widget class="QWidget" name="heading_widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>360</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<height>360</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:lightgreen;;</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="speed_limit_widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>360</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<height>360</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:salmon;</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="primary_video_label">
<property name="minimumSize">
<size>
<width>1280</width>
<height>720</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1280</width>
<height>720</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: darkblue;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="secondary_video_label">
<property name="minimumSize">
<size>
<width>640</width>
<height>360</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>640</width>
<height>360</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:darkgreen;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="tertiary_video_label">
<property name="minimumSize">
<size>
<width>640</width>
<height>360</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>640</width>
<height>360</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color:maroon;</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,178 @@
#!/usr/bin/env python
#####################################
# Imports
#####################################
# Python native imports
import sys
from PyQt5 import QtWidgets, QtCore, QtGui, uic
import signal
import rospy
import logging
import qdarkstyle
# Custom Imports
import Framework.StartupSystems.ROSMasterChecker as ROSMasterChecker
import Framework.LoggingSystems.Logger as Logger
import Framework.VideoSystems.RoverVideoCoordinator as RoverVideoCoordinator
#####################################
# Global Variables
#####################################
UI_FILE_LEFT = "Resources/Ui/left_screen.ui"
UI_FILE_RIGHT = "Resources/Ui/right_screen.ui"
#####################################
# Class Organization
#####################################
# Class Name:
# "init"
# "run (if there)" - personal pref
# "private methods"
# "public methods, minus slots"
# "slot methods"
# "static methods"
# "run (if there)" - personal pref
#####################################
# ApplicationWindow Class Definition
#####################################
class ApplicationWindow(QtWidgets.QMainWindow):
exit_requested_signal = QtCore.pyqtSignal()
kill_threads_signal = QtCore.pyqtSignal()
def __init__(self, parent=None, ui_file_path=None):
super(ApplicationWindow, self).__init__(parent)
uic.loadUi(ui_file_path, self)
QtWidgets.QShortcut(QtGui.QKeySequence("Ctrl+Q"), self, self.exit_requested_signal.emit)
#####################################
# GroundStation Class Definition
#####################################
class GroundStation(QtCore.QObject):
LEFT_SCREEN_ID = 0
RIGHT_SCREEN_ID = 1
exit_requested_signal = QtCore.pyqtSignal()
start_threads_signal = QtCore.pyqtSignal()
connect_signals_and_slots_signal = QtCore.pyqtSignal()
kill_threads_signal = QtCore.pyqtSignal()
def __init__(self, parent=None,):
# noinspection PyArgumentList
super(GroundStation, self).__init__(parent)
# ##### Setup the Logger Immediately #####
self.logger_setup_class = Logger.Logger(console_output=True) # Doesn't need to be shared
# ########## Get the Pick And Plate instance of the logger ##########
self.logger = logging.getLogger("groundstation")
self.shared_objects = {
"screens": {},
"regular_classes": {},
"threaded_classes": {}
}
# ###### Instantiate Left And Right Screens ######
self.shared_objects["screens"]["left_screen"] = \
self.create_application_window(UI_FILE_LEFT, "Rover Ground Station Left Screen",
self.LEFT_SCREEN_ID) # type: ApplicationWindow
self.shared_objects["screens"]["right_screen"] = \
self.create_application_window(UI_FILE_RIGHT, "Rover Ground Station Right Screen",
self.RIGHT_SCREEN_ID) # type: ApplicationWindow
# ###### Initialize the Ground Station Node ######
rospy.init_node("ground_station")
# ##### Instantiate Regular Classes ######
# ##### Instantiate Threaded Classes ######
self.__add_thread("Video Coordinator", RoverVideoCoordinator.RoverVideoCoordinator(self.shared_objects))
self.connect_signals_and_slots_signal.emit()
self.__connect_signals_to_slots()
self.start_threads_signal.emit()
def ___ros_master_running(self):
checker = ROSMasterChecker.ROSMasterChecker()
if not checker.master_present(5):
self.logger.debug("ROS Master Not Found!!!! Exiting!!!")
QtGui.QGuiApplication.exit()
return False
return True
def __add_thread(self, thread_name, instance):
self.shared_objects["threaded_classes"][thread_name] = instance
instance.setup_signals(self.start_threads_signal, self.connect_signals_and_slots_signal,
self.kill_threads_signal)
def __connect_signals_to_slots(self):
self.shared_objects["screens"]["left_screen"].exit_requested_signal.connect(self.on_exit_requested__slot)
self.shared_objects["screens"]["right_screen"].exit_requested_signal.connect(self.on_exit_requested__slot)
def on_exit_requested__slot(self):
self.kill_threads_signal.emit()
# Wait for Threads
for thread in self.shared_objects["threaded_classes"]:
self.shared_objects["threaded_classes"][thread].wait()
QtGui.QGuiApplication.exit()
@staticmethod
def create_application_window(ui_file_path, title, display_screen):
system_desktop = QtWidgets.QDesktopWidget() # This gets us access to the desktop geometry
app_window = ApplicationWindow(parent=None, ui_file_path=ui_file_path) # Make a window in this application
app_window.setWindowTitle(title) # Sets the window title
app_window.setWindowFlags(app_window.windowFlags() | # Sets the windows flags to:
QtCore.Qt.FramelessWindowHint | # remove the border and frame on the application,
QtCore.Qt.WindowStaysOnTopHint | # and makes the window stay on top of all others
QtCore.Qt.X11BypassWindowManagerHint) # This is needed to show fullscreen in gnome
app_window.setGeometry(
system_desktop.screenGeometry(display_screen)) # Sets the window to be on the first screen
app_window.showFullScreen() # Shows the window in full screen mode
return app_window
#####################################
# Main Definition
#####################################
if __name__ == "__main__":
signal.signal(signal.SIGINT, signal.SIG_DFL) # This allows the keyboard interrupt kill to work properly
# ########## Start the QApplication Framework ##########
application = QtWidgets.QApplication(sys.argv) # Create the ase qt gui application
application.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
# ########## Set Organization Details for QSettings ##########
QtCore.QCoreApplication.setOrganizationName("OSURC")
QtCore.QCoreApplication.setOrganizationDomain("http://osurobotics.club/")
QtCore.QCoreApplication.setApplicationName("groundstation")
# ########## Check ROS Master Status ##########
master_checker = ROSMasterChecker.ROSMasterChecker()
if not master_checker.master_present(5):
message_box = QtWidgets.QMessageBox()
message_box.setWindowTitle("Rover Ground Station")
message_box.setText("Connection to ROS Master Failed!!!\n" +
"Ensure ROS master is running or check for network issues.")
message_box.exec_()
exit()
# ########## Start Ground Station If Ready ##########
ground_station = GroundStation()
application.exec_() # Execute launching of the application

View File

@@ -0,0 +1 @@
/opt/ros/kinetic/share/catkin/cmake/toplevel.cmake

10
software/rover/Readme.md Normal file
View File

@@ -0,0 +1,10 @@
# Rover Software
This code is what runs on the NUC onboard the Rover.
This handles everything from processing vision data to actually sending drive commands to the wheels.
## Requirements
* Python 3.X
* ROS (Version TBD)
## How to Launch
TBD

View File

@@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 2.8.3)
project(drive_test)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
stage_ros
geometry_msgs
roscpp
rospy
)
catkin_package()
include_directories(
${catkin_INCLUDE_DIRS}
)

Binary file not shown.

View File

View File

@@ -0,0 +1,7 @@
<launch>
<node pkg="stage_ros" type="stageros" name="simulator" args="$(find drive_test)/worlds/manyDots.world"/>
<node pkg="drive_test" type="drive_test.py" name="hw2" output="screen">
<param name="goalX" value="20" />
<param name="goalY" value="-20" />
</node>
</launch>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0"?>
<package>
<name>drive_test</name>
<version>0.0.0</version>
<description>ROB456 HW2</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="rob456@todo.todo">rob456</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>BSD</license>
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/pioneer_delivery</url> -->
<!-- Author tags are optional, mutiple are allowed, one per tag -->
<!-- Authors do not have to be maintianers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *_depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use run_depend for packages you need at runtime: -->
<!-- <run_depend>message_runtime</run_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>geometry_msgs</build_depend>
<build_depend>stage_ros</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<run_depend>geometry_msgs</run_depend>
<run_depend>stage_ros</run_depend>
<run_depend>roscpp</run_depend>
<run_depend>rospy</run_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>

View File

@@ -0,0 +1,90 @@
#!/usr/bin/env python
import rospy
import math
import tf
from tf.transformations import euler_from_quaternion
import message_filters
from pprint import pprint
import time
# The laser scan message
from sensor_msgs.msg import Joy
# The odometry message
from nav_msgs.msg import Odometry
# the velocity command message
from geometry_msgs.msg import Twist
# global pi - this may come in handy
pi = math.pi
# method to control the robot
def callback_spacenav(twist_message):
scalar_forward = 100.0
scalar_turn = 2.0
# make a new twist message
command = Twist()
# Fill in the fields. Field values are unspecified
# until they are actually assigned. The Twist message
# holds linear and angular velocities.
command.linear.x = twist_message.linear.x * scalar_forward
command.linear.y = twist_message.linear.y * scalar_forward
command.linear.z = twist_message.linear.z * scalar_forward
command.angular.x = twist_message.angular.x * scalar_forward
command.angular.y = twist_message.angular.y * scalar_forward
command.angular.z = twist_message.angular.z * scalar_turn
# print command
# Send the commands
pub.publish(command)
# method to control the robot
def callback_joy(joy_message):
scalar_forward = 100.0
scalar_turn = 2.0
# make a new twist message
command = Twist()
# Fill in the fields. Field values are unspecified
# until they are actually assigned. The Twist message
# holds linear and angular velocities.
command.linear.x = joy_message.axes[1] * 100
#command.linear.y = twist_message.linear.y * scalar_forward
#command.linear.z = twist_message.linear.z * scalar_forward
#command.angular.x = twist_message.angular.x * scalar_forward
#command.angular.y = twist_message.angular.y * scalar_forward
command.angular.z = joy_message.axes[0] * 1.0
# command.angular.z = joy_message.axes[2] * 1.0
print joy_message
# Send the commands
pub.publish(command)
# main function call
if __name__ == "__main__":
# Initialize the node
rospy.init_node('drive_test', log_level=rospy.DEBUG)
# subscribe to laser scan message
# sub = rospy.Subscriber('/spacenav/twist', Twist, callback_spacenav)
# subscribe to laser scan message
sub = rospy.Subscriber('/joy', Joy, callback_joy)
# synchronize laser scan and odometry data
# ts = message_filters.TimeSynchronizer([sub, sub2], 10)
# ts.registerCallback(callback)
# publish twist message
pub = rospy.Publisher('cmd_vel', Twist, queue_size=10)
# Turn control over to ROS
rospy.spin()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
define block model
(
size [0.5 0.5 0.5]
gui_nose 0
)
define topurg ranger
(
sensor(
range [ 0.0 30.0 ]
fov 270.25
samples 1081
)
# generic model properties
color "black"
size [ 0.05 0.05 0.1 ]
)
define erratic position
(
size [0.35 0.35 0.25]
origin [-0.05 0 0 0]
gui_nose 0
drive "diff"
topurg(pose [ 0.050 0.000 0 0.000 ])
odom_error [0.00 0.00 0.00 0.00 0.00 0.00]
)
define floorplan model
(
# sombre, sensible, artistic
color "gray30"
# most maps will need a bounding box
boundary 1
gui_nose 0
gui_grid 0
gui_outline 0
gripper_return 0
fiducial_return 0
laser_return 1
)
# set the resolution of the underlying raytrace model in meters
resolution 0.005
interval_sim 100 # simulation timestep in milliseconds
window
(
size [ 745.000 448.000 ]
rotate [ 0.000 0.000 ]
scale 5
)
# load an environment bitmap
floorplan
(
name "manyDots"
bitmap "manyDots.pgm"
size [54.0 58.7 0.5]
pose [ 0 0.0 0 90.000 ]
)
# throw in a robot
erratic( pose [ -10.000 10.000 0 90.000 ] name "era" color "blue" localizaion "gps" localization_origin [0 0 0 0])

View File

@@ -0,0 +1,197 @@
cmake_minimum_required(VERSION 2.8.3)
project(launcher)
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
rospy
)
## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)
## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()
################################################
## Declare ROS messages, services and actions ##
################################################
## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
## * add a build_depend tag for "message_generation"
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
## but can be declared for certainty nonetheless:
## * add a run_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
## * add "message_generation" and every package in MSG_DEP_SET to
## find_package(catkin REQUIRED COMPONENTS ...)
## * add "message_runtime" and every package in MSG_DEP_SET to
## catkin_package(CATKIN_DEPENDS ...)
## * uncomment the add_*_files sections below as needed
## and list every .msg/.srv/.action file to be processed
## * uncomment the generate_messages entry below
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
## Generate messages in the 'msg' folder
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )
## Generate services in the 'srv' folder
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
## Generate actions in the 'action' folder
# add_action_files(
# FILES
# Action1.action
# Action2.action
# )
## Generate added messages and services with any dependencies listed here
# generate_messages(
# DEPENDENCIES
# std_msgs # Or other packages containing msgs
# )
################################################
## Declare ROS dynamic reconfigure parameters ##
################################################
## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
## * add a build_depend and a run_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
## * add "dynamic_reconfigure" to
## find_package(catkin REQUIRED COMPONENTS ...)
## * uncomment the "generate_dynamic_reconfigure_options" section below
## and list every .cfg file to be processed
## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
# cfg/DynReconf1.cfg
# cfg/DynReconf2.cfg
# )
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES launcher
# CATKIN_DEPENDS rospy
# DEPENDS system_lib
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
## Declare a C++ library
# add_library(${PROJECT_NAME}
# src/${PROJECT_NAME}/launcher.cpp
# )
## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/launcher_node.cpp)
## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
#############
## Install ##
#############
# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark executables and/or libraries for installation
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
# # myfile1
# # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_launcher.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

Binary file not shown.

View File

@@ -0,0 +1,15 @@
<launch>
<node name="rover_gps" pkg="ublox_gps" type="ublox_gps" output="screen" clear_params="false" respawn="true" respawn_delay="10">
<rosparam command="load" file="$(find ublox_gps)/config/nmea.yaml" />
</node>
<node pkg="robot_localization" type="navsat_transform_node" name="navsat_transform" respawn="true" output="screen">
<param name="magnetic_declination_radians" value="0"/>
<param name="yaw_offset" value="0"/>
<remap from="/imu/data" to="/your/imu/topic" />
<remap from="/gps/fix" to="/rover_gps/fix" />
<remap from="/odometry/filtered" to="/your/robot_localization/output/topic" />
</node>
</launch>

View File

@@ -0,0 +1,62 @@
<?xml version="1.0"?>
<package format="2">
<name>launcher</name>
<version>0.0.0</version>
<description>The launcher package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="caperren@todo.todo">caperren</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>TODO</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/launcher</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<!-- <exec_depend>message_runtime</exec_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>rospy</build_depend>
<build_export_depend>rospy</build_export_depend>
<exec_depend>rospy</exec_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>

View File

@@ -0,0 +1,17 @@
import rospy
from geometry_msgs.msg import Quaternion, Vector3
from std_msgs.msg import Float64
if __name__ == "__main__":
rospy.init_node("imu_test")
orientation = Quaternion()
orientation_covarience = Float64()
angular_velocity = Vector3()
angular_velocity_covarience = Float64()
linear_acceleration = Vector3()
linear_acceleration_covarience = Float64()

View File

@@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 2.8)
project(rover_camera)
add_compile_options(-std=c++11)
find_package(catkin REQUIRED COMPONENTS cv_bridge image_transport message_generation sensor_msgs)
# add the resized image message
catkin_package(CATKIN_DEPENDS cv_bridge image_transport message_runtime sensor_msgs)
find_package(OpenCV)
include_directories(include ${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})
# add the publisher example
add_executable(rover_camera src/rover_camera.cpp)
add_dependencies(rover_camera ${catkin_EXPORTED_TARGETS} ${${PROJECT_NAME}_EXPORTED_TARGETS})
target_link_libraries(rover_camera ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})
# Mark executables and/or libraries for installation
install(TARGETS rover_camera
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
#install(FILES resized_plugins.xml
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
#)

View File

@@ -0,0 +1,23 @@
<launch>
<group ns="cameras">
<node name="camera_undercarriage" pkg="rover_camera" type="rover_camera" launch-prefix="taskset -c 1" output="screen">
<param name="device_path" value="/dev/rover/camera_undercarriage"/>
</node>
<node name="main_navigation" pkg="rover_camera" type="rover_camera" launch-prefix="taskset -c 2" output="screen" >
<param name="device_path" value="/dev/rover/camera_main_navigation" />
</node>
<node name="gimbal" pkg="rover_camera" type="rover_camera" launch-prefix="taskset -c 3" output="screen" >
<param name="device_path" value="/dev/rover/camera_gimbal" />
</node>
</group>
<!--
<node name="image_view" pkg="image_view" type="image_view" launch-prefix="taskset -c 4" output="screen">
<remap from="image" to="/cameras/camera_name/image_720p"/>
</node>
-->
</launch>

View File

@@ -0,0 +1,23 @@
<package>
<name>rover_camera</name>
<version>0.0.0</version>
<description>This package opens a camera on linux using OpenCV and publishes multiple streams at different resolutions</description>
<author>Corwin Perren</author>
<maintainer email="caperren@gmail.com">Corwin Perren</maintainer>
<license>Apache 2.0</license>
<build_depend>cv_bridge</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>message_generation</build_depend>
<build_depend>opencv2</build_depend>
<build_depend>sensor_msgs</build_depend>
<run_depend>cv_bridge</run_depend>
<run_depend>image_transport</run_depend>
<run_depend>message_runtime</run_depend>
<run_depend>opencv2</run_depend>
<run_depend>sensor_msgs</run_depend>
<buildtool_depend>catkin</buildtool_depend>
</package>

View File

@@ -0,0 +1,88 @@
#include <string>
#include <iostream>
#include <ros/ros.h>
#include <ros/console.h>
#include <image_transport/image_transport.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
int main(int argc, char** argv)
{
std::string capture_device_path;
int fps;
int large_image_width;
int large_image_height;
int medium_image_width;
int medium_image_height;
int small_image_width;
int small_image_height;
ros::init(argc, argv, "camera");
ros::NodeHandle node_handle("~");
node_handle.param("device_path", capture_device_path, std::string("/dev/video0"));
node_handle.param("fps", fps, 30);
node_handle.param("large_image_width", large_image_width, 1280);
node_handle.param("large_image_height", large_image_height, 720);
node_handle.param("medium_image_width", medium_image_width, 640);
node_handle.param("medium_image_height", medium_image_height, 360);
node_handle.param("small_image_width", small_image_width, 256);
node_handle.param("small_image_height", small_image_height, 144);
cv::VideoCapture cap(capture_device_path);
cap.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
cap.set(CV_CAP_PROP_FRAME_WIDTH, large_image_width);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, large_image_height);
cap.set(CV_CAP_PROP_FPS, fps);
if(cap.isOpened() == false){
return -1;
}
std::string large_image_node_name = "image_" + std::to_string(large_image_width) + "x" + std::to_string(large_image_height);
std::string medium_image_node_name = "image_" + std::to_string(medium_image_width) + "x" + std::to_string(medium_image_height);
std::string small_image_node_name = "image_" + std::to_string(small_image_width) + "x" + std::to_string(small_image_height);
image_transport::ImageTransport large_image_transport(node_handle);
image_transport::ImageTransport medium_image_transport(node_handle);
image_transport::ImageTransport small_image_transport(node_handle);
image_transport::Publisher large_image_publisher = large_image_transport.advertise(large_image_node_name, 1);
image_transport::Publisher medium_image_publisher = medium_image_transport.advertise(medium_image_node_name, 1);
image_transport::Publisher small_image_publisher = small_image_transport.advertise(small_image_node_name, 1);
cv::Mat image_large;
cv::Mat image_medium;
cv::Mat image_small;
ros::Rate loop_rate(fps + 2);
while (ros::ok()) {
cap.read(image_large);
if(!image_large.empty()){
cv::resize(image_large, image_medium, cv::Size(medium_image_width, medium_image_height));
cv::resize(image_medium, image_small, cv::Size(small_image_width, small_image_height));
sensor_msgs::ImagePtr large_image_message = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image_large).toImageMsg();
sensor_msgs::ImagePtr medium_image_message = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image_medium).toImageMsg();
sensor_msgs::ImagePtr small_image_message = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image_small).toImageMsg();
large_image_publisher.publish(large_image_message);
medium_image_publisher.publish(medium_image_message);
small_image_publisher.publish(small_image_message);
}
ros::spinOnce();
loop_rate.sleep();
}
cap.release();
}

View File

@@ -0,0 +1,198 @@
cmake_minimum_required(VERSION 2.8.3)
project(rover_main)
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
rospy
std_msgs
)
## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)
## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()
################################################
## Declare ROS messages, services and actions ##
################################################
## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
## * add a build_depend tag for "message_generation"
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
## but can be declared for certainty nonetheless:
## * add a run_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
## * add "message_generation" and every package in MSG_DEP_SET to
## find_package(catkin REQUIRED COMPONENTS ...)
## * add "message_runtime" and every package in MSG_DEP_SET to
## catkin_package(CATKIN_DEPENDS ...)
## * uncomment the add_*_files sections below as needed
## and list every .msg/.srv/.action file to be processed
## * uncomment the generate_messages entry below
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
## Generate messages in the 'msg' folder
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )
## Generate services in the 'srv' folder
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
## Generate actions in the 'action' folder
# add_action_files(
# FILES
# Action1.action
# Action2.action
# )
## Generate added messages and services with any dependencies listed here
# generate_messages(
# DEPENDENCIES
# std_msgs
# )
################################################
## Declare ROS dynamic reconfigure parameters ##
################################################
## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
## * add a build_depend and a run_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
## * add "dynamic_reconfigure" to
## find_package(catkin REQUIRED COMPONENTS ...)
## * uncomment the "generate_dynamic_reconfigure_options" section below
## and list every .cfg file to be processed
## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
# cfg/DynReconf1.cfg
# cfg/DynReconf2.cfg
# )
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES rover
# CATKIN_DEPENDS rospy std_msgs
# DEPENDS system_lib
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
## Declare a C++ library
# add_library(${PROJECT_NAME}
# src/${PROJECT_NAME}/rover.cpp
# )
## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/rover_node.cpp)
## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
#############
## Install ##
#############
# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark executables and/or libraries for installation
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
# # myfile1
# # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_rover.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

View File

@@ -0,0 +1,52 @@
<launch>
<!-- ########## Start Hardware Interface Nodes ########## -->
<!-- ### Start Drive Interfaces ### -->
<!-- Start Left Bogie Interface -->
<!-- Start Right Bogie Interface -->
<!-- Start Rear Bogie Interface -->
<!-- ### Start Arm Interfaces ### -->
<!-- Start Arm Base Interface -->
<!-- Start Arm End Effector Interface -->
<!-- ### Start Miscellaneous Interfaces ### -->
<!-- Start Sample Containment Interface -->
<!-- Start Tower Interface -->
<!-- Start Chassis Pan/Tilt Interface -->
<!-- Start Iris Interface -->
<!-- ########## Start All Rover Camera Nodes ########## -->
<!-- ### Start 2D Cameras ### -->
<group ns="cameras">
<!-- Start Undercarriage Camera -->
<node name="undercarriage" pkg="rover_camera" type="rover_camera" launch-prefix="taskset -c 1" respawn="true" output="screen">
<param name="device_path" value="/dev/rover/camera_undercarriage"/>
</node>
<!-- Start Main Navigation Camera -->
<node name="main_navigation" pkg="rover_camera" type="rover_camera" launch-prefix="taskset -c 2" respawn="true" output="screen" >
<param name="device_path" value="/dev/rover/camera_main_navigation" />
</node>
<!-- Start Chassis Camera -->
<node name="chassis" pkg="rover_camera" type="rover_camera" launch-prefix="taskset -c 3" respawn="true" output="screen" >
<param name="device_path" value="/dev/rover/camera_chassis" />
</node>
<!-- ### Start 3D Cameras ### -->
<!-- Start ZED Camera -->
<group ns="zed">
<include file="$(find zed_wrapper)/launch/zed_camera.launch">
<!-- compliant mode for rviz -->
<arg name="odometry_frame" value="map" />
</include>
</group>
</group>
<!-- ########## Start System Status Monitoring Nodes ########## -->
<!-- Start System CPU / RAM / Filesystem Monitor -->
<!-- Start System Temperature Monitor -->
</launch>

View File

@@ -0,0 +1,6 @@
<launch>
<node name="navsat" pkg="nmea_navsat_driver" type="nmea_serial_driver" respawn="true">
<param name="port" value="/dev/rover/ttyGPS"/>
<param name="baud" value="9600"/>
</node>
</launch>

View File

@@ -0,0 +1,65 @@
<?xml version="1.0"?>
<package format="2">
<name>rover_main</name>
<version>0.0.0</version>
<description>The rover package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="caperren@todo.todo">caperren</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>TODO</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/rover</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<!-- <exec_depend>message_runtime</exec_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>

92
software/rover/ublox-master/.gitignore vendored Normal file
View File

@@ -0,0 +1,92 @@
# BUILD PRODUCTS
*.d
*.o
*.disasm
*.map
*.elf
*.bin
*.hex
*.slo
*.lo
*.obj
# CMAKE TEMPORARY FILES
CMakeCache.txt
CMakeFiles/
CMakeFiles/*
# BUILD FOLDERS
bin/
bin/*
build/
build/*
# ROS GENERATED PRODUCTS
msg_gen/
msg_gen/*
srv_gen/
srv_gen/*
# ROS GENERATED PYTHON
_*.py
_*.pyc
# ROS BAG FILES
*.bag
# XCODE BUILD PRODUCTS
*.build/
*.build/*
# XCODE USER SETTINGS
*.xcuserdatad/
*.xcuserdatad/*
*.pbxuser
*.pbxuser/*
# QTCREATOR PROJECT
*.includes
*.creator
*.creator.user
*.config
*.files
# GEANY PROJECTS
*.geany
# JETBRAINS
*.idea
# ZEND/ECLIPSE
*.buildpath
*.settings
*.project
*.pydevproject
# MACOSX SETTINGS
*.DS_Store
# GENERATED DOCUMENTATION
html_docs/
html_docs/*
# ANDROID SDK GENERATED JAVA
gen/
gen/*
# COMPILED DYNAMIC LIBRARIES
*.so
*.dylib
*.dll
# COMPILED STATIC LIBRARIES
*.lai
*.la
*.a
*.lib
# EXECUTABLES
*.exe
*.out
*.app

View File

@@ -0,0 +1,353 @@
# ublox
The `ublox` package provides support for [u-blox](http://www.u-blox.com) GPS receivers. Only the _serial_ configuration of the driver is documented here, but TCP communication is also supported by the driver (untested).
The driver was originally written by Johannes Meyer. Changes made later are detailed in the version history below.
## Options
Example .yaml configuration files are included in `ublox_gps/config`. Consult the u-blox documentation for your device for the recommended settings.
The `ublox_gps` node supports the following parameters for all products and firmware versions:
* `device`: Path to the device port. Defaults to `/dev/ttyACM0`.
* `raw_data`: Whether the device is a raw data product. Defaults to false. Firmware <= 7.03 only.
* `load`: Parameters for loading the configuration to non-volatile memory. See `ublox_msgs/CfgCFG.msg`
* `load/mask`: uint32_t. Mask of the configurations to load.
* `load/device`: uint32_t. Mask which selects the devices for the load command.
* `save`: Parameters for saving the configuration to non-volatile memory. See `ublox_msgs/CfgCFG.msg`
* `save/mask`: uint32_t. Mask of the configurations to save.
* `save/device`: uint32_t. Mask which selects the devices for the save command.
* `uart1/baudrate`: Bit rate of the serial communication. Defaults to 9600.
* `uart1/in`: UART1 in communication protocol. Defaults to UBX, NMEA & RTCM. See `CfgPRT` message for possible values.
* `uart1/out`: UART1 out communication protocol. Defaults to UBX, NMEA & RTCM. See `CfgPRT` message for possible values.
* `frame_id`: ROS name prepended to frames produced by the node. Defaults to `gps`.
* `rate`: Rate in Hz of measurements. Defaults to 4.
* `nav_rate`: How often navigation solutions are published in number of measurement cycles. Defaults to 1.
* `enable_ppp`: Enable precise-point-positioning system. Defaults to false.
* `gnss/sbas`: Enable satellite-based augmentation system. Defaults to false.
* `sbas/max`: Maximum number of SBAS channels. Defaults to 0.
* `sbas/usage`: See `CfgSBAS` message for details. Defaults to 0.
* `dynamic_model`: Possible values below. Defaults to `portable`. See u-blox documentation for further description.
* `portable`
* `stationary`
* `pedestrian`
* `automotive`
* `sea`
* `airborne1`: Airborne, max acceleration = 1G
* `airborne2`: Airborne, max acceleration = 2G
* `airborne4`: Airborne, max acceleration = 4G
* `wristwatch`
* `fix_mode`: Type of fixes supported: `2d`, `3d` or `both`.
* `dr_limit`: Max time in seconds to use dead reckoning after signal is lost. Defaults to 0.
* `dat`: Configuring the datum type (optional). See the CfgDAT message.
* `dat/set`: If true, the node will the datum based on the parameters below (required if true). Defaults to false.
* `dat/majA`: Semi-major Axis [m]
* `dat/flat`: 1.0 / Flattening
* `dat/shift`: [X-axis, Y-axis, Z-axis] shift [m]
* `dat/rot`: [X, Y, Z] rotation [s]
* `dat/scale`: scale change [ppm]
### For firmware version 6:
* `nmea/set`: If true, the NMEA will be configured with the parameters below.
* `nmea/version`: NMEA version. Must be set if `nmea/set` is true.
* `nmea/num_sv`: Maximum Number of SVs to report per TalkerId. Must be set if `nmea/set` is true.
* `nmea/compat`: Enable compatibility mode. Must be set if `nmea/set` is true.
* `nmea/consider`: Enable considering mode. Must be set if `nmea/set` is true.
* `nmea/filter`: Namespace for filter flags.
* `nmea/filter/pos`: Disable position filtering. Defaults to false.
* `nmea/filter/msk_pos`: Disable masked position filtering. Defaults to false.
* `nmea/filter/time`: Disable time filtering. Defaults to false.
* `nmea/filter/date`: Disable date filtering. Defaults to false.
* `nmea/filter/sbas`: Enable SBAS filtering. Defaults to false.
* `nmea/filter/track`: Disable track filtering. Defaults to false.
### For devices with firmware >= 7:
* `gnss` parameters:
* `gnss/gps`: Enable GPS receiver. Defaults to true.
* `gnss/glonass`: Enable GLONASS receiver. Defaults to false.
* `gnss/beidou`: Enable BeiDou receiver. Defaults to false.
* `gnss/qzss`: Enable QZSS receiver. Defaults to false.
* `gnss/qzss_sig_cfg`: QZSS signal configuration. Defaults to L1CA. See `CfgGNSS` message for constants.
* `nmea` parameters:
* `nmea/set`: If true, the NMEA will be configured.
* `nmea/version`: NMEA version. Must be set if `nmea/set` is true.
* `nmea/num_sv`: Maximum Number of SVs to report per TalkerId. Must be set if `nmea/set` is true.
* `nmea/sv_numbering`: Configures the display of satellites that do not have an NMEA-defined value. Must be set if `nmea/set` is true.
* `nmea/compat`: Enable compatibility mode. Must be set if `nmea/set` is true.
* `nmea/consider`: Enable considering mode. Must be set if `nmea/set` is true.
* `nmea/limit82`: Enable strict limit to 82 characters maximum. Defaults to false.
* `nmea/high_prec`: Enable high precision mode. Defaults to false.
* `nmea/filter`: Namespace for filter flags.
* `nmea/filter/pos`: Enable position output for failed or invalid fixes. Defaults to false.
* `nmea/filter/msk_pos`: Enable position output for invalid fixes. Defaults to false.
* `nmea/filter/time`: Enable time output for invalid times. Defaults to false.
* `nmea/filter/date`: Enable date output for invalid dates. Defaults to false.
* `nmea/filter/gps_only`: Restrict output to GPS satellites only. Defaults to false.
* `nmea/filter/track`: Enable COG output even if COG is frozen. Defaults to false.
* `nmea/gnssToFilt`: Filters out satellites based on their GNSS.
* `nmea/gnssToFilt/gps`: Disable reporting of GPS satellites. Defaults to false.
* `nmea/gnssToFilt/sbas`: Disable reporting of SBAS satellites. Defaults to false.
* `nmea/gnssToFilt/qzss`: Disable reporting of QZSS satellites. Defaults to false.
* `nmea/gnssToFilt/glonass`: Disable reporting of GLONASS satellites. Defaults to false.
* `nmea/gnssToFilt/beidou`: Disable reporting of BeiDou satellites. Defaults to false.
* `nmea/main_talker_id`: This field enables the main Talker ID to be overridden. Defaults to 0.
* `nmea/gsv_talker_id`: This field enables the GSV Talker ID to be overridden. Defaults to [0, 0].
### For devices with firmware >= 8:
* `save_on_shutdown`: If true, the node will send a `UBX-UPD-SOS` command to save the BBR to flash memory on shutdown. Defaults to false.
* `clear_bbr`: If true, the node will send a `UBX-UPD-SOS` command to clear the flash memory during configuration. Defaults to false.
* Additional `gnss` params
* `gnss/galileo`: Enable Galileo receiver. Defaults to false.
* `gnss/imes`: Enable IMES receiver. Defaults to false.
* `nmea/bds_talker_id`: (See other NMEA configuration parameters above) Sets the two characters that should be used for the BeiDou Talker ID.
### For UDR/ADR devices:
* `use_adr`: Enable ADR/UDR. Defaults to true.
* `nav_rate` should be set to 1 Hz.
### For HPG Reference devices:
* `tmode3`: Time Mode. Required. See CfgTMODE3 for constants.
* `arp/lla_flag`: True if the Fixed position is in Lat, Lon, Alt coordinates. False if ECEF. Required if `tmode3` is set to fixed.
* `arp/position`: Antenna Reference Point position in [m] or [deg]. Required if `tmode3` is set to fixed.
* `arp/position_hp`: Antenna Reference Point High Precision position in [0.1 mm] or [deg * 1e-9]. Required if tmode3 is set to fixed.
* `arp/acc`: Fixed position accuracy in [m]. Required if `tmode3` is set to fixed.
* `sv_in/reset`: Whether or not to reset the survey in upon initialization. If false, it will only reset if the TMODE is disabled. Defaults to true.
* `sv_in/min_dur`: The minimum Survey-In Duration time in seconds. Required tmode3 is set to survey in.
* `sv_in/acc_lim`: The minimum accuracy level of the survey in position in meters. Required `tmode3` is set to survey in.
### For HPG Rover devices:
* `dgnss_mode`: The Differential GNSS mode. Defaults to RTK FIXED. See `CfgDGNSS` message for constants.
### For FTS & TIM devices:
* currently unimplemented. See `FtsProduct` and `TimProduct` classes in `ublox_gps` package `node.h` & `node.cpp` files.
## Fix Topics
`~fix`([sensor_msgs/NavSatFix](http://docs.ros.org/api/sensor_msgs/html/msg/NavSatFix.html))
Navigation Satellite fix.
`~fix_velocity`([geometry_msgs/TwistWithCovarianceStamped](http://docs.ros.org/jade/api/geometry_msgs/html/msg/TwistWithCovarianceStamped.html))
Velocity in local ENU frame.
## INF messages
To enable printing INF messages to the ROS console, set the parameters below.
* `inf/all`: This is the default value for the INF parameters below, which enable printing u-blox `INF` messages to the ROS console. It defaults to true. Individual message types can be turned off by setting their corresponding parameter to false.
* `inf/debug`: Whether to configure the UBX and NMEA ports to send Debug messages and print received `INF-Debug` messages to `ROS_DEBUG` console.
* `inf/error`: Whether to enable Error messages for the UBX and NMEA ports and print received `INF-Error` messages to `ROS_ERROR` console.
* `inf/notice`: Whether to enable Notice messages for the UBX and NMEA ports and print received `INF-Notice messages to `ROS_INFO` console.
* `inf/test`: Whether to enable Test messages for the UBX and NMEA ports and print received `INF-Test` messages to `ROS_INFO` console.
* `inf/warning`: Whether to enable Warning messages for the UBX and NMEA ports and print received `INF-Warning` messages to the `ROS_WARN` console.
## Additional Topics
To publish a given u-blox message to a ROS topic, set the parameter shown below to true. The node sets the rate of the u-blox messages to 1 measurement cycle.
### All messages
* `publish/all`: This is the default value for `publish/<class>/all` parameters below. It defaults to false. Individual message classes and messages can be enabled or disabled by setting the parameters described below to false.
### AID messages
* `publish/aid/all`: This is the default value for the `publish/aid/<message>` parameters below. It defaults to `publish/all`. Individual messages can be enabled or disabled by setting the parameters below.
* `publish/aid/alm`: Topic `~aidalm`
* `publish/aid/eph`: Topic `~aideph`
* `publish/aid/hui`: Topic `~aidhui`
### RXM messages
* `publish/rxm/all`: This is the default value for the `publish/rxm/<message>` parameters below. It defaults to `publish/all`. Individual messages can be enabled or disabled by setting the parameters below.
* `publish/rxm/alm`: Topic `~rxmalm`
* `publish/rxm/eph`: Topic `~rxmeph`
* `publish/rxm/raw`: Topic `~rxmraw`. Type is either `RxmRAW` or `RxmRAWX` depending on firmware version.
* `publish/rxm/rtcm`: Topic `~rxmrtcm`. **Firmware >= 8 only**
* `publish/rxm/sfrb`: Topic `~rxmsfrb`. Type is either `RxmSFRB` or `RxmSFRBX` depending on firmware version.
### MON messages
* `publish/mon/all`: This is the default value for the `publish/mon/<message>` parameters below. It defaults to `publish/all`. Individual messages can be enabled or disabled by setting the parameters below.
* `publish/mon/hw`: Topic `~monhw`
### NAV messages
* `publish/nav/all`: This is the default value for the `publish/mon/<message>` parameters below. It defaults to `publish/all`. Individual messages can be enabled or disabled by setting the parameters below.
* `publish/nav/att`: Topic `~navatt`. **ADR/UDR devices only**
* `publish/nav/clock`: Topic `~navclock`
* `publish/nav/posecef`: Topic `~navposecef`
* `publish/nav/posllh`: Topic `~navposllh`. **Firmware <= 6 only.** For firmware 7 and above, see NavPVT
* `publish/nav/pvt`: Topic `~navpvt`. **Firmware >= 7 only.**
* `publish/nav/relposned`: Topic `~navrelposned`. **HPG Rover devices only**
* `publish/nav/sat`: Topic `~navsat`
* `publish/nav/sol`: Topic `~navsol`. **Firmware <= 6 only.** For firmware 7 and above, see NavPVT
* `publish/nav/status`: Topic `~navstatus`
* `publish/nav/svin`: Topic `~navsvin`. **HPG Reference Station Devices only**
* `publish/nav/svinfo`: Topic `~navsvinfo`
* `publish/nav/velned`: Topic `~navvelned`. **Firmware <= 6 only.** For firmware 7 and above, see NavPVT
### ESF messages
* `publish/esf/all`: This is the default value for the `publish/esf/<message>` parameters below. It defaults to `publish/all` for **ADR/UDR devices**. Individual messages can be enabled or disabled by setting the parameters below.
* `publish/esf/ins`: Topic `~esfins`
* `publish/esf/meas`: Topic `~esfmeas`
* `publish/esf/raw`: Topic `~esfraw`
* `publish/esf/status`: Topic `~esfstatus`
### HNR messages
* `publish/hnr/pvt`: Topic `~hnrpvt`. **ADR/UDR devices only**
## Launch
A sample launch file `ublox_device.launch` loads the parameters from a `.yaml` file in the `ublox_gps/config` folder, sample configuration files are included. The required arguments are `node_name` and `param_file_name`.
The two topics to which you should subscribe are `~fix` and `~fix_velocity`. The angular component of `fix_velocity` is unused.
# Version history
* **1.1.2**:
- BUG FIX for NavSatFix messages for firmware >=7. The NavSatFix now only uses the NavPVT message time if it is valid, otherwise it uses ROS time.
- BUG FIX for TMODE3 Fixed mode configuration. The ARP High Precision position is now configured correctly.
- BUG FIX for `NavDGPS` message which had the wrong Message ID.
- After GNSS configuration & reset, I/O resets automatically, without need for restart.
- Added `UBX-UPD` messages. For firmware version 8, the node can now save the flash memory on shutdown and clear the flash memory during configuration based on ROS params.
- Added `CfgGPS` message and `MonHW6` message for firmware version 6.
- Added respawn parameters to example launch file.
- Added parameters to load/save configuration.
- Added raw_data parameter for Raw Data Products.
- Changed name of "subscribe" parameter namespace to "publish" for clarity.
- Migrated all callback handling to `callback.h` from `gps.h` and `gps.cpp`. ACK messages are now processed through callback handlers.
- Modified how the I/O stream is initialized so that the node now handles parsing the port string.
- Changed class names of Ublox product components (e.g. UbloxTim -> TimProduct) for clarity.
- Cleaned up ublox custom serialization classes by adding typedefs and using count to determine repeating block statements instead of using try-catch statements to serialize stream.
- Added doxygen documentation
* **1.1.1**:
- BUG FIX for acknowledgments. The last received ack message was accessed by multiple threads but was not atomic. This variable is now thread safe.
- BUG FIX for GNSS configuration for Firmware 8, the GNSS configuration is now verified & modified properly.
- BUG FIX for fix diagnostics. NumSV was displaying incorrectly. For firmware versions >=7, the NavPVT flags variable is now compared to the constants from the NavPVT message not NavSOL.
- Removed ublox_version param, value is now determined by parsing MonVER.
- Organized parameters into namespaces.
- Better parameter checking. Checks that unsigned ints and vectors of unsigned ints are in bounds.
- Changed rtcm/rate parameter to a vector instead of a scalar, now each RTCM id can be set to a different rate.
- Diagnostic variables are displayed more clearly with units included.
- For HPG Rovers, added diagnostic updater for Carrier Phase Solution.
- Added CfgNMEA messages for each firmware version and a CfgDAT message, as well as parameters to configure the NMEA and Datum.
- Added constants for NavSAT_SV flags bit mask.
* **1.1.0**:
- BUG FIX for NAV-PVT messages for firmware 7. The NAV-PVT message is shorter for firmware version 7, the new message is `NavPVT7`
- BUG FIX for SBAS configuration, it now configures SBAS only if the device is SBAS capable. Previously, if enable_sbas was set to false, it would not configure, meaning that SBAS could not be turned off.
- BUG FIX, the baudrate of the serial I/O port was not configured correctly, on the device it was set to the user desired settings, but on the computer it was always set to 4800.
- BUG FIX, Diagnostics for Nav Status are now updated in firmware version 6.
- BUG FIX, The method which waited for ACKs now checks if the ACK is from the correct class and message ID.
- Added messages for `CfgTMODE3`, `CfgHNR`, `CfgRST`, `CfgINF`, `NavATT`, `ESF` messages, `Inf` message (for all INF types), `HnrPVT`, `MgaGAL`, `NavSAT`, `MonHw`, `NavPVT7` (for firmware version 7).
- Restructured Node class so that it now uses composition. The main node contains instances of classes which implement `UBloxInterface`, and calls the methods for each interface added to the node. The classes which implement the interface add new features that are not generic to all firmware versions or products. Each firmware version (6-8) has an interface, and each product category has one (SPG, HPG REF, HPG ROV, TIM, FTS, ADR/UDR). The product type is determined from parsing the `MonVER` message.
- Added implementations of `ComponentInterface` called `UbloxHpgRef` and `UbloxHpgRov` for HPG reference station and rover devices. The reference station tmode3 can be configured upon startup (see Options section) and the rover dgnss mode can be set. After survey in, once the reference station entire time mode, the nav_rate is set to the user desired value (it must be 1 Hz during survey-in) and the RTCM output messages are enabled. The state can be monitored through the rqt_runtime_monitor. These classes were tested on C94-M8P devices.
- Added an implementation of `ComponentInterface` called `UbloxAdrUdr` for ADR/UDR devices. It which subscribes to `NavATT` and ESF messages and configures useAdr. The diagnostics monitor specific to these devices is not implemented. This class has not been tested on a hardware device.
- Added a partial implementation of `UbloxTim` for TIM devices which subscribes to `RxmRAWX` and `RxmSFRBX` messages. The `getRosParams()`, `configureUblox()`, and `initializeDiagnostics()` methods are unimplemented.
- Added a skeleton class for `UbloxFts` for FTS devices which is unimplemented. See the `ublox_gps` `node.cpp` and `node.h` files.
- Changed how GNSS is configured in firmware version 8. The documentation recommends a cold restart after reconfiguring the GNSS, and will reset the device if it receives a `CfgGNSS` message, even if the settings do not change. For firmware version 8, before reconfiguring, the node first checks if the current GNSS settings are the same as the desired settings. If so, it will not send a CfgGNSS message to the device. After reconfiguring, it will cold reset the GNSS.
- Migrated I/O initialization to the `Gps` class from the `Node` class.
- INF messages are now printed to the ROS console.
- Changed how debug statements are displayed. If the debug parameter is set to 1 or greater, it prints debug messages.
* **1.0.0**:
- Added messages for firmware 8: `NavPVT`, `RxmRAWX`, `RxmSFRBX`.
- Modified ConfigGNSS and MonVER to include repeated blocks and added
ConfigGNSS_Block (configures all GNSS at once) and MonVER_Extension
(for MonVER_Char blocks).
- MonVER info is now published upon initialization.
- Fixed SBAS crashing issue (node crashed if device didn't have SBAS
capabilities)
- Modified remaining messages to update to firmware 8
- Added `UbloxNode` abstract class which does all previous node functions which
are the same for all firmware versions. Added subclasses which do functions
specific to a given firmware version (e.g. subscribing to NavPVT messages).
- Added a read lock to AsyncWorker
- Removed hard-coded values from `Gps` and `Node` classes specific to a certain
device and changed them to configurable parameters. Modified example
launch file accordingly.
- Added example parameter yaml files and launch file to load parameters from
this file.
- Moved implementations of Callback functions into `callback.h` (from `gps.h`
and `gps.cpp`)
- Updated formatting of some files per google style guide spec (e.g. 80 chars
per line).
* **0.0.5**:
- Reformat files under `ublox_gps`
* **0.0.4**:
- Added install targets.
* **0.0.3**:
- Added the `enable_glonass`, `enable_beidou` and `enable_ppp` options.
- Added the `ublox_version` option. Consult known issues for important details.
- Added `numSVs` field to the RQT monitor.
* **0.0.2**:
- Changed `meas_rate` to simply `rate`, which is in Hz. `meas_rate` is computed automatically.
* **0.0.1**:
- All topics are now published on a private node handle.
- Velocities are published as stamped twist messages with covariance. Angular components are unused.
- `hAcc`, `vAcc` and `sAcc` are used to generate diagonal covariances.
- Velocities use the correct convention: X-Y-Z = East-North-Up.
- 2D **or** 3D fix correspond to `STATUS_FIX` (previously only 3D).
- `fix` and `fix_velocity` are time-stamped synchronously, using the `iTOW` to check arrival times.
- Added options for changing the CFG-NAV5 settings (see above).
- Added support for `diagnostic_updater`.
- _"received ACK"_ messages are elevated to debug level 2.
- Corrected issue where baudrate was not set correctly using rosparam.
- Corrected issue where socket destructors were not called.
* **0.0.0**:
- Forked from https://github.com/tu-darmstadt-ros-pkg/ublox
- Updated to use catkin.
# Adding new features
## Adding new messages
1. Create the .msg file and add it to `ublox_msgs/msg`. Make sure the file includes the constants `CLASS_ID` and `MESSAGE_ID`.
2. Modify `ublox_msgs/include/ublox_msgs/ublox_msgs.h`.
a. Include the message header.
b. Make sure the message's class constant is declared in the `ublox_msgs::Class` namespace.
c. Declare the message's ID constant in the `ublox_messages::Message::<CLASS_NAME>` namespace.
3. Declare the message in `ublox_msgs/src/ublox_msgs.cpp`.
4. If the message has a repeated or optional block of varying size, create an additional message for the repeating block and include it in the message.
a. Include the block message in the `ublox_msgs/include/ublox_msgs/ublox_msgs.h` file.
b. Modify `ublox_msgs/include/ublox/serialization/ublox_msgs.h` and add a custom `Serializer`. If the message doesn't include the number of repeating/optional blocks as a parameter, you can infer it from the count/size of the message, which is the length of the payload.
5. Modify `ublox_gps/src/node.cpp` (and the header file if necessary) to either subscribe to the message or send the configuration message. Be sure to modify the appropriate subscribe function. For messages which apply to all firmware/hardware, modify `UbloxNode::subscribe()`. Otherwise modify the appropriate firmware or hardware's subscribe function, e.g. `UbloxFirmware8::subscribe()`, `HpgRovProduct::subscribe()`. If the message is a configuration message, consider modifying `ublox_gps/src/gps.cpp` (and the header file) to add a configuration function.
### One message protocol for multiple IDs (e.g. INF message)
If a given message protocol applies to multiple message IDs (e.g. the `Inf` message), do not include the message ID in the message itself.
When declaring the message, for the first declaration, use `DECLARE_UBLOX_MESSAGE` macro. For the following declarations use the `DECLARE_UBLOX_MESSAGE_ID` macro.
## Adding device / firmware specific functionality
The `node.cpp` file in `ublox_gps` contains a main Node class called UbloxNode which acts as the ROS Node and handles the node initialization, publishers, and diagnostics. `UbloxNode` contains a vector `components_` of instances of `ComponentInterface`. The `UbloxNode::initialize()` calls each component's public interface methods. The node contains components for both the firmware version and the product category, which are added after parsing the `MonVER` message. Any class which implements `ComponentInterface` can be added to the `UbloxNode` `components_` vector and its methods will be called by `UbloxNode`. Simply add an implementation of `ComponentInterface` to the ublox_gps `node.h` and `node.cpp` files. Behavior specific to a given firmware or product should not be implemented in the `UbloxNode` class and instead should be implemented in an implementation of `ComponentInterface`.
Currently there are implementations of `ComponentInterface` for firmware versions 6-8 and product categories `HpgRefProduct`, `HpgRovProduct`, `AdrUdrProduct`, `TimProduct`, `FtsProduct`. SPG products do not have their own implementation of `ComponentInterface`, since the Firmware classes implement all of the behavior of SPG devices.
`HpgRefProduct` and `HpgRovProduct` have been tested on the C94-M8P device.
## Adding new parameters
1. Modify the `getRosParams()` method in the appropriate implementation of ComponentInterface (e.g. UbloxNode, UbloxFirmware8, HpgRefProduct, etc.) and get the parameter. Group multiple related parameters into a namespace. Use all lower case names for parameters and namespaces separated with underscores.
* If the type is an unsigned integer (of any size) or vector of unsigned integers, use the `ublox_node::getRosUint` method which will verify the bounds of the parameter.
* If the type is an int8 or int16 or vector of int8's or int16's, use the `ublox_nod::getRosInt` method which will verify the bounds of the parameter. (This method can also be used for int32's but ROS has methods to get int32 parameters as well).
2. If the parameter is used during configuration also modify the `ComponentInterface`'s `configureUblox()` method to send the appropriate configuration message. Do not send configuration messages in `getRosParams()`.
3. Modify this README file and add the parameter name and description in the appropriate section. State whether there is a default value or if the parameter is required.
4. Modify one of the sample `.yaml` configuration files in `ublox_gps/config` to include the parameter or add a new sample `.yaml` for your device.
# Known Issues
## Unimplemented / Untested Devices
`TimProduct` and `FtsProduct` are currently unimplemented skeleton classes. `AdrUdrProduct` is implemented, with the exception of `initializeRosDiagnostics()` and has not been tested on hardware.
`UbloxFirmware7` has not been properly tested on a device with firmware version 7. `UbloxFirmware6` has been tested on a device with firmware version 8, but not with firmware version 6.
## Debugging
For debugging messages set the debug parameter to > 0. The range for debug is 0-4. At level 1 it prints configuration messages and checksum errors, at level 2 it also prints ACK/NACK messages and sent messages. At level 3 it prints the received bytes being decoded by a specific message reader. At level 4 it prints the incoming buffer before it is split by message header.
## Troubleshooting
1. Why can't the ublox_gps node open my device, even though I have correctly specified the path in `/dev`?
* Make sure you are the owner of the device, or a member of `dialout` group.
# Links
Consult the [official protocol spec](https://www.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_(UBX-13003221)_Public.pdf) for details on packets supported by u-blox devices.

View File

@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 2.8.3)
project(ublox)
find_package(catkin REQUIRED)
catkin_metapackage()

View File

@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<package>
<name>ublox</name>
<version>1.1.2</version>
<description>Provides a ublox_gps node for u-blox GPS receivers, messages, and serialization packages for the binary UBX protocol.</description>
<author>Johannes Meyer</author>
<maintainer email="vmlane@alum.mit.edu">Veronica Lane</maintainer>
<license>BSD</license>
<buildtool_depend>catkin</buildtool_depend>
<url>http://wiki.ros.org/ublox</url>
<!-- The export tag contains other, unspecified, tags -->
<export>
<rosdoc external="http://www.u-blox.com/en/product-resources"/>
<!-- You can specify that this package is a metapackage here: -->
<metapackage />
</export>
</package>

View File

@@ -0,0 +1,61 @@
cmake_minimum_required(VERSION 2.8.3)
project(ublox_gps)
find_package(catkin REQUIRED COMPONENTS
roscpp
roscpp_serialization
ublox_msgs
ublox_serialization
diagnostic_updater
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS roscpp ublox_msgs ublox_serialization)
# include boost
find_package(Boost REQUIRED COMPONENTS system regex thread)
link_directories(${Boost_LIBRARY_DIR})
include_directories(${Boost_INCLUDE_DIR})
# include other ublox packages
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${catkin_INCLUDE_DIRS})
# link pthread
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
# build library
add_library(ublox_gps src/gps.cpp)
# fix msg compile order bug
add_dependencies(ublox_gps ${catkin_EXPORTED_TARGETS})
target_link_libraries(ublox_gps
boost_system
boost_regex
boost_thread
)
target_link_libraries(ublox_gps
${catkin_LIBRARIES}
)
# build node
add_executable(ublox_gps_node src/node.cpp src/mkgmtime.c)
set_target_properties(ublox_gps_node PROPERTIES OUTPUT_NAME ublox_gps)
target_link_libraries(ublox_gps_node boost_system boost_regex boost_thread)
target_link_libraries(ublox_gps_node ${catkin_LIBRARIES})
target_link_libraries(ublox_gps_node ublox_gps)
install(TARGETS ublox_gps ublox_gps_node
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
PATTERN ".svn" EXCLUDE
)

View File

@@ -0,0 +1,72 @@
# Configuration Settings for C94-M8P device
debug: 1 # Range 0-4 (0 means no debug statements will print)
save:
mask: 3103 # Save I/O, Message, INF Message, Nav, Receiver
# Manager, Antenna, and Logging Configuration
device: 4 # Save to EEPROM
device: /dev/ttyACM0
frame_id: gps_base
dynamic_model: stationary # Velocity restricted to 0 m/s. Zero dynamics
# assumed.
fix_mode: auto
dr_limit: 0
enable_ppp: false # Not supported by C94-M8P
rate: 4 # Measurement rate in Hz
nav_rate: 4 # in number of measurement cycles
uart1:
baudrate: 19200 # C94-M8P specific
in: 0 # No UART in for base
out: 32 # RTCM 3
# TMODE3 Config
tmode3: 1 # Survey-In Mode
sv_in:
reset: false # True: disables and re-enables survey-in (resets)
# False: Disables survey-in only if TMODE3 is
# disabled
min_dur: 300 # Survey-In Minimum Duration [s]
acc_lim: 3.0 # Survey-In Accuracy Limit [m]
# RTCM out config
rtcm:
ids: [5, 87, 77, 230] # RTCM Messages to configure for Base station
# Enabled: GPS MSM7, GLONASS MSM7,
# GLONASS CP bias, Stationary RTK ref
# 0xF5 0x05 Stationary RTK reference station
# ARP
# 0xF5 0x4A GPS MSM4
# 0xF5 0x4D GPS MSM7
# 0xF5 0x54 GLONASS MSM4
# 0xF5 0x57 GLONASS MSM7
# 0xF5 0x7C BeiDou MSM4
# 0xF5 0x7F BeiDou MSM7
# 0xF5 0xE6 GLONASS code-phase biases
# 0xF5 0xFE Reference station PVT
#(u-blox proprietary RTCM Message)
rates: [1, 1, 1, 10] # in number of navigation solutions, must match
# nav_rate, except for 0xE6
dat:
set: false
# GNSS Config
gnss:
glonass: true # Supported by C94-M8P
beidou: false # Supported by C94-M8P
qzss: false # Supported by C94-M8P
inf:
all: true # Whether to display all INF messages in console
# Enable u-blox message publishers
publish:
all: true
aid:
hui: false
nav:
posecef: false

View File

@@ -0,0 +1,46 @@
# Configuration Settings for C94-M8P device
debug: 1 # Range 0-4 (0 means no debug statements will print)
save:
mask: 3103 # Save I/O, Message, INF Message, Nav, Receiver
# Manager, Antenna, and Logging Configuration
device: 4 # Save to EEPROM
device: /dev/ttyACM1
frame_id: gps
rate: 4 # in Hz
nav_rate: 4 # [# of measurement cycles], recommended 1 Hz, may
# be either 5 Hz (Dual constellation) or
# 8 Hz (GPS only)
dynamic_model: airborne2 # Airborne < 2G, 2D fix not supported (3D only),
# Max Alt: 50km
# Max Horizontal Velocity: 250 m/s,
# Max Vertical Velocity: 100 m/s
fix_mode: auto
enable_ppp: false # Not supported by C94-M8P
dr_limit: 0
uart1:
baudrate: 19200 # C94-M8P specific
in: 32 # RTCM 3
out: 0 # No UART out for rover
gnss:
glonass: true # Supported by C94-M8P
beidou: false # Supported by C94-M8P
qzss: false # Supported by C94-M8P
dgnss_mode: 3 # Fixed mode
inf:
all: true # Whether to display all INF messages in console
# Enable u-blox message publishers
publish:
all: true
aid:
hui: false
nav:
posecef: false

View File

@@ -0,0 +1,46 @@
# Configuration Settings for C94-M8P device
debug: 1 # Range 0-4 (0 means no debug statements will print)
save:
mask: 3103 # Save I/O, Message, INF Message, Nav, Receiver
# Manager, Antenna, and Logging Configuration
device: 4 # Save to EEPROM
device: /dev/ttyUSB3
frame_id: gps
rate: 4 # in Hz
nav_rate: 4 # [# of measurement cycles], recommended 1 Hz, may
# be either 5 Hz (Dual constellation) or
# 8 Hz (GPS only)
dynamic_model: airborne2 # Airborne < 2G, 2D fix not supported (3D only),
# Max Alt: 50km
# Max Horizontal Velocity: 250 m/s,
# Max Vertical Velocity: 100 m/s
fix_mode: auto
enable_ppp: false # Not supported by C94-M8P
dr_limit: 0
uart1:
baudrate: 9600 # C94-M8P specific
in: 32 # RTCM 3
out: 0 # No UART out for rover
gnss:
glonass: true # Supported by C94-M8P
beidou: false # Supported by C94-M8P
qzss: false # Supported by C94-M8P
dgnss_mode: 3 # Fixed mode
inf:
all: true # Whether to display all INF messages in console
# Enable u-blox message publishers
publish:
all: true
aid:
hui: false
nav:
posecef: false

View File

@@ -0,0 +1,31 @@
# Sample NMEA parameter configuration
device: /dev/rover/ttyGPS
uart1:
baudrate: 9600 # C94-M8P specific
nmea:
set: true
version: 65
num_sv: 8
sv_numbering: 1
compat: true
consider: true
limit82: true
high_prec: false
filter:
pos: true
msk_pos: true
time: true
date: true
gps_only: true
track: true
gnssToFilter:
gps: false
sbas: true
qzss: true
glonass: false
beidou: true
main_talker_id: 1
gsv_talker_id: 1
bds_talker_id: [0,0]

View File

@@ -0,0 +1,258 @@
//==============================================================================
// Copyright (c) 2012, Johannes Meyer, TU Darmstadt
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Flight Systems and Automatic Control group,
// TU Darmstadt, nor the names of its contributors may be used to
// endorse or promote products derived from this software without
// specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==============================================================================
#ifndef UBLOX_GPS_ASYNC_WORKER_H
#define UBLOX_GPS_ASYNC_WORKER_H
#include <ublox_gps/gps.h>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/format.hpp>
#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include "worker.h"
namespace ublox_gps {
int debug; //!< Used to determine which debug messages to display
/**
* @brief Handles Asynchronous I/O reading and writing.
*/
template <typename StreamT>
class AsyncWorker : public Worker {
public:
typedef boost::mutex Mutex;
typedef boost::mutex::scoped_lock ScopedLock;
/**
* @brief Construct an Asynchronous I/O worker.
* @param stream the stream for th I/O service
* @param io_service the I/O service
* @param buffer_size the size of the input and output buffers
*/
AsyncWorker(boost::shared_ptr<StreamT> stream,
boost::shared_ptr<boost::asio::io_service> io_service,
std::size_t buffer_size = 8192);
virtual ~AsyncWorker();
/**
* @brief Set the callback function which handles input messages.
* @param callback the read callback which handles received messages
*/
void setCallback(const Callback& callback) { read_callback_ = callback; }
/**
* @brief Send the data bytes via the I/O stream.
* @param data the buffer of data bytes to send
* @param size the size of the buffer
*/
bool send(const unsigned char* data, const unsigned int size);
/**
* @brief Wait for incoming messages.
* @param timeout the maximum time to wait
*/
void wait(const boost::posix_time::time_duration& timeout);
bool isOpen() const { return stream_->is_open(); }
protected:
/**
* @brief Read the input stream.
*/
void doRead();
/**
* @brief Process messages read from the input stream.
* @param error_code an error code for read failures
* @param the number of bytes received
*/
void readEnd(const boost::system::error_code&, std::size_t);
/**
* @brief Send all the data in the output buffer.
*/
void doWrite();
/**
* @brief Close the I/O stream.
*/
void doClose();
boost::shared_ptr<StreamT> stream_; //!< The I/O stream
boost::shared_ptr<boost::asio::io_service> io_service_; //!< The I/O service
Mutex read_mutex_; //!< Lock for the input buffer
boost::condition read_condition_;
std::vector<unsigned char> in_; //!< The input buffer
std::size_t in_buffer_size_; //!< number of bytes currently in the input
//!< buffer
Mutex write_mutex_; //!< Lock for the output buffer
boost::condition write_condition_;
std::vector<unsigned char> out_; //!< The output buffer
boost::shared_ptr<boost::thread> background_thread_; //!< thread for the I/O
//!< service
Callback read_callback_; //!< Callback function to handle received messages
bool stopping_; //!< Whether or not the I/O service is closed
};
template <typename StreamT>
AsyncWorker<StreamT>::AsyncWorker(boost::shared_ptr<StreamT> stream,
boost::shared_ptr<boost::asio::io_service> io_service,
std::size_t buffer_size)
: stopping_(false) {
stream_ = stream;
io_service_ = io_service;
in_.resize(buffer_size);
in_buffer_size_ = 0;
out_.reserve(buffer_size);
io_service_->post(boost::bind(&AsyncWorker<StreamT>::doRead, this));
background_thread_.reset(new boost::thread(
boost::bind(&boost::asio::io_service::run, io_service_)));
}
template <typename StreamT>
AsyncWorker<StreamT>::~AsyncWorker() {
io_service_->post(boost::bind(&AsyncWorker<StreamT>::doClose, this));
background_thread_->join();
//io_service_->reset();
}
template <typename StreamT>
bool AsyncWorker<StreamT>::send(const unsigned char* data,
const unsigned int size) {
ScopedLock lock(write_mutex_);
if(size == 0) {
ROS_ERROR("Ublox AsyncWorker::send: Size of message to send is 0");
return true;
}
if (out_.capacity() - out_.size() < size) {
ROS_ERROR("Ublox AsyncWorker::send: Output buffer too full to send message");
return false;
}
out_.insert(out_.end(), data, data + size);
io_service_->post(boost::bind(&AsyncWorker<StreamT>::doWrite, this));
return true;
}
template <typename StreamT>
void AsyncWorker<StreamT>::doWrite() {
ScopedLock lock(write_mutex_);
// Do nothing if out buffer is empty
if (out_.size() == 0) {
return;
}
// Write all the data in the out buffer
boost::asio::write(*stream_, boost::asio::buffer(out_.data(), out_.size()));
if (debug >= 2) {
// Print the data that was sent
std::ostringstream oss;
for (std::vector<unsigned char>::iterator it = out_.begin();
it != out_.end(); ++it)
oss << boost::format("%02x") % static_cast<unsigned int>(*it) << " ";
ROS_DEBUG("U-Blox sent %li bytes: \n%s", out_.size(), oss.str().c_str());
}
// Clear the buffer & unlock
out_.clear();
write_condition_.notify_all();
}
template <typename StreamT>
void AsyncWorker<StreamT>::doRead() {
ScopedLock lock(read_mutex_);
stream_->async_read_some(
boost::asio::buffer(in_.data() + in_buffer_size_,
in_.size() - in_buffer_size_),
boost::bind(&AsyncWorker<StreamT>::readEnd, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
template <typename StreamT>
void AsyncWorker<StreamT>::readEnd(const boost::system::error_code& error,
std::size_t bytes_transfered) {
ScopedLock lock(read_mutex_);
if (error) {
ROS_ERROR("U-Blox ASIO input buffer read error: %s, %li",
error.message().c_str(),
bytes_transfered);
} else if (bytes_transfered > 0) {
in_buffer_size_ += bytes_transfered;
if (debug >= 4) {
std::ostringstream oss;
for (std::vector<unsigned char>::iterator it =
in_.begin() + in_buffer_size_ - bytes_transfered;
it != in_.begin() + in_buffer_size_; ++it)
oss << boost::format("%02x") % static_cast<unsigned int>(*it) << " ";
ROS_DEBUG("U-Blox received %li bytes \n%s", bytes_transfered,
oss.str().c_str());
}
if (read_callback_)
read_callback_(in_.data(), in_buffer_size_);
read_condition_.notify_all();
}
if (!stopping_)
io_service_->post(boost::bind(&AsyncWorker<StreamT>::doRead, this));
}
template <typename StreamT>
void AsyncWorker<StreamT>::doClose() {
ScopedLock lock(read_mutex_);
stopping_ = true;
boost::system::error_code error;
stream_->close(error);
if(error)
ROS_ERROR_STREAM(
"Error while closing the AsyncWorker stream: " << error.message());
}
template <typename StreamT>
void AsyncWorker<StreamT>::wait(
const boost::posix_time::time_duration& timeout) {
ScopedLock lock(read_mutex_);
read_condition_.timed_wait(lock, timeout);
}
} // namespace ublox_gps
#endif // UBLOX_GPS_ASYNC_WORKER_H

View File

@@ -0,0 +1,238 @@
//==============================================================================
// Copyright (c) 2012, Johannes Meyer, TU Darmstadt
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Flight Systems and Automatic Control group,
// TU Darmstadt, nor the names of its contributors may be used to
// endorse or promote products derived from this software without
// specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==============================================================================
#ifndef UBLOX_GPS_CALLBACK_H
#define UBLOX_GPS_CALLBACK_H
#include <ros/console.h>
#include <ublox/serialization/ublox_msgs.h>
#include <boost/format.hpp>
#include <boost/function.hpp>
#include <boost/thread.hpp>
namespace ublox_gps {
/**
* @brief A callback handler for a u-blox message.
*/
class CallbackHandler {
public:
/**
* @brief Decode the u-blox message.
*/
virtual void handle(ublox::Reader& reader) = 0;
/**
* @brief Wait for on the condition.
*/
bool wait(const boost::posix_time::time_duration& timeout) {
boost::mutex::scoped_lock lock(mutex_);
return condition_.timed_wait(lock, timeout);
}
protected:
boost::mutex mutex_; //!< Lock for the handler
boost::condition_variable condition_; //!< Condition for the handler lock
};
/**
* @brief A callback handler for a u-blox message.
* @typedef T the message type
*/
template <typename T>
class CallbackHandler_ : public CallbackHandler {
public:
typedef boost::function<void(const T&)> Callback; //!< A callback function
/**
* @brief Initialize the Callback Handler with a callback function
* @param func a callback function for the message, defaults to none
*/
CallbackHandler_(const Callback& func = Callback()) : func_(func) {}
/**
* @brief Get the last received message.
*/
virtual const T& get() { return message_; }
/**
* @brief Decode the U-Blox message & call the callback function if it exists.
* @param reader a reader to decode the message buffer
*/
void handle(ublox::Reader& reader) {
boost::mutex::scoped_lock(mutex_);
try {
if (!reader.read<T>(message_)) {
ROS_DEBUG_COND(debug >= 2,
"U-Blox Decoder error for 0x%02x / 0x%02x (%d bytes)",
static_cast<unsigned int>(reader.classId()),
static_cast<unsigned int>(reader.messageId()),
reader.length());
condition_.notify_all();
return;
}
} catch (std::runtime_error& e) {
ROS_DEBUG_COND(debug >= 2,
"U-Blox Decoder error for 0x%02x / 0x%02x (%d bytes)",
static_cast<unsigned int>(reader.classId()),
static_cast<unsigned int>(reader.messageId()),
reader.length());
condition_.notify_all();
return;
}
if (func_) func_(message_);
condition_.notify_all();
}
private:
Callback func_; //!< the callback function to handle the message
T message_; //!< The last received message
};
/**
* @brief Callback handlers for incoming u-blox messages.
*/
class CallbackHandlers {
public:
/**
* @brief Add a callback handler for the given message type.
* @param callback the callback handler for the message
* @typedef.a ublox_msgs message with CLASS_ID and MESSAGE_ID constants
*/
template <typename T>
void insert(typename CallbackHandler_<T>::Callback callback) {
boost::mutex::scoped_lock lock(callback_mutex_);
CallbackHandler_<T>* handler = new CallbackHandler_<T>(callback);
callbacks_.insert(
std::make_pair(std::make_pair(T::CLASS_ID, T::MESSAGE_ID),
boost::shared_ptr<CallbackHandler>(handler)));
}
/**
* @brief Add a callback handler for the given message type and ID. This is
* used for messages in which have the same structure (and therefore msg file)
* and same class ID but different message IDs. (e.g. INF, ACK)
* @param callback the callback handler for the message
* @param message_id the ID of the message
* @typedef.a ublox_msgs message with a CLASS_ID constant
*/
template <typename T>
void insert(
typename CallbackHandler_<T>::Callback callback,
unsigned int message_id) {
boost::mutex::scoped_lock lock(callback_mutex_);
CallbackHandler_<T>* handler = new CallbackHandler_<T>(callback);
callbacks_.insert(
std::make_pair(std::make_pair(T::CLASS_ID, message_id),
boost::shared_ptr<CallbackHandler>(handler)));
}
/**
* @brief Calls the callback handler for the message in the reader.
* @param reader a reader containing a u-blox message
*/
void handle(ublox::Reader& reader) {
// Find the callback handlers for the message & decode it
boost::mutex::scoped_lock lock(callback_mutex_);
Callbacks::key_type key =
std::make_pair(reader.classId(), reader.messageId());
for (Callbacks::iterator callback = callbacks_.lower_bound(key);
callback != callbacks_.upper_bound(key); ++callback)
callback->second->handle(reader);
}
/**
* @brief Read a u-blox message of the given type.
* @param message the received u-blox message
* @param timeout the amount of time to wait for the desired message
*/
template <typename T>
bool read(T& message, const boost::posix_time::time_duration& timeout) {
bool result = false;
// Create a callback handler for this message
callback_mutex_.lock();
CallbackHandler_<T>* handler = new CallbackHandler_<T>();
Callbacks::iterator callback = callbacks_.insert(
(std::make_pair(std::make_pair(T::CLASS_ID, T::MESSAGE_ID),
boost::shared_ptr<CallbackHandler>(handler))));
callback_mutex_.unlock();
// Wait for the message
if (handler->wait(timeout)) {
message = handler->get();
result = true;
}
// Remove the callback handler
callback_mutex_.lock();
callbacks_.erase(callback);
callback_mutex_.unlock();
return result;
}
/**
* @brief Processes u-blox messages in the given buffer & clears the read
* messages from the buffer.
* @param data the buffer of u-blox messages to process
* @param size the size of the buffer
*/
void readCallback(unsigned char* data, std::size_t& size) {
ublox::Reader reader(data, size);
// Read all U-Blox messages in buffer
while (reader.search() != reader.end() && reader.found()) {
if (debug >= 3) {
// Print the received bytes
std::ostringstream oss;
for (ublox::Reader::iterator it = reader.pos();
it != reader.pos() + reader.length() + 8; ++it)
oss << boost::format("%02x") % static_cast<unsigned int>(*it) << " ";
ROS_DEBUG("U-blox: reading %d bytes\n%s", reader.length() + 8,
oss.str().c_str());
}
handle(reader);
}
// delete read bytes from ASIO input buffer
std::copy(reader.pos(), reader.end(), data);
size -= reader.pos() - data;
}
private:
typedef std::multimap<std::pair<uint8_t, uint8_t>,
boost::shared_ptr<CallbackHandler> > Callbacks;
// Call back handlers for u-blox messages
Callbacks callbacks_;
boost::mutex callback_mutex_;
};
} // namespace ublox_gps
#endif // UBLOX_GPS_CALLBACK_H

View File

@@ -0,0 +1,513 @@
//==============================================================================
// Copyright (c) 2012, Johannes Meyer, TU Darmstadt
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Flight Systems and Automatic Control group,
// TU Darmstadt, nor the names of its contributors may be used to
// endorse or promote products derived from this software without
// specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==============================================================================
#ifndef UBLOX_GPS_H
#define UBLOX_GPS_H
// STL
#include <map>
#include <vector>
#include <locale>
#include <stdexcept>
// Boost
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/atomic.hpp>
// ROS
#include <ros/console.h>
// Other u-blox packages
#include <ublox/serialization/ublox_msgs.h>
// u-blox gps
#include <ublox_gps/async_worker.h>
#include <ublox_gps/callback.h>
/**
* @namespace ublox_gps
* This namespace is for I/O communication with the u-blox device, including
* read callbacks.
*/
namespace ublox_gps {
//! Possible baudrates for u-blox devices
constexpr static unsigned int kBaudrates[] = { 4800,
9600,
19200,
38400,
57600,
115200,
230400,
460800 };
/**
* @brief Handles communication with and configuration of the u-blox device
*/
class Gps {
public:
//! Sleep time [ms] after setting the baudrate
constexpr static int kSetBaudrateSleepMs = 500;
//! Default timeout for ACK messages in seconds
constexpr static double kDefaultAckTimeout = 1.0;
//! Size of write buffer for output messages
constexpr static int kWriterSize = 1024;
Gps();
virtual ~Gps();
/**
* @brief If called, when the node shuts down, it will send a command to
* save the flash memory.
*/
void setSaveOnShutdown(bool save_on_shutdown) {
save_on_shutdown_ = save_on_shutdown;
}
/**
* @brief Initialize TCP I/O.
* @param host the TCP host
* @param port the TCP port
*/
void initializeTcp(std::string host, std::string port);
/**
* @brief Initialize the Serial I/O port.
* @param port the device port address
* @param baudrate the desired baud rate of the port
* @param uart_in the UART In protocol, see CfgPRT for options
* @param uart_out the UART Out protocol, see CfgPRT for options
*/
void initializeSerial(std::string port, unsigned int baudrate,
uint16_t uart_in, uint16_t uart_out);
/**
* @brief Reset the Serial I/O port after u-blox reset.
* @param port the device port address
* @param baudrate the desired baud rate of the port
* @param uart_in the UART In protocol, see CfgPRT for options
* @param uart_out the UART Out protocol, see CfgPRT for options
*/
void resetSerial(std::string port);
/**
* @brief Closes the I/O port, and initiates save on shutdown procedure
* if enabled.
*/
void close();
/**
* @brief Reset I/O communications.
* @param wait Time to wait before restarting communications
*/
void reset(const boost::posix_time::time_duration& wait);
/**
* @brief Send a reset message to the u-blox device.
* @param nav_bbr_mask The BBR sections to clear, see CfgRST message
* @param reset_mode The reset type, see CfgRST message
* @return true if the message was successfully sent, false otherwise
*/
bool configReset(uint16_t nav_bbr_mask, uint16_t reset_mode);
/**
* @brief Configure the GNSS, cold reset the device, and reset the I/O.
* @param gnss the desired GNSS configuration
* @param wait the time to wait after resetting I/O before restarting
* @return true if the GNSS was configured, the device was reset, and the
* I/O reset successfully
*/
bool configGnss(ublox_msgs::CfgGNSS gnss,
const boost::posix_time::time_duration& wait);
/**
* @brief Send a message to the receiver to delete the BBR data stored in
* flash.
* @return true if sent message and received ACK, false otherwise
*/
bool clearBbr();
/**
* @brief Configure the UART1 Port.
* @param baudrate the baudrate of the port
* @param in_proto_mask the in protocol mask, see CfgPRT message
* @param out_proto_mask the out protocol mask, see CfgPRT message
* @return true on ACK, false on other conditions.
*/
bool configUart1(unsigned int baudrate, uint16_t in_proto_mask,
uint16_t out_proto_mask);
/**
* @brief Disable the UART Port. Sets in/out protocol masks to 0. Does not
* modify other values.
* @param prev_cfg an empty message which will be filled with the previous
* configuration parameters
* @return true on ACK, false on other conditions.
*/
bool disableUart1(ublox_msgs::CfgPRT& prev_cfg);
/**
* @brief Configure the USB Port.
* @param tx_ready the TX ready pin configuration, see CfgPRT message
* @param in_proto_mask the in protocol mask, see CfgPRT message
* @param out_proto_mask the out protocol mask, see CfgPRT message
* @return true on ACK, false on other conditions.
*/
bool configUsb(uint16_t tx_ready, uint16_t in_proto_mask,
uint16_t out_proto_mask);
/**
* @brief Configure the device navigation and measurement rate settings.
* @param meas_rate Period in milliseconds between subsequent measurements.
* @param nav_rate the rate at which navigation solutions are generated by the
* receiver in number measurement cycles
* @return true on ACK, false on other conditions.
*/
bool configRate(uint16_t meas_rate, uint16_t nav_rate);
/**
* @brief Configure the RTCM messages with the given IDs to the set rate.
* @param ids the RTCM message ids, valid range: [0, 255]
* @param rates the send rates for each RTCM message ID, valid range: [0, 255]
* @return true on ACK, false on other conditions.
*/
bool configRtcm(std::vector<uint8_t> ids, std::vector<uint8_t> rates);
/**
* @brief Configure the SBAS settings.
* @param enable If true, enable SBAS. Deprecated in firmware 8, use CfgGNSS
* instead.
* @param usage SBAS usage, see CfgSBAS for options
* @param max_sbas Maximum Number of SBAS prioritized tracking channels
* @return true on ACK, false on other conditions.
*/
bool configSbas(bool enable, uint8_t usage, uint8_t max_sbas);
/**
* @brief Set the TMODE3 settings to fixed.
*
* @details Sets the at the given antenna reference point (ARP) position in
* either Latitude Longitude Altitude (LLA) or ECEF coordinates.
* @param arp_position a vector of size 3 representing the ARP position in
* ECEF coordinates [m] or LLA coordinates [deg]
* @param arp_position_hp a vector of size 3 a vector of size 3 representing
* the ARP position in ECEF coordinates [0.1 mm] or LLA coordinates
* [deg * 1e-9]
* @param lla_flag true if position is given in LAT/LON/ALT, false if ECEF
* @param fixed_pos_acc Fixed position 3D accuracy [m]
* @return true on ACK, false if settings are incorrect or on other conditions
*/
bool configTmode3Fixed(bool lla_flag,
std::vector<float> arp_position,
std::vector<int8_t> arp_position_hp,
float fixed_pos_acc);
/**
* @brief Set the TMODE3 settings to survey-in.
* @param svin_min_dur Survey-in minimum duration [s]
* @param svin_acc_limit Survey-in position accuracy limit [m]
* @return true on ACK, false on other conditions.
*/
bool configTmode3SurveyIn(unsigned int svin_min_dur, float svin_acc_limit);
/**
* @brief Set the TMODE3 settings to disabled. Should only be called for
* High Precision GNSS devices, otherwise the device will return a NACK.
* @return true on ACK, false on other conditions.
*/
bool disableTmode3();
/**
* @brief Set the rate at which the U-Blox device sends the given message
* @param class_id the class identifier of the message
* @param message_id the message identifier
* @param rate the updated rate in Hz
* @return true on ACK, false on other conditions.
*/
bool setRate(uint8_t class_id, uint8_t message_id, uint8_t rate);
/**
* @brief Set the device dynamic model.
* @param model Dynamic model to use. Consult ublox protocol spec for details.
* @return true on ACK, false on other conditions.
*/
bool setDynamicModel(uint8_t model);
/**
* @brief Set the device fix mode.
* @param mode 2D only, 3D only or auto.
* @return true on ACK, false on other conditions.
*/
bool setFixMode(uint8_t mode);
/**
* @brief Set the dead reckoning time limit
* @param limit Time limit in seconds.
* @return true on ACK, false on other conditions.
*/
bool setDeadReckonLimit(uint8_t limit);
/**
* @brief Enable or disable PPP (precise-point-positioning).
* @param enable If true, enable PPP.
* @return true on ACK, false on other conditions.
*
* @note This is part of the expert settings. It is recommended you check
* the ublox manual first.
*/
bool setPpp(bool enable);
/**
* @brief Set the DGNSS mode (see CfgDGNSS message for details).
* @param mode the DGNSS mode (see CfgDGNSS message for options)
* @return true on ACK, false on other conditions
*/
bool setDgnss(uint8_t mode);
/**
* @brief Enable or disable ADR (automotive dead reckoning).
* @param enable If true, enable ADR.
* @return true on ACK, false on other conditions.
*/
bool setUseAdr(bool enable);
/**
* @brief Configure the U-Blox send rate of the message & subscribe to the
* given message
* @param the callback handler for the message
* @param rate the rate in Hz of the message
*/
template <typename T>
void subscribe(typename CallbackHandler_<T>::Callback callback,
unsigned int rate);
/**
* @brief Subscribe to the given Ublox message.
* @param the callback handler for the message
*/
template <typename T>
void subscribe(typename CallbackHandler_<T>::Callback callback);
/**
* @brief Subscribe to the message with the given ID. This is used for
* messages which have the same format but different message IDs,
* e.g. INF messages.
* @param the callback handler for the message
* @param message_id the U-Blox message ID
*/
template <typename T>
void subscribeId(typename CallbackHandler_<T>::Callback callback,
unsigned int message_id);
/**
* Read a u-blox message of the given type.
* @param message the received u-blox message
* @param timeout the amount of time to wait for the desired message
*/
template <typename T>
bool read(T& message,
const boost::posix_time::time_duration& timeout = default_timeout_);
bool isInitialized() const { return worker_ != 0; }
bool isConfigured() const { return isInitialized() && configured_; }
bool isOpen() const { return worker_->isOpen(); }
/**
* Poll a u-blox message of the given type.
* @param message the received u-blox message output
* @param payload the poll message payload sent to the device
* defaults to empty
* @param timeout the amount of time to wait for the desired message
*/
template <typename ConfigT>
bool poll(ConfigT& message,
const std::vector<uint8_t>& payload = std::vector<uint8_t>(),
const boost::posix_time::time_duration& timeout = default_timeout_);
/**
* Poll a u-blox message.
* @param class_id the u-blox message class id
* @param message_id the u-blox message id
* @param payload the poll message payload sent to the device,
* defaults to empty
* @param timeout the amount of time to wait for the desired message
*/
bool poll(uint8_t class_id, uint8_t message_id,
const std::vector<uint8_t>& payload = std::vector<uint8_t>());
/**
* @brief Send the given configuration message.
* @param message the configuration message
* @param wait if true, wait for an ACK
* @return true if message sent successfully and either ACK was received or
* wait was set to false
*/
template <typename ConfigT>
bool configure(const ConfigT& message, bool wait = true);
/**
* @brief Wait for an acknowledge message until the timeout
* @param timeout maximum time to wait in seconds
* @param class_id the expected class ID of the ACK
* @param msg_id the expected message ID of the ACK
* @return true if expected ACK received, false otherwise
*/
bool waitForAcknowledge(const boost::posix_time::time_duration& timeout,
uint8_t class_id, uint8_t msg_id);
private:
//! Types for ACK/NACK messages, WAIT is used when waiting for an ACK
enum AckType {
NACK, //! Not acknowledged
ACK, //! Acknowledge
WAIT //! Waiting for ACK
};
//! Stores ACK/NACK messages
struct Ack {
AckType type; //!< The ACK type
uint8_t class_id; //!< The class ID of the ACK
uint8_t msg_id; //!< The message ID of the ACK
};
/**
* @brief Set the I/O worker
* @param an I/O handler
*/
void setWorker(const boost::shared_ptr<Worker>& worker);
/**
* @brief Subscribe to ACK/NACK messages and UPD-SOS-ACK messages.
*/
void subscribeAcks();
/**
* @brief Callback handler for UBX-ACK message.
* @param m the message to process
*/
void processAck(const ublox_msgs::Ack &m);
/**
* @brief Callback handler for UBX-NACK message.
* @param m the message to process
*/
void processNack(const ublox_msgs::Ack &m);
/**
* @brief Callback handler for UBX-UPD-SOS-ACK message.
* @param m the message to process
*/
void processUpdSosAck(const ublox_msgs::UpdSOS_Ack &m);
/**
* @brief Execute save on shutdown procedure.
*
* @details Execute the procedure recommended in the u-blox 8 documentation.
* Send a stop message to the receiver and instruct it to dump its
* current state to the attached flash memory (where fitted) as part of the
* shutdown procedure. The flash data is automatically retrieved when the
* receiver is restarted.
* @return true if the receiver reset & saved the BBR contents to flash
*/
bool saveOnShutdown();
//! Processes I/O stream data
boost::shared_ptr<Worker> worker_;
//! Whether or not the I/O port has been configured
bool configured_;
//! Whether or not to save Flash BBR on shutdown
bool save_on_shutdown_;
//! The default timeout for ACK messages
static const boost::posix_time::time_duration default_timeout_;
//! Stores last received ACK accessed by multiple threads
mutable boost::atomic<Ack> ack_;
//! Callback handlers for u-blox messages
CallbackHandlers callbacks_;
std::string host_, port_;
};
template <typename T>
void Gps::subscribe(
typename CallbackHandler_<T>::Callback callback, unsigned int rate) {
if (!setRate(T::CLASS_ID, T::MESSAGE_ID, rate)) return;
subscribe<T>(callback);
}
template <typename T>
void Gps::subscribe(typename CallbackHandler_<T>::Callback callback) {
callbacks_.insert<T>(callback);
}
template <typename T>
void Gps::subscribeId(typename CallbackHandler_<T>::Callback callback,
unsigned int message_id) {
callbacks_.insert<T>(callback, message_id);
}
template <typename ConfigT>
bool Gps::poll(ConfigT& message,
const std::vector<uint8_t>& payload,
const boost::posix_time::time_duration& timeout) {
if (!poll(ConfigT::CLASS_ID, ConfigT::MESSAGE_ID, payload)) return false;
return read(message, timeout);
}
template <typename T>
bool Gps::read(T& message, const boost::posix_time::time_duration& timeout) {
if (!worker_) return false;
return callbacks_.read(message, timeout);
}
template <typename ConfigT>
bool Gps::configure(const ConfigT& message, bool wait) {
if (!worker_) return false;
// Reset ack
Ack ack;
ack.type = WAIT;
ack_.store(ack, boost::memory_order_seq_cst);
// Encode the message
std::vector<unsigned char> out(kWriterSize);
ublox::Writer writer(out.data(), out.size());
if (!writer.write(message)) {
ROS_ERROR("Failed to encode config message 0x%02x / 0x%02x",
message.CLASS_ID, message.MESSAGE_ID);
return false;
}
// Send the message to the device
worker_->send(out.data(), writer.end() - out.data());
if (!wait) return true;
// Wait for an acknowledgment and return whether or not it was received
return waitForAcknowledge(default_timeout_,
message.CLASS_ID,
message.MESSAGE_ID);
}
} // namespace ublox_gps
#endif // UBLOX_GPS_H

View File

@@ -0,0 +1,55 @@
/* mkgmtime.h -- make a time_t from a gmtime struct tm
$Id: mkgmtime.h,v 1.5 2003/02/13 20:15:41 rjs3 Exp $
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef INCLUDED_MKGMTIME_H
#define INCLUDED_MKGMTIME_H
#include <time.h>
/**
* @brief Get the UTC time in seconds and nano-seconds from a time struct in
* GM time.
*/
extern time_t mkgmtime(struct tm * const tmp);
#endif /* INCLUDED_MKGMTIME_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
#ifndef UBLOX_GPS_UTILS_H
#define UBLOX_GPS_UTILS_H
#include <math.h>
#include <time.h>
#include "ublox_msgs/NavPVT.h"
extern "C" {
#include "ublox_gps/mkgmtime.h"
}
/**
* @brief Convert date/time to UTC time in seconds.
*/
template<typename NavPVT>
long toUtcSeconds(const NavPVT& msg) {
// Create TM struct for mkgmtime
struct tm time = {0};
time.tm_year = msg.year - 1900;
time.tm_mon = msg.month - 1;
time.tm_mday = msg.day;
time.tm_hour = msg.hour;
time.tm_min = msg.min;
time.tm_sec = msg.sec;
// C++ STL doesn't have a mkgmtime (though other libraries do)
// STL mktime converts date/time to seconds in local time
// A modified version of code external library is used for mkgmtime
return mkgmtime(&time);
}
#endif

View File

@@ -0,0 +1,72 @@
//==============================================================================
// Copyright (c) 2012, Johannes Meyer, TU Darmstadt
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Flight Systems and Automatic Control group,
// TU Darmstadt, nor the names of its contributors may be used to
// endorse or promote products derived from this software without
// specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==============================================================================
#ifndef UBLOX_GPS_WORKER_H
#define UBLOX_GPS_WORKER_H
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/function.hpp>
namespace ublox_gps {
/**
* @brief Handles I/O reading and writing.
*/
class Worker {
public:
typedef boost::function<void(unsigned char*, std::size_t&)> Callback;
virtual ~Worker() {}
/**
* @brief Set the callback function for received messages.
* @param callback the callback function which process messages in the buffer
*/
virtual void setCallback(const Callback& callback) = 0;
/**
* @brief Send the data in the buffer.
* @param data the bytes to send
* @param size the size of the buffer
*/
virtual bool send(const unsigned char* data, const unsigned int size) = 0;
/**
* @brief Wait for an incoming message.
* @param timeout the maximum time to wait.
*/
virtual void wait(const boost::posix_time::time_duration& timeout) = 0;
/**
* @brief Whether or not the I/O stream is open.
*/
virtual bool isOpen() const = 0;
};
} // namespace ublox_gps
#endif // UBLOX_GPS_WORKER_H

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<node name="rover_gps" pkg="ublox_gps" type="ublox_gps" output="screen" clear_params="false" respawn="true" respawn_delay="10">
<rosparam command="load" file="$(find ublox_gps)/config/nmea.yaml" />
</node>
</launch>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<package format='2'>
<name>ublox_gps</name>
<version>1.1.2</version>
<description>
Driver for u-blox GPS devices.
</description>
<author>Johannes Meyer</author>
<maintainer email="gcross.code@icloud.com">Gareth Cross</maintainer>
<maintainer email="quchao@seas.upenn.edu">Chao Qu</maintainer>
<maintainer email="vmlane@alum.mit.edu">Veronica Lane</maintainer>
<license>BSD</license>
<url>http://ros.org/wiki/ublox</url>
<buildtool_depend>catkin</buildtool_depend>
<depend>ublox_serialization</depend>
<depend>ublox_msgs</depend>
<depend>roscpp</depend>
<depend>roscpp_serialization</depend>
<depend>diagnostic_updater</depend>
</package>

View File

@@ -0,0 +1,540 @@
//==============================================================================
// Copyright (c) 2012, Johannes Meyer, TU Darmstadt
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Flight Systems and Automatic Control group,
// TU Darmstadt, nor the names of its contributors may be used to
// endorse or promote products derived from this software without
// specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==============================================================================
#include <ublox_gps/gps.h>
namespace ublox_gps {
using namespace ublox_msgs;
const boost::posix_time::time_duration Gps::default_timeout_ =
boost::posix_time::seconds(Gps::kDefaultAckTimeout);
Gps::Gps() : configured_(false) { subscribeAcks(); }
Gps::~Gps() { close(); }
void Gps::setWorker(const boost::shared_ptr<Worker>& worker) {
if (worker_) return;
worker_ = worker;
worker_->setCallback(boost::bind(&CallbackHandlers::readCallback,
&callbacks_, _1, _2));
configured_ = static_cast<bool>(worker);
}
void Gps::subscribeAcks() {
// Set NACK handler
subscribeId<ublox_msgs::Ack>(boost::bind(&Gps::processNack, this, _1),
ublox_msgs::Message::ACK::NACK);
// Set ACK handler
subscribeId<ublox_msgs::Ack>(boost::bind(&Gps::processAck, this, _1),
ublox_msgs::Message::ACK::ACK);
// Set UPD-SOS-ACK handler
subscribe<ublox_msgs::UpdSOS_Ack>(
boost::bind(&Gps::processUpdSosAck, this, _1));
}
void Gps::processAck(const ublox_msgs::Ack &m) {
// Process ACK/NACK messages
Ack ack;
ack.type = ACK;
ack.class_id = m.clsID;
ack.msg_id = m.msgID;
// store the ack atomically
ack_.store(ack, boost::memory_order_seq_cst);
ROS_DEBUG_COND(debug >= 2, "U-blox: received ACK: 0x%02x / 0x%02x",
m.clsID, m.msgID);
}
void Gps::processNack(const ublox_msgs::Ack &m) {
// Process ACK/NACK messages
Ack ack;
ack.type = NACK;
ack.class_id = m.clsID;
ack.msg_id = m.msgID;
// store the ack atomically
ack_.store(ack, boost::memory_order_seq_cst);
ROS_ERROR("U-blox: received NACK: 0x%02x / 0x%02x", m.clsID, m.msgID);
}
void Gps::processUpdSosAck(const ublox_msgs::UpdSOS_Ack &m) {
if (m.cmd == UpdSOS_Ack::CMD_BACKUP_CREATE_ACK) {
Ack ack;
ack.type = (m.response == m.BACKUP_CREATE_ACK) ? ACK : NACK;
ack.class_id = m.CLASS_ID;
ack.msg_id = m.MESSAGE_ID;
// store the ack atomically
ack_.store(ack, boost::memory_order_seq_cst);
ROS_DEBUG_COND(ack.type == ACK && debug >= 2,
"U-blox: received UPD SOS Backup ACK");
if(ack.type == NACK)
ROS_ERROR("U-blox: received UPD SOS Backup NACK");
}
}
void Gps::initializeSerial(std::string port, unsigned int baudrate,
uint16_t uart_in, uint16_t uart_out) {
port_ = port;
boost::shared_ptr<boost::asio::io_service> io_service(
new boost::asio::io_service);
boost::shared_ptr<boost::asio::serial_port> serial(
new boost::asio::serial_port(*io_service));
// open serial port
try {
serial->open(port);
} catch (std::runtime_error& e) {
throw std::runtime_error("U-Blox: Could not open serial port :"
+ port + " " + e.what());
}
ROS_INFO("U-Blox: Opened serial port %s", port.c_str());
// Set the I/O worker
if (worker_) return;
setWorker(boost::shared_ptr<Worker>(
new AsyncWorker<boost::asio::serial_port>(serial, io_service)));
configured_ = false;
// Set the baudrate
boost::asio::serial_port_base::baud_rate current_baudrate;
serial->get_option(current_baudrate);
// Incrementally increase the baudrate to the desired value
for (int i = 0; i < sizeof(kBaudrates)/sizeof(kBaudrates[0]); i++) {
if (current_baudrate.value() == baudrate)
break;
// Don't step down, unless the desired baudrate is lower
if(current_baudrate.value() > kBaudrates[i] && baudrate > kBaudrates[i])
continue;
serial->set_option(
boost::asio::serial_port_base::baud_rate(kBaudrates[i]));
boost::this_thread::sleep(
boost::posix_time::milliseconds(kSetBaudrateSleepMs));
serial->get_option(current_baudrate);
ROS_DEBUG("U-Blox: Set ASIO baudrate to %u", current_baudrate.value());
}
configured_ = configUart1(baudrate, uart_in, uart_out);
if(!configured_ || current_baudrate.value() != baudrate) {
throw std::runtime_error("Could not configure serial baud rate");
}
}
void Gps::resetSerial(std::string port) {
boost::shared_ptr<boost::asio::io_service> io_service(
new boost::asio::io_service);
boost::shared_ptr<boost::asio::serial_port> serial(
new boost::asio::serial_port(*io_service));
// open serial port
try {
serial->open(port);
} catch (std::runtime_error& e) {
throw std::runtime_error("U-Blox: Could not open serial port :"
+ port + " " + e.what());
}
ROS_INFO("U-Blox: Reset serial port %s", port.c_str());
// Set the I/O worker
if (worker_) return;
setWorker(boost::shared_ptr<Worker>(
new AsyncWorker<boost::asio::serial_port>(serial, io_service)));
configured_ = false;
// Poll UART PRT Config
std::vector<uint8_t> payload;
payload.push_back(CfgPRT::PORT_ID_UART1);
if (!poll(CfgPRT::CLASS_ID, CfgPRT::MESSAGE_ID, payload)) {
ROS_ERROR("Resetting Serial Port: Could not poll UART1 CfgPRT");
return;
}
CfgPRT prt;
if(!read(prt, default_timeout_)) {
ROS_ERROR("Resetting Serial Port: Could not read polled UART1 CfgPRT %s",
"message");
return;
}
// Set the baudrate
serial->set_option(boost::asio::serial_port_base::baud_rate(prt.baudRate));
configured_ = true;
}
void Gps::initializeTcp(std::string host, std::string port) {
host_ = host;
port_ = port;
boost::shared_ptr<boost::asio::io_service> io_service(
new boost::asio::io_service);
boost::asio::ip::tcp::resolver::iterator endpoint;
try {
boost::asio::ip::tcp::resolver resolver(*io_service);
endpoint =
resolver.resolve(boost::asio::ip::tcp::resolver::query(host, port));
} catch (std::runtime_error& e) {
throw std::runtime_error("U-Blox: Could not resolve" + host + " " +
port + " " + e.what());
}
boost::shared_ptr<boost::asio::ip::tcp::socket> socket(
new boost::asio::ip::tcp::socket(*io_service));
try {
socket->connect(*endpoint);
} catch (std::runtime_error& e) {
throw std::runtime_error("U-Blox: Could not connect to " +
endpoint->host_name() + ":" +
endpoint->service_name() + ": " + e.what());
}
ROS_INFO("U-Blox: Connected to %s:%s.", endpoint->host_name().c_str(),
endpoint->service_name().c_str());
if (worker_) return;
setWorker(boost::shared_ptr<Worker>(
new AsyncWorker<boost::asio::ip::tcp::socket>(socket,
io_service)));
}
void Gps::close() {
if(save_on_shutdown_) {
if(saveOnShutdown())
ROS_INFO("U-Blox Flash BBR saved");
else
ROS_INFO("U-Blox Flash BBR failed to save");
}
worker_.reset();
configured_ = false;
}
void Gps::reset(const boost::posix_time::time_duration& wait) {
worker_.reset();
configured_ = false;
// sleep because of undefined behavior after I/O reset
boost::this_thread::sleep(wait);
if (host_ == "")
resetSerial(port_);
else
initializeTcp(host_, port_);
}
bool Gps::configReset(uint16_t nav_bbr_mask, uint16_t reset_mode) {
ROS_WARN("Resetting u-blox. If device address changes, %s",
"node must be relaunched.");
CfgRST rst;
rst.navBbrMask = nav_bbr_mask;
rst.resetMode = reset_mode;
// Don't wait for ACK, return if it fails
if (!configure(rst, false))
return false;
return true;
}
bool Gps::configGnss(CfgGNSS gnss,
const boost::posix_time::time_duration& wait) {
// Configure the GNSS settings
ROS_DEBUG("Re-configuring GNSS.");
if (!configure(gnss))
return false;
// Cold reset the GNSS
ROS_WARN("GNSS re-configured, cold resetting device.");
if (!configReset(CfgRST::NAV_BBR_COLD_START, CfgRST::RESET_MODE_GNSS))
return false;
ros::Duration(1.0).sleep();
// Reset the I/O
reset(wait);
return isConfigured();
}
bool Gps::saveOnShutdown() {
// Command the receiver to stop
CfgRST rst;
rst.navBbrMask = rst.NAV_BBR_HOT_START;
rst.resetMode = rst.RESET_MODE_GNSS_STOP;
if(!configure(rst))
return false;
// Command saving the contents of BBR to flash memory
// And wait for UBX-UPD-SOS-ACK
UpdSOS backup;
return configure(backup);
}
bool Gps::clearBbr() {
// Command saving the contents of BBR to flash memory
// And wait for UBX-UPD-SOS-ACK
UpdSOS sos;
sos.cmd = sos.CMD_FLASH_BACKUP_CLEAR;
return configure(sos);
}
bool Gps::configUart1(unsigned int baudrate, uint16_t in_proto_mask,
uint16_t out_proto_mask) {
if (!worker_) return true;
ROS_DEBUG("Configuring UART1 baud rate: %u, In/Out Protocol: %u / %u",
baudrate, in_proto_mask, out_proto_mask);
CfgPRT port;
port.portID = CfgPRT::PORT_ID_UART1;
port.baudRate = baudrate;
port.mode = CfgPRT::MODE_RESERVED1 | CfgPRT::MODE_CHAR_LEN_8BIT |
CfgPRT::MODE_PARITY_NO | CfgPRT::MODE_STOP_BITS_1;
port.inProtoMask = in_proto_mask;
port.outProtoMask = out_proto_mask;
return configure(port);
}
bool Gps::disableUart1(CfgPRT& prev_config) {
ROS_DEBUG("Disabling UART1");
// Poll UART PRT Config
std::vector<uint8_t> payload;
payload.push_back(CfgPRT::PORT_ID_UART1);
if (!poll(CfgPRT::CLASS_ID, CfgPRT::MESSAGE_ID, payload)) {
ROS_ERROR("disableUart: Could not poll UART1 CfgPRT");
return false;
}
if(!read(prev_config, default_timeout_)) {
ROS_ERROR("disableUart: Could not read polled UART1 CfgPRT message");
return false;
}
// Keep original settings, but disable in/out
CfgPRT port;
port.portID = CfgPRT::PORT_ID_UART1;
port.mode = prev_config.mode;
port.baudRate = prev_config.baudRate;
port.inProtoMask = 0;
port.outProtoMask = 0;
port.txReady = prev_config.txReady;
port.flags = prev_config.flags;
return configure(port);
}
bool Gps::configUsb(uint16_t tx_ready,
uint16_t in_proto_mask,
uint16_t out_proto_mask) {
if (!worker_) return true;
ROS_DEBUG("Configuring USB tx_ready: %u, In/Out Protocol: %u / %u",
tx_ready, in_proto_mask, out_proto_mask);
CfgPRT port;
port.portID = CfgPRT::PORT_ID_USB;
port.txReady = tx_ready;
port.inProtoMask = in_proto_mask;
port.outProtoMask = out_proto_mask;
return configure(port);
}
bool Gps::configRate(uint16_t meas_rate, uint16_t nav_rate) {
ROS_DEBUG("Configuring measurement rate to %u and nav rate to %u", meas_rate,
nav_rate);
CfgRATE rate;
rate.measRate = meas_rate;
rate.navRate = nav_rate; // must be fixed at 1 for ublox 5 and 6
rate.timeRef = CfgRATE::TIME_REF_GPS;
return configure(rate);
}
bool Gps::configRtcm(std::vector<uint8_t> ids, std::vector<uint8_t> rates) {
for(size_t i = 0; i < ids.size(); ++i) {
ROS_DEBUG("Setting RTCM %d Rate %u", ids[i], rates[i]);
if(!setRate(ublox_msgs::Class::RTCM, (uint8_t)ids[i], rates[i])) {
ROS_ERROR("Could not set RTCM %d to rate %u", ids[i], rates[i]);
return false;
}
}
return true;
}
bool Gps::configSbas(bool enable, uint8_t usage, uint8_t max_sbas) {
ROS_DEBUG("Configuring SBAS: usage %u, max_sbas %u", usage, max_sbas);
ublox_msgs::CfgSBAS msg;
msg.mode = (enable ? CfgSBAS::MODE_ENABLED : 0);
msg.usage = usage;
msg.maxSBAS = max_sbas;
return configure(msg);
}
bool Gps::configTmode3Fixed(bool lla_flag,
std::vector<float> arp_position,
std::vector<int8_t> arp_position_hp,
float fixed_pos_acc) {
if(arp_position.size() != 3 || arp_position_hp.size() != 3) {
ROS_ERROR("Configuring TMODE3 to Fixed: size of position %s",
"& arp_position_hp args must be 3");
return false;
}
ROS_DEBUG("Configuring TMODE3 to Fixed");
CfgTMODE3 tmode3;
tmode3.flags = tmode3.FLAGS_MODE_FIXED & tmode3.FLAGS_MODE_MASK;
tmode3.flags |= lla_flag ? tmode3.FLAGS_LLA : 0;
// Set position
if(lla_flag) {
// Convert from [deg] to [deg * 1e-7]
tmode3.ecefXOrLat = (int)round(arp_position[0] * 1e7);
tmode3.ecefYOrLon = (int)round(arp_position[1] * 1e7);
tmode3.ecefZOrAlt = (int)round(arp_position[2] * 1e7);
} else {
// Convert from m to cm
tmode3.ecefXOrLat = (int)round(arp_position[0] * 1e2);
tmode3.ecefYOrLon = (int)round(arp_position[1] * 1e2);
tmode3.ecefZOrAlt = (int)round(arp_position[2] * 1e2);
}
tmode3.ecefXOrLatHP = arp_position_hp[0];
tmode3.ecefYOrLonHP = arp_position_hp[1];
tmode3.ecefZOrAltHP = arp_position_hp[2];
// Convert from m to [0.1 mm]
tmode3.fixedPosAcc = (uint32_t)round(fixed_pos_acc * 1e4);
return configure(tmode3);
}
bool Gps::configTmode3SurveyIn(unsigned int svin_min_dur,
float svin_acc_limit) {
CfgTMODE3 tmode3;
ROS_DEBUG("Setting TMODE3 to Survey In");
tmode3.flags = tmode3.FLAGS_MODE_SURVEY_IN & tmode3.FLAGS_MODE_MASK;
tmode3.svinMinDur = svin_min_dur;
// Convert from m to [0.1 mm]
tmode3.svinAccLimit = (int)round(svin_acc_limit * 1e4);
return configure(tmode3);
}
bool Gps::disableTmode3() {
ROS_DEBUG("Disabling TMODE3");
CfgTMODE3 tmode3;
tmode3.flags = tmode3.FLAGS_MODE_DISABLED & tmode3.FLAGS_MODE_MASK;
return configure(tmode3);
}
bool Gps::setRate(uint8_t class_id, uint8_t message_id, uint8_t rate) {
ROS_DEBUG_COND(debug >= 2, "Setting rate 0x%02x, 0x%02x, %u", class_id,
message_id, rate);
ublox_msgs::CfgMSG msg;
msg.msgClass = class_id;
msg.msgID = message_id;
msg.rate = rate;
return configure(msg);
}
bool Gps::setDynamicModel(uint8_t model) {
ROS_DEBUG("Setting dynamic model to %u", model);
ublox_msgs::CfgNAV5 msg;
msg.dynModel = model;
msg.mask = ublox_msgs::CfgNAV5::MASK_DYN;
return configure(msg);
}
bool Gps::setFixMode(uint8_t mode) {
ROS_DEBUG("Setting fix mode to %u", mode);
ublox_msgs::CfgNAV5 msg;
msg.fixMode = mode;
msg.mask = ublox_msgs::CfgNAV5::MASK_FIX_MODE;
return configure(msg);
}
bool Gps::setDeadReckonLimit(uint8_t limit) {
ROS_DEBUG("Setting DR Limit to %u", limit);
ublox_msgs::CfgNAV5 msg;
msg.drLimit = limit;
msg.mask = ublox_msgs::CfgNAV5::MASK_DR_LIM;
return configure(msg);
}
bool Gps::setPpp(bool enable) {
ROS_DEBUG("%s PPP", (enable ? "Enabling" : "Disabling"));
ublox_msgs::CfgNAVX5 msg;
msg.usePPP = enable;
msg.mask1 = ublox_msgs::CfgNAVX5::MASK1_PPP;
return configure(msg);
}
bool Gps::setDgnss(uint8_t mode) {
CfgDGNSS cfg;
ROS_DEBUG("Setting DGNSS mode to %u", mode);
cfg.dgnssMode = mode;
return configure(cfg);
}
bool Gps::setUseAdr(bool enable) {
ROS_DEBUG("%s ADR/UDR", (enable ? "Enabling" : "Disabling"));
ublox_msgs::CfgNAVX5 msg;
msg.useAdr = enable;
msg.mask2 = ublox_msgs::CfgNAVX5::MASK2_ADR;
return configure(msg);
}
bool Gps::poll(uint8_t class_id, uint8_t message_id,
const std::vector<uint8_t>& payload) {
if (!worker_) return false;
std::vector<unsigned char> out(kWriterSize);
ublox::Writer writer(out.data(), out.size());
if (!writer.write(payload.data(), payload.size(), class_id, message_id))
return false;
worker_->send(out.data(), writer.end() - out.data());
return true;
}
bool Gps::waitForAcknowledge(const boost::posix_time::time_duration& timeout,
uint8_t class_id, uint8_t msg_id) {
ROS_DEBUG_COND(debug >= 2, "Waiting for ACK 0x%02x / 0x%02x",
class_id, msg_id);
boost::posix_time::ptime wait_until(
boost::posix_time::second_clock::local_time() + timeout);
Ack ack = ack_.load(boost::memory_order_seq_cst);
while (boost::posix_time::second_clock::local_time() < wait_until
&& (ack.class_id != class_id
|| ack.msg_id != msg_id
|| ack.type == WAIT)) {
worker_->wait(timeout);
ack = ack_.load(boost::memory_order_seq_cst);
}
bool result = ack.type == ACK
&& ack.class_id == class_id
&& ack.msg_id == msg_id;
return result;
}
} // namespace ublox_gps

View File

@@ -0,0 +1,156 @@
/* mkgmtime.c - make time corresponding to a GMT timeval struct
$Id: mkgmtime.c,v 1.10 2003/10/22 18:50:12 rjs3 Exp $
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*
*/
/*
* Copyright (c) 1987, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Arthur David Olson of the National Cancer Institute.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
** Adapted from code provided by Robert Elz, who writes:
** The "best" way to do mktime I think is based on an idea of Bob
** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
** It does a binary search of the time_t space. Since time_t's are
** just 32 bits, its a max of 32 iterations (even at 64 bits it
** would still be very reasonable).
*/
#include "ublox_gps/mkgmtime.h"
#ifndef WRONG
#define WRONG (-1)
#endif /* !defined WRONG */
static int tmcomp(register const struct tm * const atmp,
register const struct tm * const btmp)
{
register int result;
if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
(result = (atmp->tm_min - btmp->tm_min)) == 0)
result = atmp->tm_sec - btmp->tm_sec;
return result;
}
time_t mkgmtime(struct tm * const tmp) {
register int dir;
register int bits;
register int saved_seconds;
time_t t;
struct tm yourtm, *mytm;
yourtm = *tmp;
saved_seconds = yourtm.tm_sec;
yourtm.tm_sec = 0;
/*
** Calculate the number of magnitude bits in a time_t
** (this works regardless of whether time_t is
** signed or unsigned, though lint complains if unsigned).
*/
for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
;
/*
** If time_t is signed, then 0 is the median value,
** if time_t is unsigned, then 1 << bits is median.
*/
t = (t < 0) ? 0 : ((time_t) 1 << bits);
/* Some gmtime() implementations are broken and will return
* NULL for time_ts larger than 40 bits even on 64-bit platforms
* so we'll just cap it at 40 bits */
if(bits > 40) bits = 40;
for ( ; ; ) {
mytm = gmtime(&t);
if(!mytm) return WRONG;
dir = tmcomp(mytm, &yourtm);
if (dir != 0) {
if (bits-- < 0)
return WRONG;
if (bits < 0)
--t;
else if (dir > 0)
t -= (time_t) 1 << bits;
else t += (time_t) 1 << bits;
continue;
}
break;
}
t += saved_seconds;
return t;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 2.8.3)
project(ublox_msgs)
find_package(catkin REQUIRED COMPONENTS message_generation ublox_serialization std_msgs sensor_msgs)
add_message_files(DIRECTORY msg)
generate_messages(DEPENDENCIES std_msgs sensor_msgs)
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS message_runtime ublox_serialization std_msgs sensor_msgs)
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${ublox_serialization_INCLUDE_DIRS})
add_library(${PROJECT_NAME} src/ublox_msgs.cpp)
add_dependencies(${PROJECT_NAME}
${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS}
)
target_link_libraries(${PROJECT_NAME}
${catkin_LIBRARIES}
)
install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
install(DIRECTORY include/
DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
PATTERN ".svn" EXCLUDE
)

View File

@@ -0,0 +1,883 @@
//==============================================================================
// Copyright (c) 2012, Johannes Meyer, TU Darmstadt
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Flight Systems and Automatic Control group,
// TU Darmstadt, nor the names of its contributors may be used to
// endorse or promote products derived from this software without
// specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==============================================================================
#ifndef UBLOX_SERIALIZATION_UBLOX_MSGS_H
#define UBLOX_SERIALIZATION_UBLOX_MSGS_H
#include <ros/console.h>
#include <ublox/serialization.h>
#include <ublox_msgs/ublox_msgs.h>
///
/// This file declares custom serializers for u-blox messages with dynamic
/// lengths and messages where the get/set messages have different sizes, but
/// share the same parameters, such as CfgDAT.
///
namespace ublox {
///
/// @brief Serializes the CfgDAT message which has a different length for
/// get/set.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::CfgDAT_<ContainerAllocator> > {
typedef boost::call_traits<ublox_msgs::CfgDAT_<ContainerAllocator> >
CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.datumNum);
stream.next(m.datumName);
stream.next(m.majA);
stream.next(m.flat);
stream.next(m.dX);
stream.next(m.dY);
stream.next(m.dZ);
stream.next(m.rotX);
stream.next(m.rotY);
stream.next(m.rotZ);
stream.next(m.scale);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
// this is the size of CfgDAT set messages
// serializedLength is only used for writes so this is ok
return 44;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
// ignores datumNum & datumName
stream.next(m.majA);
stream.next(m.flat);
stream.next(m.dX);
stream.next(m.dY);
stream.next(m.dZ);
stream.next(m.rotX);
stream.next(m.rotY);
stream.next(m.rotZ);
stream.next(m.scale);
}
};
///
/// @brief Serializes the CfgGNSS message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::CfgGNSS_<ContainerAllocator> > {
typedef ublox_msgs::CfgGNSS_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.msgVer);
stream.next(m.numTrkChHw);
stream.next(m.numTrkChUse);
stream.next(m.numConfigBlocks);
m.blocks.resize(m.numConfigBlocks);
for(std::size_t i = 0; i < m.blocks.size(); ++i)
ros::serialization::deserialize(stream, m.blocks[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 4 + 8 * m.numConfigBlocks;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.blocks.size() != m.numConfigBlocks) {
ROS_ERROR("CfgGNSS numConfigBlocks must equal blocks size");
}
ros::serialization::OStream stream(data, size);
stream.next(m.msgVer);
stream.next(m.numTrkChHw);
stream.next(m.numTrkChUse);
stream.next(
static_cast<typename Msg::_numConfigBlocks_type>(m.blocks.size()));
for(std::size_t i = 0; i < m.blocks.size(); ++i)
ros::serialization::serialize(stream, m.blocks[i]);
}
};
///
/// @brief Serializes the CfgInf message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::CfgINF_<ContainerAllocator> > {
typedef boost::call_traits<ublox_msgs::CfgINF_<ContainerAllocator> >
CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
int num_blocks = count / 10;
m.blocks.resize(num_blocks);
for(std::size_t i = 0; i < num_blocks; ++i)
ros::serialization::deserialize(stream, m.blocks[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 10 * m.blocks.size();
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
for(std::size_t i = 0; i < m.blocks.size(); ++i)
ros::serialization::serialize(stream, m.blocks[i]);
}
};
///
/// @brief Serializes the Inf message which has a dynamic length string.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::Inf_<ContainerAllocator> > {
typedef boost::call_traits<ublox_msgs::Inf_<ContainerAllocator> > CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
m.str.resize(count);
for (int i = 0; i < count; ++i)
ros::serialization::deserialize(stream, m.str[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return m.str.size();
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
for(std::size_t i = 0; i < m.str.size(); ++i)
ros::serialization::serialize(stream, m.str[i]);
}
};
///
/// @brief Serializes the MonVER message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::MonVER_<ContainerAllocator> > {
typedef ublox_msgs::MonVER_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.swVersion);
stream.next(m.hwVersion);
m.extension.clear();
int N = (count - 40) / 30;
m.extension.reserve(N);
typename Msg::_extension_type::value_type ext;
for (int i = 0; i < N; i++) {
// Read each extension string
stream.next(ext);
m.extension.push_back(ext);
}
}
static uint32_t serializedLength(typename CallTraits::param_type m) {
return 40 + (30 * m.extension.size());
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
stream.next(m.swVersion);
stream.next(m.hwVersion);
for(std::size_t i = 0; i < m.extension.size(); ++i)
ros::serialization::serialize(stream, m.extension[i]);
}
};
///
/// @brief Serializes the NavDGPS message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::NavDGPS_<ContainerAllocator> > {
typedef ublox_msgs::NavDGPS_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.iTOW);
stream.next(m.age);
stream.next(m.baseId);
stream.next(m.baseHealth);
stream.next(m.numCh);
stream.next(m.status);
stream.next(m.reserved1);
m.sv.resize(m.numCh);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::deserialize(stream, m.sv[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 16 + 12 * m.numCh;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.sv.size() != m.numCh) {
ROS_ERROR("NavDGPS numCh must equal sv size");
}
ros::serialization::OStream stream(data, size);
stream.next(m.iTOW);
stream.next(m.age);
stream.next(m.baseId);
stream.next(m.baseHealth);
stream.next(static_cast<typename Msg::_numCh_type>(m.sv.size()));
stream.next(m.status);
stream.next(m.reserved1);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::serialize(stream, m.sv[i]);
}
};
///
/// @brief Serializes the NavSBAS message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::NavSBAS_<ContainerAllocator> > {
typedef ublox_msgs::NavSBAS_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.iTOW);
stream.next(m.geo);
stream.next(m.mode);
stream.next(m.sys);
stream.next(m.service);
stream.next(m.cnt);
stream.next(m.reserved0);
m.sv.resize(m.cnt);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::deserialize(stream, m.sv[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 12 + 12 * m.cnt;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.sv.size() != m.cnt) {
ROS_ERROR("NavSBAS cnt must equal sv size");
}
ros::serialization::OStream stream(data, size);
stream.next(m.iTOW);
stream.next(m.geo);
stream.next(m.mode);
stream.next(m.sys);
stream.next(m.service);
stream.next(static_cast<typename Msg::_cnt_type>(m.sv.size()));
stream.next(m.reserved0);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::serialize(stream, m.sv[i]);
}
};
///
/// @brief Serializes the NavSAT message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::NavSAT_<ContainerAllocator> > {
typedef ublox_msgs::NavSAT_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.iTOW);
stream.next(m.version);
stream.next(m.numSvs);
stream.next(m.reserved0);
m.sv.resize(m.numSvs);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::deserialize(stream, m.sv[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 8 + 12 * m.numSvs;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.sv.size() != m.numSvs) {
ROS_ERROR("NavSAT numSvs must equal sv size");
}
ros::serialization::OStream stream(data, size);
stream.next(m.iTOW);
stream.next(m.version);
stream.next(static_cast<typename Msg::_numSvs_type>(m.sv.size()));
stream.next(m.reserved0);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::serialize(stream, m.sv[i]);
}
};
///
/// @brief Serializes the NavDGPS message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::NavSVINFO_<ContainerAllocator> > {
typedef ublox_msgs::NavSVINFO_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.iTOW);
stream.next(m.numCh);
stream.next(m.globalFlags);
stream.next(m.reserved2);
m.sv.resize(m.numCh);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::deserialize(stream, m.sv[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 8 + 12 * m.numCh;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.sv.size() != m.numCh) {
ROS_ERROR("NavSVINFO numCh must equal sv size");
}
ros::serialization::OStream stream(data, size);
stream.next(m.iTOW);
stream.next(static_cast<typename Msg::_numCh_type>(m.sv.size()));
stream.next(m.globalFlags);
stream.next(m.reserved2);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::serialize(stream, m.sv[i]);
}
};
///
/// @brief Serializes the RxmRAW message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::RxmRAW_<ContainerAllocator> > {
typedef ublox_msgs::RxmRAW_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.rcvTOW);
stream.next(m.week);
stream.next(m.numSV);
stream.next(m.reserved1);
m.sv.resize(m.numSV);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::deserialize(stream, m.sv[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 8 + 24 * m.numSV;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.sv.size() != m.numSV) {
ROS_ERROR("RxmRAW numSV must equal sv size");
}
ros::serialization::OStream stream(data, size);
stream.next(m.rcvTOW);
stream.next(m.week);
stream.next(static_cast<typename Msg::_numSV_type>(m.sv.size()));
stream.next(m.reserved1);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::serialize(stream, m.sv[i]);
}
};
///
/// @brief Serializes the RxmRAWX message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::RxmRAWX_<ContainerAllocator> > {
typedef ublox_msgs::RxmRAWX_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.rcvTOW);
stream.next(m.week);
stream.next(m.leapS);
stream.next(m.numMeas);
stream.next(m.recStat);
stream.next(m.version);
stream.next(m.reserved1);
m.meas.resize(m.numMeas);
for(std::size_t i = 0; i < m.meas.size(); ++i)
ros::serialization::deserialize(stream, m.meas[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 16 + 32 * m.numMeas;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.meas.size() != m.numMeas) {
ROS_ERROR("RxmRAWX numMeas must equal meas size");
}
ros::serialization::OStream stream(data, size);
stream.next(m.rcvTOW);
stream.next(m.week);
stream.next(m.leapS);
stream.next(static_cast<typename Msg::_numMeas_type>(m.meas.size()));
stream.next(m.recStat);
stream.next(m.version);
stream.next(m.reserved1);
for(std::size_t i = 0; i < m.meas.size(); ++i)
ros::serialization::serialize(stream, m.meas[i]);
}
};
///
/// @brief Serializes the RxmSFRBX message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::RxmSFRBX_<ContainerAllocator> > {
typedef ublox_msgs::RxmSFRBX_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.gnssId);
stream.next(m.svId);
stream.next(m.reserved0);
stream.next(m.freqId);
stream.next(m.numWords);
stream.next(m.chn);
stream.next(m.version);
stream.next(m.reserved1);
m.dwrd.resize(m.numWords);
for(std::size_t i = 0; i < m.dwrd.size(); ++i)
ros::serialization::deserialize(stream, m.dwrd[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 8 + 4 * m.numWords;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.dwrd.size() != m.numWords) {
ROS_ERROR("RxmSFRBX numWords must equal dwrd size");
}
ros::serialization::OStream stream(data, size);
stream.next(m.gnssId);
stream.next(m.svId);
stream.next(m.reserved0);
stream.next(m.freqId);
stream.next(static_cast<typename Msg::_numWords_type>(m.dwrd.size()));
stream.next(m.chn);
stream.next(m.version);
stream.next(m.reserved1);
for(std::size_t i = 0; i < m.dwrd.size(); ++i)
ros::serialization::serialize(stream, m.dwrd[i]);
}
};
///
/// @brief Serializes the RxmSVSI message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::RxmSVSI_<ContainerAllocator> > {
typedef ublox_msgs::RxmSVSI_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.iTOW);
stream.next(m.week);
stream.next(m.numVis);
stream.next(m.numSV);
m.sv.resize(m.numSV);
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::deserialize(stream, m.sv[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 8 + 6 * m.numSV;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.sv.size() != m.numSV) {
ROS_ERROR("RxmSVSI numSV must equal sv size");
}
ros::serialization::OStream stream(data, size);
stream.next(m.iTOW);
stream.next(m.week);
stream.next(m.numVis);
stream.next(static_cast<typename Msg::_numSV_type>(m.sv.size()));
for(std::size_t i = 0; i < m.sv.size(); ++i)
ros::serialization::serialize(stream, m.sv[i]);
}
};
///
/// @brief Serializes the RxmALM message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::RxmALM_<ContainerAllocator> > {
typedef ublox_msgs::RxmALM_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.svid);
stream.next(m.week);
m.dwrd.clear();
if(count == 40) {
typename Msg::_dwrd_type::value_type temp;
m.dwrd.resize(8);
for(std::size_t i = 0; i < 8; ++i) {
stream.next(temp);
m.dwrd.push_back(temp);
}
}
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 8 + (4 * m.dwrd.size());
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
stream.next(m.svid);
stream.next(m.week);
for(std::size_t i = 0; i < m.dwrd.size(); ++i)
ros::serialization::serialize(stream, m.dwrd[i]);
}
};
///
/// @brief Serializes the RxmEPH message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::RxmEPH_<ContainerAllocator> >
{
typedef ublox_msgs::RxmEPH_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.svid);
stream.next(m.how);
m.sf1d.clear();
m.sf2d.clear();
m.sf3d.clear();
if (count == 104) {
typename Msg::_sf1d_type::value_type temp1;
typename Msg::_sf2d_type::value_type temp2;
typename Msg::_sf3d_type::value_type temp3;
m.sf1d.resize(8);
for(std::size_t i = 0; i < 8; ++i) {
stream.next(temp1);
m.sf1d.push_back(temp1);
}
m.sf2d.resize(8);
for(std::size_t i = 0; i < 8; ++i) {
stream.next(temp2);
m.sf2d.push_back(temp2);
}
m.sf3d.resize(8);
for(std::size_t i = 0; i < 8; ++i) {
stream.next(temp3);
m.sf3d.push_back(temp3);
}
}
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 8 + (4 * m.sf1d.size()) + (4 * m.sf2d.size()) + (4 * m.sf3d.size());
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
stream.next(m.svid);
stream.next(m.how);
for(std::size_t i = 0; i < m.sf1d.size(); ++i)
ros::serialization::serialize(stream, m.sf1d[i]);
for(std::size_t i = 0; i < m.sf2d.size(); ++i)
ros::serialization::serialize(stream, m.sf2d[i]);
for(std::size_t i = 0; i < m.sf3d.size(); ++i)
ros::serialization::serialize(stream, m.sf3d[i]);
}
};
///
/// @brief Serializes the AidALM message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::AidALM_<ContainerAllocator> > {
typedef ublox_msgs::AidALM_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.svid);
stream.next(m.week);
m.dwrd.clear();
if (count == 40) {
typename Msg::_dwrd_type::value_type temp;
m.dwrd.resize(8);
for(std::size_t i = 0; i < 8; ++i) {
stream.next(temp);
m.dwrd.push_back(temp);
}
}
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 8 + (4 * m.dwrd.size());
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
stream.next(m.svid);
stream.next(m.week);
for(std::size_t i = 0; i < m.dwrd.size(); ++i)
ros::serialization::serialize(stream, m.dwrd[i]);
}
};
///
/// @brief Serializes the AidEPH message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::AidEPH_<ContainerAllocator> >
{
typedef ublox_msgs::AidEPH_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.svid);
stream.next(m.how);
m.sf1d.clear();
m.sf2d.clear();
m.sf3d.clear();
if (count == 104) {
typename Msg::_sf1d_type::value_type temp1;
typename Msg::_sf2d_type::value_type temp2;
typename Msg::_sf3d_type::value_type temp3;
m.sf1d.resize(8);
for(std::size_t i = 0; i < 8; ++i) {
stream.next(temp1);
m.sf1d.push_back(temp1);
}
m.sf2d.resize(8);
for(std::size_t i = 0; i < 8; ++i) {
stream.next(temp2);
m.sf2d.push_back(temp2);
}
m.sf3d.resize(8);
for(std::size_t i = 0; i < 8; ++i) {
stream.next(temp3);
m.sf3d.push_back(temp3);
}
}
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 8 + (4 * m.sf1d.size()) + (4 * m.sf2d.size()) + (4 * m.sf3d.size());
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
stream.next(m.svid);
stream.next(m.how);
for(std::size_t i = 0; i < m.sf1d.size(); ++i)
ros::serialization::serialize(stream, m.sf1d[i]);
for(std::size_t i = 0; i < m.sf2d.size(); ++i)
ros::serialization::serialize(stream, m.sf2d[i]);
for(std::size_t i = 0; i < m.sf3d.size(); ++i)
ros::serialization::serialize(stream, m.sf3d[i]);
}
};
///
/// @brief Serializes the EsfMEAS message which has a repeated block and an
/// optional block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::EsfMEAS_<ContainerAllocator> > {
typedef boost::call_traits<ublox_msgs::EsfMEAS_<ContainerAllocator> >
CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.timeTag);
stream.next(m.flags);
stream.next(m.id);
bool calib_valid = m.flags & m.FLAGS_CALIB_T_TAG_VALID;
int data_size = (count - (calib_valid ? 12 : 8)) / 4;
// Repeating block
m.data.resize(data_size);
for(std::size_t i = 0; i < data_size; ++i)
ros::serialization::deserialize(stream, m.data[i]);
// Optional block
if(calib_valid) {
m.calibTtag.resize(1);
ros::serialization::deserialize(stream, m.calibTtag[0]);
}
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 4 + 8 * m.data.size() + 4 * m.calibTtag.size();
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
stream.next(m.timeTag);
stream.next(m.flags);
stream.next(m.id);
for(std::size_t i = 0; i < m.data.size(); ++i)
ros::serialization::serialize(stream, m.data[i]);
for(std::size_t i = 0; i < m.calibTtag.size(); ++i)
ros::serialization::serialize(stream, m.calibTtag[i]);
}
};
///
/// @brief Serializes the EsfRAW message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::EsfRAW_<ContainerAllocator> > {
typedef boost::call_traits<ublox_msgs::EsfRAW_<ContainerAllocator> >
CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.reserved0);
m.blocks.clear();
int num_blocks = (count - 4) / 8;
m.blocks.resize(num_blocks);
for(std::size_t i = 0; i < num_blocks; ++i)
ros::serialization::deserialize(stream, m.blocks[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 4 + 8 * m.blocks.size();
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
ros::serialization::OStream stream(data, size);
stream.next(m.reserved0);
for(std::size_t i = 0; i < m.blocks.size(); ++i)
ros::serialization::serialize(stream, m.blocks[i]);
}
};
///
/// @brief Serializes the EsfSTATUS message which has a repeated block.
///
template <typename ContainerAllocator>
struct Serializer<ublox_msgs::EsfSTATUS_<ContainerAllocator> > {
typedef ublox_msgs::EsfSTATUS_<ContainerAllocator> Msg;
typedef boost::call_traits<Msg> CallTraits;
static void read(const uint8_t *data, uint32_t count,
typename CallTraits::reference m) {
ros::serialization::IStream stream(const_cast<uint8_t *>(data), count);
stream.next(m.iTOW);
stream.next(m.version);
stream.next(m.fusionMode);
stream.next(m.reserved2);
stream.next(m.numSens);
m.sens.resize(m.numSens);
for(std::size_t i = 0; i < m.sens.size(); ++i)
ros::serialization::deserialize(stream, m.sens[i]);
}
static uint32_t serializedLength (typename CallTraits::param_type m) {
return 16 + 4 * m.numSens;
}
static void write(uint8_t *data, uint32_t size,
typename CallTraits::param_type m) {
if(m.sens.size() != m.numSens) {
ROS_ERROR("Writing EsfSTATUS message: numSens must equal size of sens");
}
ros::serialization::OStream stream(data, size);
stream.next(m.iTOW);
stream.next(m.version);
stream.next(m.fusionMode);
stream.next(m.reserved2);
stream.next(static_cast<typename Msg::_numSens_type>(m.sens.size()));
for(std::size_t i = 0; i < m.sens.size(); ++i)
ros::serialization::serialize(stream, m.sens[i]);
}
};
} // namespace ublox
#endif // UBLOX_SERIALIZATION_UBLOX_MSGS_H

View File

@@ -0,0 +1,251 @@
//==============================================================================
// Copyright (c) 2012, Johannes Meyer, TU Darmstadt
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Flight Systems and Automatic Control group,
// TU Darmstadt, nor the names of its contributors may be used to
// endorse or promote products derived from this software without
// specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==============================================================================
#ifndef UBLOX_MSGS_H
#define UBLOX_MSGS_H
#include <ublox_msgs/NavATT.h>
#include <ublox_msgs/NavCLOCK.h>
#include <ublox_msgs/NavDGPS.h>
#include <ublox_msgs/NavDOP.h>
#include <ublox_msgs/NavPOSECEF.h>
#include <ublox_msgs/NavPOSLLH.h>
#include <ublox_msgs/NavRELPOSNED.h>
#include <ublox_msgs/NavSBAS.h>
#include <ublox_msgs/NavSOL.h>
#include <ublox_msgs/NavPVT.h>
#include <ublox_msgs/NavPVT7.h>
#include <ublox_msgs/NavSTATUS.h>
#include <ublox_msgs/NavSAT.h>
#include <ublox_msgs/NavSVIN.h>
#include <ublox_msgs/NavSVINFO.h>
#include <ublox_msgs/NavTIMEGPS.h>
#include <ublox_msgs/NavTIMEUTC.h>
#include <ublox_msgs/NavVELECEF.h>
#include <ublox_msgs/NavVELNED.h>
#include <ublox_msgs/RxmALM.h>
#include <ublox_msgs/RxmEPH.h>
#include <ublox_msgs/RxmRAW.h>
#include <ublox_msgs/RxmRAW_SV.h>
#include <ublox_msgs/RxmRAWX.h>
#include <ublox_msgs/RxmRAWX_Meas.h>
#include <ublox_msgs/RxmRTCM.h>
#include <ublox_msgs/RxmSFRB.h>
#include <ublox_msgs/RxmSFRBX.h>
#include <ublox_msgs/RxmSVSI.h>
#include <ublox_msgs/Inf.h>
#include <ublox_msgs/Ack.h>
#include <ublox_msgs/CfgANT.h>
#include <ublox_msgs/CfgCFG.h>
#include <ublox_msgs/CfgDAT.h>
#include <ublox_msgs/CfgDGNSS.h>
#include <ublox_msgs/CfgGNSS.h>
#include <ublox_msgs/CfgHNR.h>
#include <ublox_msgs/CfgINF.h>
#include <ublox_msgs/CfgINF_Block.h>
#include <ublox_msgs/CfgMSG.h>
#include <ublox_msgs/CfgNAV5.h>
#include <ublox_msgs/CfgNAVX5.h>
#include <ublox_msgs/CfgNMEA.h>
#include <ublox_msgs/CfgNMEA6.h>
#include <ublox_msgs/CfgNMEA7.h>
#include <ublox_msgs/CfgPRT.h>
#include <ublox_msgs/CfgRATE.h>
#include <ublox_msgs/CfgRST.h>
#include <ublox_msgs/CfgSBAS.h>
#include <ublox_msgs/CfgTMODE3.h>
#include <ublox_msgs/CfgUSB.h>
#include <ublox_msgs/UpdSOS.h>
#include <ublox_msgs/UpdSOS_Ack.h>
#include <ublox_msgs/MonGNSS.h>
#include <ublox_msgs/MonHW.h>
#include <ublox_msgs/MonHW6.h>
#include <ublox_msgs/MonVER.h>
#include <ublox_msgs/AidALM.h>
#include <ublox_msgs/AidEPH.h>
#include <ublox_msgs/AidHUI.h>
#include <ublox_msgs/EsfINS.h>
#include <ublox_msgs/EsfMEAS.h>
#include <ublox_msgs/EsfRAW.h>
#include <ublox_msgs/EsfSTATUS.h>
#include <ublox_msgs/EsfSTATUS_Sens.h>
#include <ublox_msgs/MgaGAL.h>
#include <ublox_msgs/HnrPVT.h>
namespace ublox_msgs {
namespace Class {
static const uint8_t NAV = 0x01; //!< Navigation Result Messages: Position,
//!< Speed, Time, Acceleration, Heading,
//!< DOP, SVs used
static const uint8_t RXM = 0x02; //!< Receiver Manager Messages:
//!< Satellite Status, RTC Status
static const uint8_t INF = 0x04; //!< Information Messages:
//!< Printf-Style Messages, with IDs such as
//!< Error, Warning, Notice
static const uint8_t ACK = 0x05; //!< Ack/Nack Messages: Acknowledge or Reject
//!< messages to CFG input messages
static const uint8_t CFG = 0x06; //!< Configuration Input Messages: Set
//!< Dynamic Model, Set DOP Mask, Set Baud
//!< Rate, etc.
static const uint8_t UPD = 0x09; //!< Firmware Update Messages: i.e.
//!< Memory/Flash erase/write, Reboot, Flash
//!< identification, etc.
//!< Used to update the firmware and identify
//!< any attached flash device
static const uint8_t MON = 0x0A; //!< Monitoring Messages: Communication
//!< Status, CPU Load, Stack Usage,
//!< Task Status
static const uint8_t AID = 0x0B; //!< AssistNow Aiding Messages: Ephemeris,
//!< Almanac, other A-GPS data input
static const uint8_t TIM = 0x0D; //!< Timing Messages: Timepulse Output,
//!< Timemark Results
static const uint8_t ESF = 0x10; //!< External Sensor Fusion Messages:
//!< External sensor measurements and status
//!< information
static const uint8_t MGA = 0x13; //!< Multiple GNSS Assistance Messages:
//!< Assistance data for various GNSS
static const uint8_t LOG = 0x21; //!< Logging Messages: Log creation,
//!< deletion, info and retrieval
static const uint8_t SEC = 0x27; //!< Security Feature Messages
static const uint8_t HNR = 0x28; //!< High Rate Navigation Results Messages:
//!< High rate time, position, speed, heading
static const uint8_t RTCM = 0xF5; //!< RTCM Configuration Messages
}
namespace Message {
namespace NAV {
static const uint8_t ATT = NavATT::MESSAGE_ID;
static const uint8_t CLOCK = NavCLOCK::MESSAGE_ID;
static const uint8_t DGPS = NavDGPS::MESSAGE_ID;
static const uint8_t DOP = NavDOP::MESSAGE_ID;
static const uint8_t POSECEF = NavPOSECEF::MESSAGE_ID;
static const uint8_t POSLLH = NavPOSLLH::MESSAGE_ID;
static const uint8_t RELPOSNED = NavRELPOSNED::MESSAGE_ID;
static const uint8_t SBAS = NavSBAS::MESSAGE_ID;
static const uint8_t SOL = NavSOL::MESSAGE_ID;
static const uint8_t PVT = NavPVT::MESSAGE_ID;
static const uint8_t SAT = NavSAT::MESSAGE_ID;
static const uint8_t STATUS = NavSTATUS::MESSAGE_ID;
static const uint8_t SVINFO = NavSVINFO::MESSAGE_ID;
static const uint8_t SVIN = NavSVIN::MESSAGE_ID;
static const uint8_t TIMEGPS = NavTIMEGPS::MESSAGE_ID;
static const uint8_t TIMEUTC = NavTIMEUTC::MESSAGE_ID;
static const uint8_t VELECEF = NavVELECEF::MESSAGE_ID;
static const uint8_t VELNED = NavVELNED::MESSAGE_ID;
}
namespace RXM {
static const uint8_t ALM = RxmALM::MESSAGE_ID;
static const uint8_t EPH = RxmEPH::MESSAGE_ID;
static const uint8_t RAW = RxmRAW::MESSAGE_ID;
static const uint8_t RAWX = RxmRAWX::MESSAGE_ID;
static const uint8_t RTCM = RxmRTCM::MESSAGE_ID;
static const uint8_t SFRB = RxmSFRB::MESSAGE_ID;
static const uint8_t SFRBX = RxmSFRBX::MESSAGE_ID;
static const uint8_t SVSI = RxmSVSI::MESSAGE_ID;
}
namespace INF {
static const uint8_t ERROR = 0x00;
static const uint8_t WARNING = 0x01;
static const uint8_t NOTICE = 0x02;
static const uint8_t TEST = 0x03;
static const uint8_t DEBUG = 0x04;
}
namespace ACK {
static const uint8_t NACK = 0x00;
static const uint8_t ACK = 0x01;
}
namespace AID {
static const uint8_t ALM = AidALM::MESSAGE_ID;
static const uint8_t EPH = AidEPH::MESSAGE_ID;
static const uint8_t HUI = AidHUI::MESSAGE_ID;
}
namespace CFG {
static const uint8_t ANT = CfgANT::MESSAGE_ID;
static const uint8_t CFG = CfgCFG::MESSAGE_ID;
static const uint8_t DAT = CfgDAT::MESSAGE_ID;
static const uint8_t GNSS = CfgGNSS::MESSAGE_ID;
static const uint8_t HNR = CfgHNR::MESSAGE_ID;
static const uint8_t INF = CfgINF::MESSAGE_ID;
static const uint8_t DGNSS = CfgDGNSS::MESSAGE_ID;
static const uint8_t MSG = CfgMSG::MESSAGE_ID;
static const uint8_t NAV5 = CfgNAV5::MESSAGE_ID;
static const uint8_t NAVX5 = CfgNAVX5::MESSAGE_ID;
static const uint8_t NMEA = CfgNMEA::MESSAGE_ID;
static const uint8_t PRT = CfgPRT::MESSAGE_ID;
static const uint8_t RATE = CfgRATE::MESSAGE_ID;
static const uint8_t RST = CfgRST::MESSAGE_ID;
static const uint8_t SBAS = CfgSBAS::MESSAGE_ID;
static const uint8_t TMODE3 = CfgTMODE3::MESSAGE_ID;
static const uint8_t USB = CfgUSB::MESSAGE_ID;
}
namespace UPD {
//! SOS and SOS_Ack have the same message ID, but different lengths
static const uint8_t SOS = UpdSOS::MESSAGE_ID;
}
namespace MON {
static const uint8_t GNSS = MonGNSS::MESSAGE_ID;
static const uint8_t HW = MonHW::MESSAGE_ID;
static const uint8_t VER = MonVER::MESSAGE_ID;
}
namespace ESF {
static const uint8_t INS = EsfINS::MESSAGE_ID;
static const uint8_t MEAS = EsfMEAS::MESSAGE_ID;
static const uint8_t RAW = EsfRAW::MESSAGE_ID;
static const uint8_t STATUS = EsfSTATUS::MESSAGE_ID;
}
namespace MGA {
static const uint8_t GAL = MgaGAL::MESSAGE_ID;
}
namespace HNR {
static const uint8_t PVT = HnrPVT::MESSAGE_ID;
}
}
} //!< namespace ublox_msgs
#endif //!< UBLOX_MSGS_H

View File

@@ -0,0 +1,12 @@
# ACK (0x05)
# Message Acknowledged / Not-Acknowledged
#
# Output upon processing of an input message
#
uint8 CLASS_ID = 5
uint8 NACK_MESSAGE_ID = 0
uint8 ACK_MESSAGE_ID = 1
uint8 clsID # Class ID of the (Not-)Acknowledged Message
uint8 msgID # Message ID of the (Not-)Acknowledged Message

View File

@@ -0,0 +1,28 @@
# AID-ALM (0x0B 0x30)
# GPS Aiding Almanach Input/Output Message
#
# All UBX-AID messages are deprecated; use UBX-MGA messages instead
# - If the WEEK Value is 0, DWRD0 to DWRD7 are not sent as the almanach is not
# available for the given SV. This may happen even if NAV-SVINFO and RXM-SVSI
# are indicating almanac availability as the internal data may not represent
# the content of an original broadcast almanac (or only parts thereof).
# - DWORD0 to DWORD7 contain the 8 words following the Hand-Over Word ( HOW )
# from the GPS navigation message, either pages 1 to 24 of sub-frame 5 or
# pages 2 to 10 of subframe 4. See IS-GPS-200 for a full description of the
# contents of the Almanac pages.
# - In DWORD0 to DWORD7, the parity bits have been removed, and the 24 bits of
# data are located in Bits 0 to 23. Bits 24 to 31 shall be ignored.
# - Example: Parameter e (Eccentricity) from Almanach Subframe 4/5, Word 3,
# Bits 69-84 within the subframe can be found in DWRD0, Bits 15-0 whereas
# Bit 0 is the LSB.
uint8 CLASS_ID = 11
uint8 MESSAGE_ID = 48
uint32 svid # SV ID for which the receiver shall return its
# Almanac Data (Valid Range: 1 .. 32 or 51, 56, 63).
uint32 week # Issue Date of Almanach (GPS week number)
# Start of optional block
uint32[] dwrd # Almanach Words
# End of optional block

View File

@@ -0,0 +1,33 @@
# AID-EPH (0x0B 0x31)
# GPS Aiding Ephemeris Input/Output Message
#
# All UBX-AID messages are deprecated; use UBX-MGA messages instead
# - SF1D0 to SF3D7 is only sent if ephemeris is available for this SV. If not, the payload may
# be reduced to 8 Bytes, or all bytes are set to zero, indicating that this SV Number does
# not have valid ephemeris for the moment. This may happen even if NAV-SVINFO and
# RXM-SVSI are indicating ephemeris availability as the internal data may not represent the
# content of an original broadcast ephemeris (or only parts thereof).
# - SF1D0 to SF3D7 contain the 24 words following the Hand-Over Word ( HOW ) from the
# GPS navigation message, subframes 1 to 3. The Truncated TOW Count is not valid and
# cannot be used. See IS-GPS-200 for a full description of the contents of the Subframes.
# - In SF1D0 to SF3D7, the parity bits have been removed, and the 24 bits of data are
# located in Bits 0 to 23. Bits 24 to 31 shall be ignored.
# - When polled, the data contained in this message does not represent the full original
# ephemeris broadcast. Some fields that are irrelevant to u-blox receivers may be missing.
# The week number in Subframe 1 has already been modified to match the Time Of
# Ephemeris (TOE).
uint8 CLASS_ID = 11
uint8 MESSAGE_ID = 49
uint32 svid # SV ID for which this ephemeris data is
# (Valid Range: 1 .. 32).
uint32 how # Hand-Over Word of first Subframe. This is
# required if data is sent to the receiver.
# 0 indicates that no Ephemeris Data is following.
# Start of optional block
uint32[] sf1d # Subframe 1 Words 3..10 (SF1D0..SF1D7)
uint32[] sf2d # Subframe 2 Words 3..10 (SF2D0..SF2D7)
uint32[] sf3d # Subframe 3 Words 3..10 (SF3D0..SF3D7)
# End of optional block

View File

@@ -0,0 +1,35 @@
# AID-HUI (0x0B 0x02)
# GPS Health, UTC and ionosphere parameters
#
# All UBX-AID messages are deprecated; use UBX-MGA messages instead.
# This message contains a health bit mask, UTC time and Klobuchar parameters. For more
# information on these parameters, please see the ICD-GPS-200 documentation.
uint8 CLASS_ID = 11
uint8 MESSAGE_ID = 2
uint32 health # Bitmask, every bit represents a GPS SV (1-32).
# If the bit is set the SV is healthy.
float64 utcA0 # UTC - parameter A0
float64 utcA1 # UTC - parameter A1
int32 utcTOW # UTC - reference time of week
int16 utcWNT # UTC - reference week number
int16 utcLS # UTC - time difference due to leap seconds before event
int16 utcWNF # UTC - week number when next leap second event occurs
int16 utcDN # UTC - day of week when next leap second event occurs
int16 utcLSF # UTC - time difference due to leap seconds after event
int16 utcSpare # UTC - Spare to ensure structure is a multiple of 4
# bytes
float32 klobA0 # Klobuchar - alpha 0 [s]
float32 klobA1 # Klobuchar - alpha 1 [s/semicircle]
float32 klobA2 # Klobuchar - alpha 2 [s/semicircle^2]
float32 klobA3 # Klobuchar - alpha 3 [s/semicircle^3]
float32 klobB0 # Klobuchar - beta 0 [s]
float32 klobB1 # Klobuchar - beta 1 [s/semicircle]
float32 klobB2 # Klobuchar - beta 2 [s/semicircle^2]
float32 klobB3 # Klobuchar - beta 3 [s/semicircle^3]
uint32 flags # flags
uint32 FLAGS_HEALTH = 1 # Healthmask field in this message is valid
uint32 FLAGS_UTC = 2 # UTC parameter fields in this message are valid
uint32 FLAGS_KLOB = 4 # Klobuchar parameter fields in this message are
# valid

View File

@@ -0,0 +1,25 @@
# CFG-ANT (0x06 0x13)
# Antenna Control Settings
#
uint8 CLASS_ID = 6
uint8 MESSAGE_ID = 19
uint16 flags # Antenna Flag Mask
uint16 FLAGS_SVCS = 1 # Enable Antenna Supply Voltage Control Signal
uint16 FLAGS_SCD = 2 # Enable Short Circuit Detection
uint16 FLAGS_OCD = 4 # Enable Open Circuit Detection
uint16 FLAGS_PDWN_ON_SCD = 8 # Power Down Antenna supply if Short Circuit is
# detected. (only in combination with Bit 1)
uint16 FLAGS_RECOVERY = 16 # Enable automatic recovery from short state
uint16 pins # Antenna Pin Configuration
uint16 PIN_SWITCH_MASK = 31 # PIO-Pin used for switching antenna supply
# (internal to TIM-LP/TIM-LF)
uint16 PIN_SCD_MASK = 992 # PIO-Pin used for detecting a short in the
# antenna supply
uint16 PIN_OCD_MASK = 31744 # PIO-Pin used for detecting open/not connected
# antenna
uint16 PIN_RECONFIG = 32678 # if set to one, and this command is sent to the
# receiver, the receiver will reconfigure the
# pins as specified.

View File

@@ -0,0 +1,38 @@
# CFG-CFG (0x06 0x09)
# Clear, Save and Load configurations
#
uint8 CLASS_ID = 6
uint8 MESSAGE_ID = 9
uint32 clearMask # Mask with configuration sub-sections to Clear
# (=Load Default Configurations to Permanent
# Configurations in non-volatile memory)
uint32 saveMask # Mask with configuration sub-section to Save
# (=Save Current Configuration to Non-volatile
# Memory)
uint32 loadMask # Mask with configuration sub-sections to Load
# (=Load Permanent Configurations from
# Non-volatile Memory to Current Configurations)
uint32 MASK_IO_PORT = 1 # Communications port settings. Modifying this
# sub-section results in an IO system reset.
# Because of this undefined data may be output
# for a short period of time after receiving the
# message.
uint32 MASK_MSG_CONF = 2 # Message Configuration
uint32 MASK_INF_MSG = 4 # INF Message Configuration
uint32 MASK_NAV_CONF = 8 # Navigation Configuration
uint32 MASK_RXM_CONF = 16 # Receiver Manager Configuration
uint32 MASK_SEN_CONF = 256 # Sensor Interface Configuration, protocol >= 19
uint32 MASK_RINV_CONF = 512 # Remote Inventory Configuration
uint32 MASK_ANT_CONF = 1024 # Antenna Configuration
uint32 MASK_LOG_CONF = 2048 # Logging Configuration
uint32 MASK_FTS_CONF = 4096 # FTS Configuration. Only applicable to the
# FTS product variant.
uint8 deviceMask # Mask which selects the devices for this command
uint8 DEV_BBR = 1 # device battery backed RAM
uint8 DEV_FLASH = 2 # device Flash
uint8 DEV_EEPROM = 4 # device EEPROM
uint8 DEV_SPI_FLASH = 16 # device SPI Flash

View File

@@ -0,0 +1,37 @@
# CFG-DAT (0x06 0x06)
# Set User-defined Datum
#
# For more information see the description of Geodetic Systems and Frames.
#
uint8 CLASS_ID = 6
uint8 MESSAGE_ID = 6
# Only for GET, these values are not used for write
uint16 datumNum # Datum Number: 0 = WGS84, 0xFFFF = user-defined
uint16 DATUM_NUM_WGS84 = 0
uint16 DATUM_NUM_USER = 65535
uint8[6] datumName # ASCII String: WGS84 or USER
float64 majA # Semi-major Axis [m]
# accepted range = 6,300,000.0 to 6,500,000.0 meters
float64 flat # 1.0 / Flattening
# accepted range is 0.0 to 500.0
float32 dX # X Axis shift at the origin [m]
# accepted range is +/- 5000.0 meters
float32 dY # Y Axis shift at the origin [m]
# accepted range is +/- 5000.0 meters
float32 dZ # Z Axis shift at the origin [m]
# accepted range is +/- 5000.0 meters
float32 rotX # Rotation about the X Axis [s]
# accepted range is +/- 20.0 milli-arc seconds
float32 rotY # Rotation about the Y Axis [s]
# accepted range is +/- 20.0 milli-arc seconds
float32 rotZ # Rotation about the Z Axis [s]
# accepted range is +/- 20.0 milli-arc seconds
float32 scale # Scale change [ppm]
# accepted range is 0.0 to 50.0 parts per million

View File

@@ -0,0 +1,18 @@
# CFG-DGNSS (0x06 0x70)
# DGNSS configuration
#
# This message allows the user to configure the DGNSS configuration of the
# receiver.
# Supported on:
# - u-blox 8 / u-blox M8 from protocol version 20.01 up to version 23.01 (only
# with High Precision GNSS products)
uint8 CLASS_ID = 6
uint8 MESSAGE_ID = 112
uint8 dgnssMode # Specifies differential mode:
uint8 DGNSS_MODE_RTK_FLOAT = 2 # RTK float: No attempts are made to fix
# ambiguities.
uint8 DGNSS_MODE_RTK_FIXED = 3 # RTK fixed: Ambiguities are fixed whenever
# possible.
uint8[3] reserved0 # Reserved

View File

@@ -0,0 +1,44 @@
# CFG-GNSS (0x06 0x3E)
# GNSS Configuration
#
# Gets or sets the GNSS system channel sharing configuration.
# If the receiver is sent a valid new configuration, it will respond with a
# UBX-ACK-ACK message and immediately change to the new configuration. Otherwise
# the receiver will reject the request, by issuing a UBX-ACK-NAK and continuing
# operation with the previous configuration.
# Configuration requirements:
# - It is necessary for at least one major GNSS to be enabled, after applying
# the new configuration to the current one.
# - It is also required that at least 4 tracking channels are available to each
# enabled major GNSS, i.e. maxTrkCh must have a minimum value of 4 for each
# enabled major GNSS.
# - The number of tracking channels in use must not exceed the number of
# tracking channels available in hardware, and the sum of all reserved
# tracking channels needs to be less than or equal to the number of tracking
# channels in use.
# Notes:
# - To avoid cross-correlation issues, it is recommended that GPS and QZSS are
# always both enabled or both disabled.
# - Polling this message returns the configuration of all supported GNSS,
# whether enabled or not; it may also include GNSS unsupported by the
# particular product, but in such cases the enable flag will always be unset.
# - See section GNSS Configuration for a discussion of the use of this message
# and section Satellite Numbering for a description of the GNSS IDs available
# - Configuration specific to the GNSS system can be done via other messages
# (e.g. UBX-CFG-SBAS).
#
uint8 CLASS_ID = 6
uint8 MESSAGE_ID = 62
uint8 msgVer # Message version (= 0 for this version)
uint8 numTrkChHw # Number of tracking channels in hardware (read only)
uint8 numTrkChUse # (Read only in protocol versions greater than 23)
# Number of tracking channels to use (<= numTrkChHw)
# If 0xFF, then number of tracking channels to use will
# be set to numTrkChHw
uint8 numConfigBlocks # Number of configuration blocks following
# Start of repeated block (numConfigBlocks times)
CfgGNSS_Block[] blocks
# End of repeated block

View File

@@ -0,0 +1,54 @@
# see Cfg-GNSS message
#
uint8 gnssId # System identifier (see Satellite Numbering)
uint8 GNSS_ID_GPS = 0
uint8 GNSS_ID_SBAS = 1
uint8 GNSS_ID_GALILEO = 2
uint8 GNSS_ID_BEIDOU = 3
uint8 GNSS_ID_IMES = 4
uint8 GNSS_ID_QZSS = 5
uint8 GNSS_ID_GLONASS = 6
uint8 resTrkCh # (Read only in protocol versions greater than 23)
# Number of reserved (minimum) tracking channels
# for this GNSS system
uint8 RES_TRK_CH_GPS = 8
uint8 RES_TRK_CH_QZSS = 0
uint8 RES_TRK_CH_SBAS = 0
uint8 RES_TRK_CH_GLONASS = 8
uint8 maxTrkCh # (Read only in protocol versions greater than 23)
# Maximum number of tracking channels used for this
# system. Must be > 0, >= resTrkChn, <= numTrkChUse and
# <= maximum number of tracking channels supported for
# this system
uint8 MAX_TRK_CH_MAJOR_MIN = 4 # maxTrkCh must have this minimum value
# for each enabled major GNSS
uint8 MAX_TRK_CH_GPS = 16
uint8 MAX_TRK_CH_GLONASS = 14
uint8 MAX_TRK_CH_QZSS = 3
uint8 MAX_TRK_CH_SBAS = 3
uint8 reserved1 # Reserved
uint32 flags # Bitfield of flags. At least one signal must be
# configured in every enabled system.
uint32 FLAGS_ENABLE = 1 # Enable this system
uint32 FLAGS_SIG_CFG_MASK = 16711680 # Signal configuration mask
uint32 SIG_CFG_GPS_L1CA = 65536 # When gnssId is 0 (GPS)
# * 0x01 = GPS L1C/A
uint32 SIG_CFG_SBAS_L1CA = 65536 # When gnssId is 1 (SBAS)
# * 0x01 = SBAS L1C/A
uint32 SIG_CFG_GALILEO_E1OS = 65536 # When gnssId is 2 (Galileo)
# * 0x01 = Galileo E1OS (not supported in
# protocol versions less than 18)
uint32 SIG_CFG_BEIDOU_B1I = 65536 # When gnssId is 3 (BeiDou)
# * 0x01 = BeiDou B1I
uint32 SIG_CFG_IMES_L1 = 65536 # When gnssId is 4 (IMES)
# * 0x01 = IMES L1
uint32 SIG_CFG_QZSS_L1CA = 65536 # When gnssId is 5 (QZSS)
# * 0x01 = QZSS L1C/A
uint32 SIG_CFG_QZSS_L1SAIF = 262144 # * 0x04 = QZSS L1SAIF
uint32 SIG_CFG_GLONASS_L1OF = 65536 # When gnssId is 6 (GLONASS)
# * 0x01 = GLONASS L1OF

View File

@@ -0,0 +1,19 @@
# CFG-HNR (0x06 0x5C)
# High Navigation Rate Settings
#
# The u-blox receivers support high rates of navigation update up to 30 Hz.
# The navigation solution output (NAV-HNR) will not be aligned to the top of a
# second.
# The update rate has a direct influence on the power consumption. The more
# fixes that are required, the more CPU power and communication resources are
# required.
# For most applications a 1 Hz update rate would be sufficient.
#
# (only with ADR or UDR products)
#
uint8 CLASS_ID = 6
uint8 MESSAGE_ID = 92
uint8 highNavRate # Rate of navigation solution output [Hz]
uint8[3] reserved0 # Reserved

Some files were not shown because too many files have changed in this diff Show More