Skip to content

Commit f6af74b

Browse files
authored
Merge pull request #81 from cpaxton/devel
Notifications, instructor plugin refactor, and easy mode switch
2 parents 34ccd0b + b9ca1f1 commit f6af74b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1211
-2246
lines changed

costar_instructor/instructor_core/nodes/instructor_gui.py

Lines changed: 0 additions & 878 deletions
This file was deleted.

costar_instructor/instructor_core/nodes/instructor_view.py

Lines changed: 112 additions & 88 deletions
Large diffs are not rendered by default.

costar_instructor/instructor_core/src/instructor_core/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
__all__ += ['NamedComboBox']
2020
__all__ += ['JogDialog']
2121
__all__ += ['SmartMoveDialog']
22+
__all__ += ['NotificationDialog']
2223
__all__ += ['RobotInterface']
2324

2425
# NodeGUI Base Classes
@@ -35,6 +36,7 @@
3536
from instructor_core_nodes import NodeDecoratorResetGUI
3637
from instructor_core_nodes import NodeDecoratorIgnoreFailGUI
3738
from instructor_core_nodes import NodeDecoratorWaitForSuccessGUI
39+
from instructor_gui_components import NotificationDialog
3840

3941
from smart_move_dialog import *
4042
from jog_dialog import *

costar_instructor/instructor_core/src/instructor_core/instructor_core_nodes.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def generate(self):
157157
if all([self.name.full(),self.repeat.full()]):
158158
return beetree.NodeDecoratorRepeat(self.get_name(),self.get_label(),int(self.repeat.get()))
159159
else:
160-
return 'ERROR: node not properly defined'
160+
return 'ERROR: check that all menu items are properly selected for this node'
161161

162162
class NodeDecoratorResetGUI(NodeGUI):
163163
def __init__(self):
@@ -171,7 +171,7 @@ def generate(self):
171171
if all([self.name.full(),self.reset.full()]):
172172
return beetree.NodeDecoratorReset(self.get_name(),self.get_label(),int(self.reset.get()))
173173
else:
174-
return 'ERROR: node not properly defined'
174+
return 'ERROR: check that all menu items are properly selected for this node'
175175

176176
class NodeDecoratorIgnoreFailGUI(NodeGUI):
177177
def __init__(self):
@@ -185,7 +185,7 @@ def generate(self):
185185
if all([self.name.full()]):
186186
return beetree.NodeDecoratorIgnoreFail(self.get_name(),self.get_label())
187187
else:
188-
return 'ERROR: node not properly defined'
188+
return 'ERROR: check that all menu items are properly selected for this node'
189189

190190
class NodeDecoratorWaitForSuccessGUI(NodeGUI):
191191
def __init__(self):
@@ -200,6 +200,6 @@ def generate(self):
200200
if all([self.name.full(),self.timeout.full()]):
201201
return beetree.NodeDecoratorWaitForSuccess(self.get_name(),self.get_label(),int(self.timeout.get()))
202202
else:
203-
return 'ERROR: node not properly defined'
203+
return 'ERROR: check that all menu items are properly selected for this node'
204204

205205

costar_instructor/instructor_core/src/instructor_core/instructor_gui_components.py

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,17 @@ def __init__(self, parent=None):
4242
self.button_layout.addWidget(self.save_cancel_btn,2,0)
4343

4444
class Button(QPushButton):
45-
def __init__(self, name, label, txtsz=12, color=Color('#222222','#ffffff'),parent=None):
45+
def __init__(self, name, label, txtsz=12, color=Color('#222222','#ffffff'),parent=None, text_color=Color('#ffffff', '#ffffff', '#dddddd')):
4646
QPushButton.__init__(self, parent)
4747
self.setMouseTracking(True)
4848
self.name = name
4949
self.label = label
5050
self.setText(self.label)
5151
# COLOR
5252
self.color = color
53-
self.default_style = 'border: solid 4px #ffffff; background-color:'+self.color.normal+';color:'+'#ffffff'+';border:none;'
54-
self.hover_style = 'border: solid 4px #ffffff; background-color:'+self.color.hover+';color:'+'#ffffff'+';border:none;'
53+
self.text_color = text_color
54+
self.default_style = 'border: solid 4px #ffffff; background-color:'+self.color.normal+';color:'+self.text_color.normal+';border:none;'
55+
self.hover_style = 'border: solid 4px #ffffff; background-color:'+self.color.hover+';color:'+self.text_color.normal+';border:none;'
5556
self.setStyleSheet(self.default_style)
5657
self.font = QtGui.QFont("Ubuntu", txtsz, QtGui.QFont.Bold)
5758
self.setFont(self.font)
@@ -127,7 +128,7 @@ def halve_string(s):
127128

