mirror of
https://github.com/OSURoboticsClub/Rover_2017_2018.git
synced 2025-11-08 18:21:15 +00:00
Merge branch 'master' into system_statuses
This commit is contained in:
@@ -62,3 +62,71 @@ Where `descriptor` is either `RAW` or `SYS`. `voltage` is represented as shown i
|
||||
For example:
|
||||
|
||||

|
||||
|
||||
### Exporting your Project
|
||||
|
||||
#### Board Outline
|
||||
Ensure you have your board outline connector setup. You need an outline defined in the "Outline" layer (mechanical 1) as well as an exact copy on Mechanical 4 (per [CircuitMaker Fourm Post](https://circuitmaker.com/forum/posts/220409)).
|
||||
|
||||
We need both gerber files, and NC Drill files. Gerbers tell the manufacture where to put copper, silkscreen, etc, while the NC Drill files tell them where to drill. Your guess as to why they are different processes.
|
||||
|
||||
#### Outputting Gerbers
|
||||
|
||||
Make sure your file is 100% ready to go (do a final Design Rule Check), and then go to the output tab and select "Gerber". You will have to commit your project to export any manufacturing files.
|
||||
|
||||
Choose the following settings:
|
||||

|
||||

|
||||
|
||||
|
||||
Then hit OK, and save your project into the "Node Output Files" folder in the Google Drive (if outputting a node) under your folder's name.
|
||||
|
||||
#### Outputting NC Drill Files
|
||||
|
||||
Select "NC Drill Files" under the output menu. You will have to commit your project again.
|
||||
|
||||
Choose the following settings:
|
||||

|
||||
|
||||
Save this .zip in the same folder as the gerber ones.
|
||||
|
||||
#### Assembling your files for being sent to the manufacturer
|
||||
|
||||
Extract both of the .zip files into their own folders. We're looking to establish the following group of files:
|
||||
|
||||

|
||||
|
||||
Make a folder with a basic board name (e.g. "IrisBoard") that will hold your finalized board generation files. This will be your staging folder.
|
||||
|
||||
Grab the **.TXT** from the "\*\_NC\_Drill" folder, rename it "_boardname_.XLN" and move it into your staging folder.
|
||||
|
||||
Rename the **.GM4** file from the "\_Gerber" folder to "_boardname_.GKO" and move it to your staging folder.
|
||||
|
||||
From the same folder, move the following files into your staging folder:
|
||||
|
||||
* .GBL
|
||||
* .GBO
|
||||
* .GBS
|
||||
* .GTL
|
||||
* .GTO
|
||||
* .GTS
|
||||
|
||||
You should now have all the files from the picture above in your staging folder. Make a .zip of this folder. This folder is all you have to send to the manufacturer to make your board.
|
||||
|
||||
#### Verifying you've done this correctly
|
||||
|
||||
Upload your design to [OshPark.com](https://oshpark.com/) and make sure that they render it correctly. This is a great first pass indicator to make sure you've done this process correctly. PCBWAY will also check your boards, but this prevents some dumb mistakes in assemling your .zip file.
|
||||
|
||||
|
||||
#### Ordering your boards
|
||||
|
||||
Email the Team Lead with your .zip files, and he will place the order for you. Include the following information:
|
||||
|
||||
* Board dimensions in mm
|
||||
* Desired color for the board (if not Red for Rover)
|
||||
* Desired copper weight (1oz is the default, unless you have a reason for it to be different)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="2b03", ATTRS{
|
||||
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_gimbal"
|
||||
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"
|
||||
|
||||
2
ground_station/.idea/deployment.xml
generated
2
ground_station/.idea/deployment.xml
generated
@@ -5,7 +5,7 @@
|
||||
<paths name="ssh://rover@192.168.1.15:22/usr/bin/python">
|
||||
<serverdata>
|
||||
<mappings>
|
||||
<mapping deploy="/home/rover/ground_station" local="$PROJECT_DIR$" />
|
||||
<mapping deploy="/ground_station" local="$PROJECT_DIR$" />
|
||||
</mappings>
|
||||
</serverdata>
|
||||
</paths>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="useProjectProfile" value="false" />
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
2
ground_station/.idea/webServers.xml
generated
2
ground_station/.idea/webServers.xml
generated
@@ -3,7 +3,7 @@
|
||||
<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" accessType="SFTP">
|
||||
<fileTransfer host="192.168.1.15" port="22" rootFolder="/home/rover" accessType="SFTP">
|
||||
<option name="port" value="22" />
|
||||
</fileTransfer>
|
||||
</webServer>
|
||||
|
||||
286
ground_station/.idea/workspace.xml
generated
286
ground_station/.idea/workspace.xml
generated
@@ -2,6 +2,7 @@
|
||||
<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" />
|
||||
@@ -15,16 +16,75 @@
|
||||
<component name="CreatePatchCommitExecutor">
|
||||
<option name="PATCH_PATH" value="" />
|
||||
</component>
|
||||
<component name="DockManager">
|
||||
<window id="1">
|
||||
<content type="file-editors">
|
||||
<state>
|
||||
<leaf>
|
||||
<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="-888">
|
||||
<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#0#10#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<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="306">
|
||||
<caret line="50" column="113" selection-start-line="50" selection-start-column="113" selection-end-line="50" selection-end-column="113" />
|
||||
<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="RoverGroundStation.py" pinned="false" current-in-tab="true">
|
||||
<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="357">
|
||||
<caret line="84" column="25" lean-forward="false" selection-start-line="84" selection-start-column="25" selection-end-line="84" selection-end-column="25" />
|
||||
<state relative-caret-position="576">
|
||||
<caret line="86" column="110" selection-start-line="86" selection-start-column="110" selection-end-line="86" selection-end-column="110" />
|
||||
<folding>
|
||||
<element signature="e#260#270#0" expanded="true" />
|
||||
<element signature="e#132#142#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<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="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>
|
||||
</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="864">
|
||||
<caret line="63" column="25" selection-start-line="63" selection-start-column="25" selection-end-line="63" selection-end-column="25" />
|
||||
<folding>
|
||||
<element signature="e#110#152#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
@@ -32,10 +92,20 @@
|
||||
</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/VideoSystems/RoverVideoReceiver.py" />
|
||||
<option value="$PROJECT_DIR$/Framework/LoggingSystems/Logger.py" />
|
||||
<option value="$PROJECT_DIR$/RoverGroundStation.py" />
|
||||
<option value="$PROJECT_DIR$/Framework/VideoSystems/RoverVideoCoordinator.py" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
@@ -46,13 +116,21 @@
|
||||
<sorting>DEFINITION_ORDER</sorting>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds">
|
||||
<option name="x" value="55" />
|
||||
<option name="y" value="52" />
|
||||
<option name="width" value="1360" />
|
||||
<option name="height" value="1028" />
|
||||
<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 proportions="" version="1">
|
||||
<navigator currentView="ProjectPane" proportions="" version="1">
|
||||
<flattenPackages />
|
||||
<showMembers />
|
||||
<showModules />
|
||||
@@ -65,13 +143,87 @@
|
||||
<manualOrder />
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes />
|
||||
<panes>
|
||||
<pane id="Scratches" />
|
||||
<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="LoggingSystems" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope" />
|
||||
</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">
|
||||
@@ -94,12 +246,6 @@
|
||||
<option name="OPTIONS" value="" />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="JavaScriptTestRunnerProtractor" factoryName="Protractor">
|
||||
<config-file value="" />
|
||||
<node-interpreter value="project" />
|
||||
<envs />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="JavascriptDebugType" factoryName="JavaScript Debug">
|
||||
<method />
|
||||
</configuration>
|
||||
@@ -172,7 +318,7 @@
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="js.build_tools.npm" factoryName="npm">
|
||||
<command value="run" />
|
||||
<command value="run-script" />
|
||||
<scripts />
|
||||
<node-interpreter value="project" />
|
||||
<envs />
|
||||
@@ -306,28 +452,28 @@
|
||||
<servers />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="55" y="52" width="1360" height="1028" extended-state="4" />
|
||||
<editor active="false" />
|
||||
<frame x="0" y="0" 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="false" show_stripe_button="true" weight="0.13468939" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<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="false" show_stripe_button="true" weight="0.32908705" 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="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="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="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="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.18347639" sideWeight="0.49807587" order="7" 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="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="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="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="7" 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="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" />
|
||||
<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" />
|
||||
@@ -340,8 +486,8 @@
|
||||
<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.17918456" 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="true" show_stripe_button="true" weight="0.30439684" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<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" />
|
||||
@@ -354,6 +500,14 @@
|
||||
<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>
|
||||
@@ -365,37 +519,75 @@
|
||||
<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" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="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#260#270#0" expanded="true" />
|
||||
<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">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="471">
|
||||
<caret line="181" column="66" lean-forward="false" selection-start-line="181" selection-start-column="50" selection-end-line="181" selection-end-column="66" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.PyCharm2016.3/system/remote_sources/-1418177152/1376253408/rospy/topics.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-3777">
|
||||
<caret line="513" column="8" lean-forward="false" selection-start-line="513" selection-start-column="8" selection-end-line="513" selection-end-column="8" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/RoverGroundStation.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="357">
|
||||
<caret line="84" column="25" lean-forward="false" selection-start-line="84" selection-start-column="25" selection-end-line="84" selection-end-column="25" />
|
||||
<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#260#270#0" expanded="true" />
|
||||
<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://$PROJECT_DIR$/Framework/VideoSystems/RoverVideoReceiverOld.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-888">
|
||||
<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#0#10#0" expanded="true" />
|
||||
</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="306">
|
||||
<caret line="50" column="113" selection-start-line="50" selection-start-column="113" selection-end-line="50" selection-end-column="113" />
|
||||
<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$/RoverGroundStation.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="576">
|
||||
<caret line="86" column="110" selection-start-line="86" selection-start-column="110" selection-end-line="86" selection-end-column="110" />
|
||||
<folding>
|
||||
<element signature="e#132#142#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="864">
|
||||
<caret line="63" column="25" selection-start-line="63" selection-start-column="25" selection-end-line="63" selection-end-column="25" />
|
||||
<folding>
|
||||
<element signature="e#110#152#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
<component name="webServersAuthStorage">
|
||||
<data>AAAAsC92Kuu3oLrABnhEDJd2fqLpSLKMDnz1RoGljcqcyx6rWWvT/BV+wcLNHGnvYk97nqnk/pKm4cGIiar9MRU3nZkNwyjJxPVtt3haC8iDCZdLJZ6CmktPYqrohRIav09rau96cPFO/I//1EIneIP/1ljcNiibrP6ukAATwUH19NLQaGz1/EYXXVq+qowSGeFE7dAFp107pLkmub5CsKj/8zF+PCqHoF8AEDn937Vn/JpXGWVGlieBMxMrucAQD8JqIA==</data>
|
||||
</component>
|
||||
</project>
|
||||
50
ground_station/Framework/DriveSystems/RoverDriveSender.py
Normal file
50
ground_station/Framework/DriveSystems/RoverDriveSender.py
Normal 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
|
||||
0
ground_station/Framework/DriveSystems/__init__.py
Normal file
0
ground_station/Framework/DriveSystems/__init__.py
Normal file
127
ground_station/Framework/LoggingSystems/Logger.py
Normal file
127
ground_station/Framework/LoggingSystems/Logger.py
Normal 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)
|
||||
0
ground_station/Framework/LoggingSystems/__init__.py
Normal file
0
ground_station/Framework/LoggingSystems/__init__.py
Normal file
@@ -0,0 +1,75 @@
|
||||
#####################################
|
||||
# Imports
|
||||
#####################################
|
||||
# Python native imports
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
import logging
|
||||
import cv2
|
||||
import numpy as np
|
||||
import qimage2ndarray
|
||||
import pprint
|
||||
|
||||
import rospy
|
||||
from cv_bridge import CvBridge
|
||||
from sensor_msgs.msg import CompressedImage
|
||||
|
||||
# Custom Imports
|
||||
|
||||
#####################################
|
||||
# Global Variables
|
||||
#####################################
|
||||
FONT = cv2.FONT_HERSHEY_TRIPLEX
|
||||
|
||||
|
||||
#####################################
|
||||
# RoverVideoReceiver Class Definition
|
||||
#####################################
|
||||
class RoverVideoCoordinator(QtCore.QThread):
|
||||
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.primary_video_display_label = self.right_screen.secondary_video_label # type:QtWidgets.QLabel
|
||||
self.primary_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
|
||||
|
||||
def run(self):
|
||||
self.logger.debug("Starting Video Coordinator Thread")
|
||||
|
||||
topics = rospy.get_published_topics("/cameras")
|
||||
|
||||
for group in topics:
|
||||
main_topic = group[0]
|
||||
last_section_topic = main_topic.split("/")[-1]
|
||||
if "image_" in main_topic and "zed" not in main_topic and last_section_topic == "compressed" :
|
||||
print group[0]
|
||||
|
||||
while self.run_thread_flag:
|
||||
|
||||
self.msleep(100)
|
||||
|
||||
self.logger.debug("Stopping Video Coordinator Thread")
|
||||
|
||||
def _get_cameras(self):
|
||||
|
||||
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
|
||||
129
ground_station/Framework/VideoSystems/RoverVideoReceiver.py
Normal file
129
ground_station/Framework/VideoSystems/RoverVideoReceiver.py
Normal file
@@ -0,0 +1,129 @@
|
||||
#####################################
|
||||
# Imports
|
||||
#####################################
|
||||
# Python native imports
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
import logging
|
||||
import cv2
|
||||
import numpy as np
|
||||
import qimage2ndarray
|
||||
import pprint
|
||||
|
||||
import rospy
|
||||
from cv_bridge import CvBridge
|
||||
from sensor_msgs.msg import CompressedImage
|
||||
|
||||
# Custom Imports
|
||||
|
||||
#####################################
|
||||
# Global Variables
|
||||
#####################################
|
||||
FONT = cv2.FONT_HERSHEY_TRIPLEX
|
||||
|
||||
|
||||
#####################################
|
||||
# RoverVideoReceiver Class Definition
|
||||
#####################################
|
||||
class RoverVideoReceiver(QtCore.QThread):
|
||||
publish_message_signal = QtCore.pyqtSignal()
|
||||
image_ready_signal = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, shared_objects, video_display_label, topic_path):
|
||||
super(RoverVideoReceiver, self).__init__()
|
||||
|
||||
# ########## Reference to class init variables ##########
|
||||
self.shared_objects = shared_objects
|
||||
self.video_display_label = video_display_label # type:QtWidgets.QLabel
|
||||
self.topic_path = topic_path
|
||||
|
||||
# ########## 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 ##########
|
||||
# Subscription variables
|
||||
# self.video_subscriber = rospy.Subscriber(self.topic_path, CompressedImage,
|
||||
# self.__image_data_received_callback) # type: rospy.Subscriber
|
||||
|
||||
self.subscription_queue_size = 10
|
||||
|
||||
# Steam name variable
|
||||
self.video_name = self.topic_path.split("/")[2].replace("_", " ").title()
|
||||
|
||||
# Image variables
|
||||
self.raw_image = None
|
||||
self.opencv_image = None
|
||||
self.pixmap = None
|
||||
|
||||
# Processing variables
|
||||
self.bridge = CvBridge() # OpenCV ROS Video Data Processor
|
||||
self.video_enabled = False
|
||||
self.new_frame = False
|
||||
|
||||
# Assign local callbacks
|
||||
self.__set_local_callbacks()
|
||||
|
||||
def run(self):
|
||||
self.logger.debug("Starting \"%s\" Thread")
|
||||
|
||||
while self.run_thread_flag:
|
||||
if self.video_enabled:
|
||||
self.__show_video_enabled()
|
||||
else:
|
||||
self.__show_video_disabled()
|
||||
|
||||
self.msleep(18)
|
||||
|
||||
self.logger.debug("Stopping \"%s\" Thread")
|
||||
|
||||
def __show_video_enabled(self):
|
||||
if self.new_frame:
|
||||
self.opencv_image = self.bridge.compressed_imgmsg_to_cv2(self.raw_image, "rgb8")
|
||||
self.opencv_image = cv2.resize(self.opencv_image, (1280, 720))
|
||||
self.pixmap = QtGui.QPixmap.fromImage(qimage2ndarray.array2qimage(self.opencv_image))
|
||||
self.image_ready_signal.emit()
|
||||
self.new_frame = False
|
||||
|
||||
def __show_video_disabled(self):
|
||||
if self.new_frame:
|
||||
fps_image = np.zeros((720, 1280, 3), np.uint8)
|
||||
|
||||
self.pixmap = QtGui.QPixmap.fromImage(qimage2ndarray.array2qimage(fps_image))
|
||||
self.image_ready_signal.emit()
|
||||
self.new_frame = False
|
||||
|
||||
def __on_image_update_ready(self):
|
||||
self.video_display_label.setPixmap(self.pixmap)
|
||||
|
||||
def __image_data_received_callback(self, raw_image):
|
||||
self.raw_image = raw_image
|
||||
self.new_frame = True
|
||||
|
||||
def __set_local_callbacks(self):
|
||||
self.video_display_label.mouseDoubleClickEvent = self.toggle_video_display
|
||||
|
||||
def toggle_video_display(self, _):
|
||||
if self.video_enabled:
|
||||
self.video_subscriber.unregister()
|
||||
self.new_frame = True
|
||||
self.video_enabled = False
|
||||
else:
|
||||
self.video_subscriber = rospy.Subscriber(self.topic_path, CompressedImage,
|
||||
self.__image_data_received_callback)
|
||||
self.video_enabled = True
|
||||
|
||||
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.run_thread_flag = False
|
||||
134
ground_station/Framework/VideoSystems/RoverVideoReceiverOld.py
Normal file
134
ground_station/Framework/VideoSystems/RoverVideoReceiverOld.py
Normal 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
|
||||
0
ground_station/Framework/VideoSystems/__init__.py
Normal file
0
ground_station/Framework/VideoSystems/__init__.py
Normal file
0
ground_station/Framework/__init__.py
Normal file
0
ground_station/Framework/__init__.py
Normal file
246
ground_station/Resources/Ui/left_screen.ui
Normal file
246
ground_station/Resources/Ui/left_screen.ui
Normal 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>
|
||||
236
ground_station/Resources/Ui/right_screen.ui
Normal file
236
ground_station/Resources/Ui/right_screen.ui
Normal 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>
|
||||
@@ -1,10 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Main file used to launch the Rover Base Station
|
||||
No other files should be used for launching this application.
|
||||
"""
|
||||
|
||||
#####################################
|
||||
# Imports
|
||||
#####################################
|
||||
@@ -13,190 +7,29 @@ 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
|
||||
import qdarkstyle
|
||||
|
||||
from geometry_msgs.msg import Twist
|
||||
from sensor_msgs.msg import CompressedImage
|
||||
#from sensor_msgs.msg import Image, CompressedImage
|
||||
# Custom Imports
|
||||
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"
|
||||
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"
|
||||
|
||||
|
||||
class VideoTest(QtCore.QThread):
|
||||
ROS_CORE_COMMAND = ["roscore"]
|
||||
|
||||
publish_message_signal = QtCore.pyqtSignal()
|
||||
image_ready_signal = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, screen_label, video_size=None, sub_path=None):
|
||||
super(VideoTest, self).__init__()
|
||||
|
||||
self.not_abort = True
|
||||
|
||||
self.right_screen_label = screen_label # type: QtGui.QPixmap
|
||||
self.video_size = video_size
|
||||
|
||||
#rospy.init_node("video_test")
|
||||
|
||||
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.image_ready_signal.connect(self.__on_image_update_ready)
|
||||
|
||||
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 setup_start_and_kill_signals(self, start_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
|
||||
|
||||
|
||||
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, 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
|
||||
# "run (if there)" - personal pref
|
||||
|
||||
|
||||
#####################################
|
||||
@@ -223,47 +56,73 @@ class GroundStation(QtCore.QObject):
|
||||
RIGHT_SCREEN_ID = 1
|
||||
|
||||
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)
|
||||
|
||||
# self.left_screen = self.create_application_window(UI_FILE_LEFT, "Rover Ground Station Left Screen",
|
||||
# self.LEFT_SCREEN_ID) # type: ApplicationWindow
|
||||
self.right_screen = self.create_application_window(UI_FILE_RIGHT, "Rover Ground Station Right Screen",
|
||||
self.LEFT_SCREEN_ID) # type: ApplicationWindow
|
||||
rospy.init_node("ground_station")
|
||||
|
||||
# Start ROSCORE
|
||||
self.video_test = VideoTest(self.right_screen.primary_video_label, (1280, 720), sub_path="/cameras/main_navigation/image_640x360/compressed")
|
||||
self.video_test_1 = VideoTest(self.right_screen.secondary_video_label, (640, 360), sub_path="/cameras/chassis/image_640x360/compressed")
|
||||
self.video_test_2 = VideoTest(self.right_screen.tertiary_video_label, (640, 360), sub_path="/cameras/undercarriage/image_640x360/compressed")
|
||||
self.drive_test = DriveTest()
|
||||
self.shared_objects = {
|
||||
"screens": {},
|
||||
"regular_classes": {},
|
||||
"threaded_classes": {}
|
||||
}
|
||||
|
||||
# Keep track of all threads
|
||||
self.threads = []
|
||||
self.threads.append(self.drive_test)
|
||||
self.threads.append(self.video_test)
|
||||
self.threads.append(self.video_test_1)
|
||||
self.threads.append(self.video_test_2)
|
||||
# ###### 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
|
||||
|
||||
# Connect signals
|
||||
for thread in self.threads:
|
||||
thread.setup_start_and_kill_signals(self.start_threads_signal, self.kill_threads_signal)
|
||||
self.shared_objects["screens"]["right_screen"] = \
|
||||
self.create_application_window(UI_FILE_RIGHT, "Rover Ground Station Right Screen",
|
||||
self.RIGHT_SCREEN_ID) # type: ApplicationWindow
|
||||
|
||||
# ##### Instantiate Simple Classes #####
|
||||
self.logger_setup_class = Logger.Logger(console_output=True) # Doesn't need to be shared
|
||||
|
||||
# ##### Instantiate Threaded Classes #####
|
||||
self.__add_thread("Video Coordinator", RoverVideoCoordinator.RoverVideoCoordinator(self.shared_objects))
|
||||
|
||||
# self.__add_thread("Primary Video",
|
||||
# RoverVideoReceiver.RoverVideoReceiver(
|
||||
# self.shared_objects,
|
||||
# self.shared_objects["screens"]["right_screen"].primary_video_label,
|
||||
# "/cameras/main_navigation/"))
|
||||
# self.__add_thread("Secondary Video",
|
||||
# RoverVideoReceiverOld.VideoTest(
|
||||
# self.shared_objects,
|
||||
# self.shared_objects["screens"]["right_screen"].secondary_video_label,
|
||||
# (640, 360),
|
||||
# sub_path="/cameras/chassis/image_640x360/compressed"))
|
||||
# self.__add_thread("Tertiary Video",
|
||||
# RoverVideoReceiverOld.VideoTest(
|
||||
# self.shared_objects,
|
||||
# self.shared_objects["screens"]["right_screen"].tertiary_video_label,
|
||||
# (640, 360),
|
||||
# sub_path="/cameras/undercarriage/image_640x360/compressed"))
|
||||
|
||||
self.connect_signals_and_slots_signal.emit()
|
||||
self.__connect_signals_to_slots()
|
||||
self.start_threads_signal.emit()
|
||||
|
||||
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.left_screen.exit_requested_signal.connect(self.on_exit_requested__slot)
|
||||
self.right_screen.exit_requested_signal.connect(self.on_exit_requested__slot)
|
||||
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.threads:
|
||||
thread.wait()
|
||||
for thread in self.threads["threaded_classes"]:
|
||||
self.threads["threaded_classes"][thread].wait()
|
||||
|
||||
QtGui.QGuiApplication.exit()
|
||||
|
||||
@@ -294,6 +153,11 @@ 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 ase qt gui application
|
||||
application.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
|
||||
|
||||
QtCore.QCoreApplication.setOrganizationName("OSURC")
|
||||
QtCore.QCoreApplication.setOrganizationDomain("http://osurobotics.club/")
|
||||
QtCore.QCoreApplication.setApplicationName("groundstation")
|
||||
|
||||
ground_station = GroundStation()
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
<?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>
|
||||
@@ -1,149 +0,0 @@
|
||||
<?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="QGridLayout" name="gridLayout">
|
||||
<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>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<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 row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<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>
|
||||
<item row="0" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -16,6 +16,8 @@ int main(int argc, char** argv)
|
||||
|
||||
int large_image_width;
|
||||
int large_image_height;
|
||||
int medium_image_width;
|
||||
int medium_image_height;
|
||||
int small_image_width;
|
||||
int small_image_height;
|
||||
|
||||
@@ -27,8 +29,10 @@ int main(int argc, char** argv)
|
||||
|
||||
node_handle.param("large_image_width", large_image_width, 1280);
|
||||
node_handle.param("large_image_height", large_image_height, 720);
|
||||
node_handle.param("small_image_width", small_image_width, 640);
|
||||
node_handle.param("small_image_height", small_image_height, 360);
|
||||
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);
|
||||
|
||||
@@ -42,32 +46,38 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
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 full_res_image_transport(node_handle);
|
||||
image_transport::ImageTransport lower_res_image_transport(node_handle);
|
||||
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 full_size_publisher = full_res_image_transport.advertise(large_image_node_name, 1);
|
||||
image_transport::Publisher lower_size_publisher = lower_res_image_transport.advertise(small_image_node_name, 1);
|
||||
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;
|
||||
cv::Mat image_smaller;
|
||||
|
||||
ros::Rate loop_rate(fps + 5);
|
||||
cv::Mat image_large;
|
||||
cv::Mat image_medium;
|
||||
cv::Mat image_small;
|
||||
|
||||
ros::Rate loop_rate(fps + 2);
|
||||
|
||||
while (ros::ok()) {
|
||||
|
||||
cap.read(image);
|
||||
cap.read(image_large);
|
||||
|
||||
if(!image.empty()){
|
||||
cv::resize(image, image_smaller, cv::Size(small_image_width, small_image_height));
|
||||
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 full_res_message = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();
|
||||
sensor_msgs::ImagePtr lower_res_message = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image_smaller).toImageMsg();
|
||||
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();
|
||||
|
||||
full_size_publisher.publish(full_res_message);
|
||||
lower_size_publisher.publish(lower_res_message);
|
||||
large_image_publisher.publish(large_image_message);
|
||||
medium_image_publisher.publish(medium_image_message);
|
||||
small_image_publisher.publish(small_image_message);
|
||||
}
|
||||
|
||||
ros::spinOnce();
|
||||
|
||||
Reference in New Issue
Block a user