Skip to content

Commit

Permalink
Fully implemented small zone functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
nluzod committed Jul 15, 2013
1 parent ebd44fa commit 22a7935
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 65 deletions.
96 changes: 52 additions & 44 deletions display/gui/tkinter_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
ALERT_DURATION = 5

LOGGER_WIDTH = 49
PAD_MENU = 85
PAD_MENU = 83

COLOR_LIGHT = '#4E4D4A'
COLOR_DARK = '#353432'
Expand All @@ -43,17 +43,18 @@ def __init__(self, name, image_processors={}):
self.frame.grid(rowspan=3, sticky=(tk.N, tk.S))

### Top Frame
self.top_frame = TopFrame(self.frame, bg=COLOR_DARK, padx=10, pady=10)
self.top_frame = TopFrame(self.frame, self, image_processors,
bg=COLOR_DARK, padx=0, pady=5)

### Bottom Frame
self.bot_frame = BotFrame(self.frame, self, image_processors,
bg=COLOR_LIGHT, padx=10, pady=0)
bg=COLOR_DARK, padx=0, pady=0)
self.bot_frame.addViewports()

# Grid Frames
self.top_frame.grid(row=0, column=0)
# self.mid_frame.grid(row=1, column=0)
self.bot_frame.grid(row=2, column=0, pady=(0, 10))
self.bot_frame.grid(row=2, column=0, pady=(0, 5))


self.root.bind("<Escape>", lambda e: e.widget.quit())
Expand Down Expand Up @@ -235,11 +236,11 @@ def __init__(self, root):
def createItems(self):

self.label_text = tk.StringVar()
font = tkFont.Font(family="Arial", size=12)
font = tkFont.Font(family="Verdana", size=12, weight='bold')

# Alert label
alert_label = tk.Label(self.root, font=font,
textvariable=self.label_text, bg=COLOR_LIGHT)
textvariable=self.label_text, bg=COLOR_LIGHT, pady=5)
alert_label.grid(row=0, column=0, columnspan=2, sticky=(tk.W+tk.E))

# Set scrollbar
Expand Down Expand Up @@ -340,8 +341,11 @@ def apply(self):

class TopFrame(tk.Frame):

def __init__(self, parent, **options):
def __init__(self, parent, ui, image_processors, **options):
tk.Frame.__init__(self, parent, options)
self.parent = parent
self.ui = ui
self.image_processors = image_processors
self.bg = self.cget('bg')

self.menu_main = None
Expand All @@ -353,15 +357,15 @@ def __init__(self, parent, **options):
def createItems(self):

# Main menu frame
self.menu_main = MenuMain(self, bg=self.bg, highlightthickness=0)
self.menu_main = MenuMain(self, self.ui, self.image_processors, bg=self.bg, highlightthickness=0)
self.menu_main.pack(side=tk.LEFT, padx=PAD_MENU, fill=tk.X, expand=1)

# Tactical frame
self.tactical_frame = tk.Frame(self, bg=self.bg)
self.tactical_frame.pack(side=tk.LEFT, padx=0, fill=tk.BOTH, expand=1)

# Calibration menu frame
self.menu_cal = MenuCal(self, bg=self.bg, highlightthickness=0)
self.menu_cal = MenuCal(self, self.ui, self.image_processors, bg=self.bg, highlightthickness=0)
self.menu_cal.pack(side=tk.LEFT, padx=PAD_MENU, fill=tk.X, expand=1)

class BotFrame(tk.Frame):
Expand Down Expand Up @@ -416,7 +420,7 @@ def createCalLabels(self):
# Frame for alert info label
frame = tk.Frame(self, padx=0, pady=0, bg=self.bg)
self.label_alert = tk.Label(frame, text="Alert Messages",
font=("Verdana", 21, "bold"),
font=("Verdana", 16, "bold"),
bg=self.bg_light, fg="#353432")
self.label_alert.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
frame.grid(row=0, column=1, sticky=(tk.W + tk.E))
Expand All @@ -440,64 +444,68 @@ def update(self):