128129
class HeadingContainer(QWidget):
129130
def __init__(self, name, label, color, size='small',parent=None):
130-
QWidget.__init__(self,parent)
131+
QWidget.__init__(self, parent)
131132
self.label = label
132133
self.name = name
133134
self.color = color
@@ -141,7 +142,7 @@ def __init__(self, name, label, color, size='small',parent=None):
141142
self.scrollArea.hide()
142143

143144
class Container(QWidget):
144-
def __init__(self, name, label, color, size='small',parent=None):
145+
def __init__(self, name, label, color, size='small', parent=None):
145146
QWidget.__init__(self,parent)
146147
self.label = label
147148
self.name = name
@@ -164,7 +165,7 @@ def __init__(self, name, label, color, size='small',parent=None):
164165
self.groups = {}
165166
self.group_members = {}
166167

167-
def register_callbacks(self,contract_cb,selected_cb=None):
168+
def register_callbacks(self,contract_cb, selected_cb=None):
168169
self.contract_cb = contract_cb
169170
self.selected_cb = selected_cb
170171

@@ -183,7 +184,7 @@ def contract(self):
183184
self.button.setStyleSheet(self.button.default_style)
184185
self.button.current_style = self.button.default_style
185186

186-
def add_item(self,name):
187+
def add_item(self, name):
187188
pass
188189

189190
def remove_all(self):
@@ -331,6 +332,77 @@ def __init__(self,parent):
331332
w_path = rp.get_path('instructor_core') + '/ui/drawer_2.ui'
332333
uic.loadUi(w_path, self)
333334

335+
def window_resized(self,event):
336+
visible = self.drawer.isVisible()
337+
self.resize(360,self.container_widget.geometry().height()-100)
338+
self.move(self.container_widget.geometry().left()-360,50)
339+
if visible:
340+
self.show()
341+
else:
342+
self.hide()
343+
344+
class NotificationDialog(QWidget):
345+
def __init__(self, parent=None):
346+
QWidget.__init__(self, parent, QtCore.Qt.WindowStaysOnTopHint)
347+
# GUI
348+
rp = rospkg.RosPack()
349+
w_path = rp.get_path('instructor_core') + '/ui/notifications.ui'
350+
uic.loadUi(w_path, self)
351+
self.show_hide = self.show_hide_slide
352+
self.selected_object = None
353+
self.selected_move = None
354+
self.saved_geom = None
355+
self.new_move_name = None
356+
357+
self.done_button.clicked.connect(self.done)
358+
self.notification_list.itemClicked.connect(self.object_selected)
359+
self.notification_list.itemClicked.connect(self.move_selected)
360+
self.hide()
361+
362+
def notify(self, message, severity='warn'):
363+
"""Adds a message to the notification dialog, showing it if not visible.
364+
365+
# Arguments
366+
367+
message: string message to show in the dialog
368+
severity: one of 'info', 'warn', 'error'
369+
"""
370+
self.most_recent_notification = QListWidgetItem(message)
371+
self.notification_list.addItem(self.most_recent_notification)
372+
self.notification_list.setCurrentItem(self.most_recent_notification)
373+
self.notification_list.scrollToItem(self.most_recent_notification)
374+
if not self.isVisible():
375+
self.show_hide_slide()
376+
377+
if severity is 'warn':
378+
rospy.logwarn(message)
379+
elif severity is 'error':
380+
rospy.logerr(message)
381+
else:
382+
rospy.loginfo(message)
383+
384+
def show_hide_slide(self):
385+
if self.isVisible():
386+
self.saved_geom = self.geometry()
387+
self.hide()
388+
else:
389+
if self.saved_geom is not None:
390+
self.move(self.saved_geom.x(),self.saved_geom.y())
391+
else:
392+
self.move(self.geometry().x()+self.geometry().width()/2-self.geometry().width()/2,self.geometry().y()+self.geometry().height()/2)
393+
self.show()
394+
395+
def done(self):
396+
self.notification_list.clear()
397+
self.show_hide_slide()
398+
399+
def object_selected(self,item):
400+
self.selected_object = str(item.text())
401+
402+
def move_selected(self,item):
403+
self.selected_move = str(item.text())
404+
405+
334406
class Popup(QWidget):
335407
def __init__(self,parent):
336408
QWidget.__init__(self,parent)

costar_instructor/instructor_core/src/instructor_core/instructor_qt.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
from PyQt4.QtCore import *
77

88
class Color:
9-
def __init__(self,normal,hover):
9+
def __init__(self,normal,hover, disabled='#dddddd'):
1010
self.normal = normal
1111
self.hover = hover
12+
self.disabled = disabled
1213

1314
class ColorOptions:
1415
def __init__(self):
@@ -58,6 +59,53 @@ def leaveEvent(self, event):
5859
self.setStyleSheet(self.default_style)
5960

6061

