+
+
@@ -343,7 +461,7 @@
-
+
@@ -402,7 +520,9 @@
-
+
+
+
@@ -410,17 +530,59 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ground_station/Framework/LoggingSystems/Logger.py b/ground_station/Framework/LoggingSystems/Logger.py
new file mode 100644
index 0000000..bbb222a
--- /dev/null
+++ b/ground_station/Framework/LoggingSystems/Logger.py
@@ -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)
\ No newline at end of file
diff --git a/ground_station/Framework/LoggingSystems/__init__.py b/ground_station/Framework/LoggingSystems/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ground_station/Framework/VideoSystems/RoverVideoCoordinator.py b/ground_station/Framework/VideoSystems/RoverVideoCoordinator.py
index 24ef9c4..536ef6a 100644
--- a/ground_station/Framework/VideoSystems/RoverVideoCoordinator.py
+++ b/ground_station/Framework/VideoSystems/RoverVideoCoordinator.py
@@ -24,9 +24,9 @@ FONT = cv2.FONT_HERSHEY_TRIPLEX
#####################################
# RoverVideoReceiver Class Definition
#####################################
-class RoverVideoReceiver(QtCore.QThread):
+class RoverVideoCoordinator(QtCore.QThread):
def __init__(self, shared_objects):
- super(RoverVideoReceiver, self).__init__()
+ super(RoverVideoCoordinator, self).__init__()
# ########## Reference to class init variables ##########
self.shared_objects = shared_objects
@@ -47,12 +47,22 @@ class RoverVideoReceiver(QtCore.QThread):
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
diff --git a/ground_station/Framework/VideoSystems/RoverVideoReceiver.py b/ground_station/Framework/VideoSystems/RoverVideoReceiver.py
index 56b4ded..e3e8b18 100644
--- a/ground_station/Framework/VideoSystems/RoverVideoReceiver.py
+++ b/ground_station/Framework/VideoSystems/RoverVideoReceiver.py
@@ -50,12 +50,6 @@ class RoverVideoReceiver(QtCore.QThread):
# self.video_subscriber = rospy.Subscriber(self.topic_path, CompressedImage,
# self.__image_data_received_callback) # type: rospy.Subscriber
- topics = rospy.get_published_topics(self.topic_path)
-
- for group in topics:
- if "image_" in group[0]:
- print group[0]
-
self.subscription_queue_size = 10
# Steam name variable
@@ -103,7 +97,6 @@ class RoverVideoReceiver(QtCore.QThread):
self.image_ready_signal.emit()
self.new_frame = False
-
def __on_image_update_ready(self):
self.video_display_label.setPixmap(self.pixmap)
diff --git a/ground_station/RoverGroundStation.py b/ground_station/RoverGroundStation.py
index 4935951..1c2851e 100755
--- a/ground_station/RoverGroundStation.py
+++ b/ground_station/RoverGroundStation.py
@@ -10,6 +10,7 @@ import rospy
import qdarkstyle
# Custom Imports
+import Framework.LoggingSystems.Logger as Logger
import Framework.VideoSystems.RoverVideoCoordinator as RoverVideoCoordinator
#####################################
@@ -80,8 +81,10 @@ class GroundStation(QtCore.QObject):
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(
@@ -152,6 +155,10 @@ if __name__ == "__main__":
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()
application.exec_() # Execute launching of the application