class MenuCal(tk.Frame):

def __init__(self, parent, **options):
def __init__(self, parent, ui, image_processors, **options):

tk.Frame.__init__(self, parent, options)
self.parent = parent
self.ui = ui
self.image_processors = image_processors
self.method = None
self.size = None
self.zone = None

# Build Menu Interface
self.createItems()

def createItems(self):

# Calibrate Button
tk.Button(self, text="Calibrate\nSystem", font=("Verdana", 12, "bold"),
pady=10, padx=2, bg='green', relief=tk.FLAT,
command=self.callbackCalibrate).pack(side=tk.TOP, pady=10)

# Simple separator (Horizontal)
separator = tk.Frame(self, width=2, height=2, bd=1, relief=tk.FLAT)
separator.pack(side=tk.TOP, pady=10, padx=5, fill=tk.X)

# Calibration Method
tk.Label(self, text="Calibration\nMethod", font=("Verdana", 10, "bold"), bg=COLOR_LIGHT).pack(side=tk.TOP, fill=tk.X)
self.method = MultiRadio(self,
text=("Point", "Color"), value=("POINT", "COLOR"),
callback=self.callbackCalibrate,
side=tk.TOP, fill=tk.X).pack(fill=tk.X, side=tk.TOP)

# Simple separator (Horizontal)
separator = tk.Frame(self, width=2, height=2, bd=1, relief=tk.FLAT)
separator.pack(side=tk.TOP, pady=10, padx=5, fill=tk.X)
# # Calibrate Button
# tk.Button(self, text="Calibrate\nSystem", font=("Verdana", 12, "bold"),
# pady=10, padx=2, bg='green', relief=tk.FLAT,
# command=self.callbackCalibrate).pack(side=tk.TOP, pady=10)
#
# # Simple separator (Horizontal)
# separator = tk.Frame(self, width=2, height=2, bd=1, relief=tk.FLAT)
# separator.pack(side=tk.TOP, pady=10, padx=5, fill=tk.X)
#
# # Calibration Method
# tk.Label(self, text="Calibration\nMethod", font=("Verdana", 10, "bold"), bg=COLOR_LIGHT).pack(side=tk.TOP, fill=tk.X)
# self.method = MultiRadio(self,
# text=("Point", "Color"), value=("POINT", "COLOR"),
# callback=self.callbackCalibrate,
# side=tk.TOP, fill=tk.X).pack(fill=tk.X, side=tk.TOP)
#
# # Simple separator (Horizontal)
# separator = tk.Frame(self, width=2, height=2, bd=1, relief=tk.FLAT)
# separator.pack(side=tk.TOP, pady=10, padx=5, fill=tk.X)

# Zone Type
tk.Label(self, text="Zone Type", font=("Verdana", 10, "bold"), bg=COLOR_LIGHT).pack(side=tk.TOP, fill=tk.X)
self.size = MultiRadio(self,
self.zone = MultiRadio(self,
text=("Normal", "Small"), value=("NORMAL", "SMALL"),
callback=self.callbackSetZone,
side=tk.TOP, fill=tk.X).pack(fill=tk.X, side=tk.TOP)
side=tk.TOP, fill=tk.X)
self.zone.pack(fill=tk.X, side=tk.TOP)

def callbackCalibrate(self):
if self.method.variable == "POINT":
pass
else:
pass
# def callbackCalibrate(self):
# if self.method.variable == "POINT":
# pass
# else:
# pass

def callbackSetZone(self):
if self.zone.variable == "NORMAL":
pass
else:
pass

# Set zone distances
for img_proc in self.image_processors:
img_proc.scm.setCalibrationDistances(self.zone.variable.get())

logging.debug('setting zone distances %s' % self.zone.variable.get())