62+
class TextEdit(QTextEdit):
63+
64+
def __init__(self, name, label, txtsz=12, color=Color('#222222','#ffffff'),parent=None):
65+
QTextEdit.__init__(self, parent)
66+
self.document().contentsChanged.connect(self.sizeChange)
67+
68+
self.heightMin = 0
69+
self.heightMax = 65000
70+
# self.setMouseTracking(True)
71+
self.name = name
72+
self.label = label
73+
self.setText(self.label)
74+
# COLOR
75+
self.color = color
76+
self.default_style = 'border: solid 4px #ffffff; background-color:'+self.color.normal+';color:'+'#ffffff'+';border:none;'
77+
self.hover_style = 'border: solid 4px #ffffff; background-color:'+self.color.hover+';color:'+'#ffffff'+';border:none;'
78+
self.setStyleSheet(self.default_style)
79+
# self.font = QtGui.QFont("Ubuntu", txtsz, QtGui.QFont.Bold)
80+
# self.setCurrentFont(self.font)
81+
self.setFocusPolicy(QtCore.Qt.NoFocus)
82+
self.setMinimumHeight(30)
83+
def set_color(self,color):
84+
self.color = color
85+
self.default_style = 'border: solid 4px #ffffff; background-color:'+self.color.normal+';color:'+'#ffffff'+';border:none;'
86+
self.hover_style = 'border: solid 4px #ffffff; background-color:'+self.color.hover+';color:'+'#ffffff'+';border:none;'
87+
self.setStyleSheet(self.default_style)
88+
# def enterEvent(self, event):
89+
# self.setStyleSheet(self.hover_style)
90+
# def leaveEvent(self, event):
91+
# self.setStyleSheet(self.default_style)
92+
def notify(self, message, severity='info'):
93+
self.show()
94+
self.setText(message)
95+
if severity is 'warn':
96+
rospy.logwarn(message)
97+
elif severity is 'error':
98+
rospy.logerr(message)
99+
else:
100+
rospy.loginfo(message)
101+
102+
def sizeChange(self):
103+
docHeight = self.document().size().height()
104+
if self.heightMin <= docHeight <= self.heightMax:
105+
self.setMaximumHeight(docHeight)
106+
107+
108+
61109
class OverlayDialog(QWidget):
62110
def __init__(self, parent=None):
63111
QWidget.__init__(self, parent, QtCore.Qt.WindowStaysOnTopHint)

costar_instructor/instructor_core/src/instructor_core/robot_interface.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def update_status(self):
6262
# self.status_label.setText('ROBOT MODE: ['+self.driver_status.upper()+']')
6363

6464
def teach(self):
65-
if self.driver_status == 'IDLE':
65+
if self.driver_status == 'IDLE' or self.driver_status == 'SERVO':
6666
try:
6767
rospy.wait_for_service('/costar/SetTeachMode',2)
6868
except rospy.ROSException as e:
@@ -95,7 +95,7 @@ def teach(self):
9595
self.toast('Driver is in ['+self.driver_status+'] mode!')
9696

9797
def servo(self):
98-
if self.driver_status == 'IDLE':
98+
if self.driver_status == 'IDLE' or self.driver_status == 'TEACH':
9999
try:
100100
rospy.wait_for_service('/costar/SetServoMode',2)
101101
except rospy.ROSException as e:

costar_instructor/instructor_core/src/instructor_core/smart_move_dialog.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
from smart_waypoint_manager import SmartWaypointManager
1010

1111
class SmartMoveDialog(QWidget):
12-
def __init__(self, show_hide_fn,parent=None):
12+
def __init__(self, parent=None):
1313
QWidget.__init__(self, parent, QtCore.Qt.WindowStaysOnTopHint)
1414
# GUI
1515
rp = rospkg.RosPack()
1616
w_path = rp.get_path('instructor_core') + '/ui/smart_move.ui'
1717
uic.loadUi(w_path, self)
18-
self.show_hide = show_hide_fn
18+
self.show_hide = self.show_hide_slide
1919
self.selected_object = None
2020
self.selected_move = None
2121
self.saved_geom = None
@@ -34,6 +34,19 @@ def __init__(self, show_hide_fn,parent=None):
3434
self.update_objects()
3535
self.update_moves()
3636

37+
38+
def show_hide_slide(self):
39+
if self.isVisible():
40+
self.saved_geom = self.geometry()
41+
self.hide()
42+
else:
43+
if self.saved_geom is not None:
44+
self.move(self.saved_geom.x(),self.saved_geom.y())
45+
else:
46+
self.move(self.geometry().x()+self.geometry().width()/2-self.geometry().width()/2,self.geometry().y()+self.geometry().height()/2-self.geometry().height()/2)
47+
self.show()
48+
self.update_all()
49+
3750
def update_all(self):
3851
self.update_objects()
3952
self.update_moves()

0 commit comments

Comments
 (0)