@@ -40,42 +40,50 @@ class RecordUI(Plugin):
40
40
41
41
def __init__ (self , context ):
42
42
super ().__init__ (context )
43
+ # Store reference to node
43
44
self ._node : Node = context .node
44
45
46
+ # Set Name of the plugin
47
+ self .setObjectName ("Record Animation" )
48
+
49
+ # Create publishers
50
+ self ._joint_pub = self ._node .create_publisher (JointCommand , "record_motor_goals" , 1 )
51
+ self .effort_pub = self ._node .create_publisher (JointTorque , "ros_control/set_torque_individual" , 1 )
52
+
53
+ # Initialize the recorder module
54
+ self ._recorder = Recorder (self ._node )
55
+
45
56
# Initialize the window
46
57
self ._widget = QMainWindow ()
47
58
48
59
# Load XML ui definition
49
60
ui_file = os .path .join (get_package_share_directory ("bitbots_animation_rqt" ), "resource" , "RecordUI.ui" )
50
61
loadUi (ui_file , self ._widget , {})
51
62
52
- # Initialize the recorder module
53
- self ._recorder = Recorder (self ._node )
54
-
55
63
# Initialize the GUI state
56
64
self ._sliders = {}
57
65
self ._text_fields = {}
58
66
self ._motor_switched = {}
59
67
self ._selected_frame = None
68
+
69
+ self .update_time = 0.1 # TODO what is this for?
60
70
61
71
self ._current_goals = {} # this is the data about the current unsaved frame
62
72
self ._current_duration = 1.0
63
73
self ._current_pause = 0.0
64
74
self ._current_name = "new frame"
65
75
76
+ # Save current keyframe when switching to other frames in the ui
66
77
self ._working_values = {} # this is the data about the frame that is displayed
67
78
self ._working_duration = 1.0
68
79
self ._working_pause = 0.0
69
- self ._working_name = self ._currentName
70
-
80
+ self ._working_name = self ._current_name
71
81
self ._current = True
72
82
73
83
# QT directory for saving files
74
84
self ._save_directory = None
75
85
76
- # save current frame when switching to other frames for reference
77
- # working frame
78
-
86
+ # Initialize the motor tree structure where we can select which motors are stiff
79
87
self ._treeItems = {}
80
88
self ._motor_check_body = QTreeWidgetItem (self ._widget .motorTree )
81
89
self ._motor_check_legs = QTreeWidgetItem (self ._motor_check_body )
@@ -86,49 +94,46 @@ def __init__(self, context):
86
94
self ._motor_check_left_leg = QTreeWidgetItem (self ._motor_check_legs )
87
95
self ._motor_check_right_leg = QTreeWidgetItem (self ._motor_check_legs )
88
96
89
- # saves configuration of the trees checkboxes for each of the tree modes.
97
+ # Save configuration of the trees checkboxes for each of the tree modes
90
98
self ._check_boxes_save = {}
91
99
self ._check_boxes_power = {}
92
100
self ._previous_tree_mode = 0
93
101
94
- self .setObjectName ("Record Animation" )
95
-
102
+ # Create drag and dop list for keyframes
96
103
self ._widget .frameList = DragDropList (self ._widget , self )
97
104
self ._widget .verticalLayout_2 .insertWidget (0 , self ._widget .frameList )
98
105
self ._widget .frameList .setDragDropMode (QAbstractItemView .InternalMove )
99
106
100
107
# Create a dictionary to map joint names to ids # TODO this should not be hardcoded
101
- self .ids = {
102
- "HeadPan" : 0 ,
103
- "HeadTilt" : 1 ,
104
- "LShoulderPitch" : 2 ,
105
- "LShoulderRoll" : 3 ,
106
- "LElbow" : 4 ,
107
- "RShoulderPitch" : 5 ,
108
- "RShoulderRoll" : 6 ,
109
- "RElbow" : 7 ,
110
- "LHipYaw" : 8 ,
111
- "LHipRoll" : 9 ,
112
- "LHipPitch" : 10 ,
113
- "LKnee" : 11 ,
114
- "LAnklePitch" : 12 ,
115
- "LAnkleRoll" : 13 ,
116
- "RHipYaw" : 14 ,
117
- "RHipRoll" : 15 ,
118
- "RHipPitch" : 16 ,
119
- "RKnee" : 17 ,
120
- "RAnklePitch" : 18 ,
121
- "RAnkleRoll" : 19 ,
122
- }
123
-
124
- self ._initial_joints = JointState ()
125
-
126
- self .update_time = 0.1
127
-
128
- for k , _v in self .ids .items ():
129
- self ._node .get_logger ().info (f"Adding { k } to initial_joints" )
130
- self ._initial_joints .name .append (k )
131
- self ._initial_joints .position .append (0 )
108
+ self .motors = [
109
+ "HeadPan" ,
110
+ "HeadTilt" ,
111
+ "LShoulderPitch" ,
112
+ "LShoulderRoll" ,
113
+ "LElbow" ,
114
+ "RShoulderPitch" ,
115
+ "RShoulderRoll" ,
116
+ "RElbow" ,
117
+ "LHipYaw" ,
118
+ "LHipRoll" ,
119
+ "LHipPitch" ,
120
+ "LKnee" ,
121
+ "LAnklePitch" ,
122
+ "LAnkleRoll" ,
123
+ "RHipYaw" ,
124
+ "RHipRoll" ,
125
+ "RHipPitch" ,
126
+ "RKnee" ,
127
+ "RAnklePitch" ,
128
+ "RAnkleRoll" ,
129
+ ]
130
+
131
+ # Create the initial joint state
132
+ self ._initial_joints = JointState (
133
+ name = self .motors ,
134
+ position = [0.0 ] * len (self .motors ),
135
+ )
136
+
132
137
133
138
for i in range (0 , len (self ._initial_joints .name )):
134
139
self ._current_goals [self ._initial_joints .name [i ]] = self ._initial_joints .position [i ]
@@ -141,9 +146,9 @@ def __init__(self, context):
141
146
142
147
self ._check_boxes_power ["#CURRENT_FRAME" ] = init_torque
143
148
144
- self .motor_controller ()
145
- self .motor_switcher ()
146
- self .action_connect ()
149
+ self .create_motor_controller ()
150
+ self .create_motor_switcher ()
151
+ self .connect_gui_callbacks ()
147
152
self .box_ticked ()
148
153
self .frame_list ()
149
154
self .update_frames ()
@@ -154,10 +159,6 @@ def __init__(self, context):
154
159
# Create subscriptions
155
160
self .state_sub = self ._node .create_subscription (JointState , "joint_states" , self .state_update , 1 )
156
161
157
- # Create publishers
158
- self ._joint_pub = self ._node .create_publisher (JointCommand , "record_motor_goals" , 1 )
159
- self .effort_pub = self ._node .create_publisher (JointTorque , "ros_control/set_torque_individual" , 1 )
160
-
161
162
self ._widget .statusBar .showMessage ("Initialization complete." )
162
163
163
164
def state_update (self , joint_states ):
@@ -175,13 +176,12 @@ def state_update(self, joint_states):
175
176
time .sleep (self .update_time )
176
177
self .set_sliders_and_text_fields (manual = False )
177
178
178
- def motor_controller (self ):
179
+ def create_motor_controller (self ):
179
180
"""
180
181
Sets up the GUI in the middle of the Screen to control the motors.
181
182
Uses self._motorValues to determine which motors are present.
182
183
"""
183
- i = 0
184
- for k , _v in sorted (self ._current_goals .items ()):
184
+ for i , k in enumerate (sorted (self ._current_goals .keys ())):
185
185
group = QGroupBox ()
186
186
slider = QSlider (Qt .Horizontal )
187
187
slider .setTickInterval (1 )
@@ -207,9 +207,8 @@ def motor_controller(self):
207
207
layout .addWidget (self ._text_fields [k ])
208
208
group .setLayout (layout )
209
209
self ._widget .motorControlLayout .addWidget (group , i // 5 , i % 5 )
210
- i = i + 1
211
210
212
- def action_connect (self ):
211
+ def connect_gui_callbacks (self ):
213
212
"""
214
213
Connects the actions in the top bar to the corresponding functions, and sets their shortcuts
215
214
:return:
@@ -639,7 +638,7 @@ def frame_select(self):
639
638
selected_frame_name = self ._widget .frameList .currentItem ().text ()
640
639
self ._selected_frame = None
641
640
642
- for v in []: # TODO self._recorder.get_animation_state():
641
+ for v in self ._recorder .get_animation_state ():
643
642
if v ["name" ] == selected_frame_name :
644
643
self ._selected_frame = v
645
644
break
@@ -652,7 +651,7 @@ def frame_select(self):
652
651
self .update_tree_config (0 )
653
652
self ._widget .treeModeSelector .setEnabled (False )
654
653
self ._working_values = deepcopy (self ._current_goals )
655
- self ._working_name = deepcopy (self ._currentName )
654
+ self ._working_name = deepcopy (self ._current_name )
656
655
self ._working_duration = deepcopy (self ._current_duration )
657
656
self ._working_pause = deepcopy (self ._current_pause )
658
657
@@ -663,7 +662,7 @@ def frame_select(self):
663
662
self ._widget .treeModeSelector .setEnabled (True )
664
663
if self ._current :
665
664
self ._current_goals = deepcopy (self ._working_values )
666
- self ._currentName = deepcopy (self ._working_name )
665
+ self ._current_name = deepcopy (self ._working_name )
667
666
self ._current_duration = deepcopy (self ._working_duration )
668
667
self ._current_pause = deepcopy (self ._working_pause )
669
668
@@ -686,7 +685,7 @@ def frame_select(self):
686
685
687
686
self .box_ticked ()
688
687
689
- def motor_switcher (self ):
688
+ def create_motor_switcher (self ):
690
689
"""
691
690
Loads the motors into the tree and adds the checkboxes
692
691
"""
@@ -724,7 +723,7 @@ def motor_switcher(self):
724
723
)
725
724
self ._motor_check_right_leg .setExpanded (True )
726
725
727
- for k , _v in self ._current_goals .items ():
726
+ for k in self ._current_goals .keys ():
728
727
parent = None
729
728
if "LHip" in k or "LKnee" in k or "LAnkle" in k :
730
729
parent = self ._motor_check_left_leg
@@ -844,7 +843,7 @@ def set_sliders_and_text_fields(self, manual):
844
843
self ._widget .spinBoxDuration .setValue (self ._working_duration )
845
844
self ._widget .spinBoxPause .setValue (self ._working_pause )
846
845
847
- def box_ticked (self ):
846
+ def box_ticked (self ): # TODO rename
848
847
"""
849
848
Controls whether a checkbox has been clicked, and reacts.
850
849
"""
@@ -890,7 +889,7 @@ def update_frames(self, keep=False):
890
889
"""
891
890
current_index = self ._widget .frameList .currentIndex ()
892
891
current_mode = self ._widget .treeModeSelector .currentIndex ()
893
- current_state = [] # TODO self._recorder.get_animation_state()
892
+ current_state = self ._recorder .get_animation_state ()
894
893
while self ._widget .frameList .takeItem (0 ):
895
894
continue
896
895
@@ -912,7 +911,7 @@ def update_frames(self, keep=False):
912
911
self ._widget .frameList .setCurrentItem (current )
913
912
self ._current = True
914
913
915
- def change_frame_order (self , new_order ):
914
+ def change_keyframe_order (self , new_order ):
916
915
"""Calls the recorder to update frame order and updates the gui"""
917
916
self ._recorder .change_frame_order (new_order )
918
917
self .update_frames ()
0 commit comments