class MenuMain(tk.Frame):

def __init__(self, parent, **options):
def __init__(self, parent, ui, image_processors, **options):

tk.Frame.__init__(self, parent, options)
self.parent = parent
self.ui = ui
self.power = False
self.text_power = tk.StringVar()
self.button_power = None
Expand Down
10 changes: 6 additions & 4 deletions display/tactical/tactical.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,21 @@ def update(self):
#continue

self.displayTarget(target)

zone_distances = self.data_proc.tca.image_processors[0].scm.getCalibrationDistances()

# Display alerts
if distance((0, 0), target.pos) < 4.8:
if distance((0, 0), target.pos) < zone_distances[0] - 0.2:
target.left_safe = False
if distance((0, 0), target.pos) < 9.8:
if distance((0, 0), target.pos) < zone_distances[1] - 0.2:
target.left_alert = False

if distance((0, 0), target.pos) >= 10 and target.left_alert == False:
if distance((0, 0), target.pos) >= zone_distances[1] and target.left_alert == False:
self.data_proc.tca.ui.displayAlert("Target has left the ALERT zone!!!")
self.data_proc.tca.ui.logAlert("Target has left the ALERT zone!!!")
target.left_alert = True
target.left_safe = True
elif distance((0, 0), target.pos) >= 5 and target.left_safe == False:
elif distance((0, 0), target.pos) >= zone_distances[0] and target.left_safe == False:
self.data_proc.tca.ui.displayAlert("Target has entered the ALERT zone!!!")
self.data_proc.tca.ui.logAlert("Target has entered the ALERT zone!!!")
target.left_safe = True
Expand Down
23 changes: 15 additions & 8 deletions processors/data/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from display.tactical.tactical import PERSIST_TIME, MAXLEN_DEQUE
import prediction
from processors.image.calibration import DISTANCES_NORMAL, DISTANCES_SMALL

ORIGIN = [0, 0]

Expand All @@ -20,8 +19,9 @@ class Target(object):
SAFE_RADIUS = 5
TURN_THRESHOLD_DEGREES = 4

def __init__(self, pos, config=None):
def __init__(self, pos, config=None, ttm=None):
self.pos = pos
self.ttm = ttm
self.kalman = None
self.prediction = None
self.missed_updates = 0
Expand All @@ -48,12 +48,15 @@ def __init__(self, pos, config=None):
Target.TIME_STEP = config.getfloat('track', 'time_step')
Target.PREDICTION_RADIUS = config.getfloat('track', 'prediction_radius')
Target.TURN_THRESHOLD_DEGREES = config.getfloat('track', 'turn_threshold')
if config.get('calibration', 'zone_size') == 'NORMAL':
Target.PREDICTION_RADIUS = DISTANCES_NORMAL[2]
Target.SAFE_RADIUS = DISTANCES_NORMAL[1]
elif config.get('calibration', 'zone_size') == 'SMALL':
Target.PREDICTION_RADIUS = DISTANCES_SMALL[2]
Target.SAFE_RADIUS = DISTANCES_SMALL[1]
zone_distances = self.ttm.data_processor.tca.image_processors[0].scm.getCalibrationDistances()
Target.PREDICTION_RADIUS = zone_distances[2]
Target.SAFE_RADIUS = zone_distances[1]
# if config.get('calibration', 'zone_size') == 'NORMAL':
# Target.PREDICTION_RADIUS = DISTANCES_NORMAL[2]
# Target.SAFE_RADIUS = DISTANCES_NORMAL[1]
# elif config.get('calibration', 'zone_size') == 'SMALL':
# Target.PREDICTION_RADIUS = DISTANCES_SMALL[2]
# Target.SAFE_RADIUS = DISTANCES_SMALL[1]

def update(self, pos):

Expand Down Expand Up @@ -82,6 +85,10 @@ def update(self, pos):

self.kal_pred = cv.KalmanPredict(self.kalman)
self.prediction = [self.kal_pred[0, 0], self.kal_pred[1, 0]]

zone_distances = self.ttm.data_processor.tca.image_processors[0].scm.getCalibrationDistances()
Target.PREDICTION_RADIUS = zone_distances[2]
Target.SAFE_RADIUS = zone_distances[1]

if self.valid:
# Calculate prediction line when target is located in alert zone
Expand Down
7 changes: 4 additions & 3 deletions processors/data/track.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ class TargetTrackModule(object):
UNKNOWN_GATE = 1.5
CONSTANTS_SET = False

def __init__(self, dataProcessor):
def __init__(self, data_processor):
self.targets = []
self.config = dataProcessor.config
self.data_processor = data_processor
self.config = data_processor.config
if (TargetTrackModule.CONSTANTS_SET is False and
self.config is not None):
TargetTrackModule.CONSTANTS_SET = True
Expand Down Expand Up @@ -66,7 +67,7 @@ def processDetections(self, unmatchedList):
for pos in unmatchedList:
logging.debug("New Target:")
logging.debug(pos)
self.targets.append(Target(pos, self.config))
self.targets.append(Target(pos, self.config, self))

def associateTrack(self, pos, target):
# TODO reimplement
Expand Down
21 changes: 15 additions & 6 deletions processors/image/calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class SourceCalibrationModule(object):

CAL_THRESHOLDS = CalibrationThreshold()
DISPLAY_COLORS = False, False
ZONE_DISTANCES = []

def __init__(self, image_processor):
self.image_processor = image_processor
Expand All @@ -117,9 +118,6 @@ def __init__(self, image_processor):
side_thresh_max = np.array(self.config.get
('calibration', 'side_color_max').
split(','), np.uint8)

# self.colors = [[center_thresh_min, center_thresh_max],
# [side_thresh_min, side_thresh_max]]

# Initialize calibration colors to those in config file
# This is no longer needed, but must initialize to something
Expand All @@ -139,9 +137,9 @@ def __init__(self, image_processor):

# Set calibration target distances
if self.config.get('calibration', 'zone_size') == 'NORMAL':
self.setCalibrationDistances(DISTANCES_NORMAL)
self.setCalibrationDistances('NORMAL')
elif self.config.get('calibration', 'zone_size') == 'SMALL':
self.setCalibrationDistances(DISTANCES_SMALL)
self.setCalibrationDistances('SMALL')

def calibrate(self, cal_points=None):
"""Calibrates the image processor
Expand Down Expand Up @@ -366,13 +364,19 @@ def getDisplayColors(self):

return SourceCalibrationModule.DISPLAY_COLORS

def setCalibrationDistances(self, zone_distances=(5, 10, 12)):
def setCalibrationDistances(self, zone_type='NORMAL'):
""" Sets Distances for safe, alert, and prediction zone boundaries
Arguments:
zone_size -- Three element iterable containing boundary lengths
"""
if zone_type == 'NORMAL':
zone_distances = DISTANCES_NORMAL
else:
zone_distances = DISTANCES_SMALL

SourceCalibrationModule.ZONE_DISTANCES = zone_distances

# Calibration point position calculations
DISTANCES = [distance * SCALE for distance in zone_distances]
Expand All @@ -383,6 +387,11 @@ def setCalibrationDistances(self, zone_distances=(5, 10, 12)):
self.center_points = [[distance * coordinate for coordinate in CENTER_POINTS]
for distance in DISTANCES]
self.left_points = [[-1 * x, y, z] for x, y, z in self.right_points]

def getCalibrationDistances(self):
""" Returns calibration distances in 3 element tuple """

return SourceCalibrationModule.ZONE_DISTANCES

class CalibrationData(object):
"""Saves or loads calibration data to/from file.
Expand Down

0 comments on commit 22a7935

Please sign in to comment.