Skip to content

Commit b5b947b

Browse files
committed
Sort motors according to hierarchy and move torque switch
1 parent 4264337 commit b5b947b

File tree

1 file changed

+26
-17
lines changed
  • bitbots_motion/bitbots_animation_rqt/bitbots_animation_rqt

1 file changed

+26
-17
lines changed

bitbots_motion/bitbots_animation_rqt/bitbots_animation_rqt/record_ui.py

+26-17
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from PyQt5.QtGui import QKeySequence
99
from PyQt5.QtWidgets import (
1010
QAbstractItemView,
11+
QCheckBox,
1112
QFileDialog,
1213
QGroupBox,
1314
QLabel,
@@ -28,7 +29,7 @@
2829
from std_srvs.srv import SetBool
2930

3031
from bitbots_animation_rqt.animation_recording import Recorder
31-
from bitbots_animation_rqt.utils import DragDropList
32+
from bitbots_animation_rqt.utils import DragDropList, flatten_dict_of_lists
3233
from bitbots_msgs.action import PlayAnimation
3334
from bitbots_msgs.msg import JointCommand, JointTorque
3435
from bitbots_msgs.srv import AddAnimation
@@ -82,7 +83,7 @@ def __init__(self, context):
8283

8384
# Initialize the motor tree structure where we can select which motors are stiff
8485
self._motor_switcher_active_checkbox: dict[str, QTreeWidgetItem] = {}
85-
self._motor_switcher_torque_checkbox: dict[str, QTreeWidgetItem] = {}
86+
self._motor_controller_torque_checkbox: dict[str, QTreeWidgetItem] = {}
8687

8788
# Motor hierarchy
8889
self._motor_hierarchy = { # TODO this should be a parameter / loaded from the urdf
@@ -120,6 +121,7 @@ def __init__(self, context):
120121
},
121122
}
122123
}
124+
self._motor_hierarchy_flat = flatten_dict_of_lists(self._motor_hierarchy)
123125

124126
# Create drag and dop list for keyframes
125127
self._widget.frameList = DragDropList(self._widget, self.change_keyframe_order)
@@ -175,11 +177,13 @@ def create_motor_controller(self) -> None:
175177
Sets up the GUI in the middle of the Screen to control the motors.
176178
Uses self._motorValues to determine which motors are present.
177179
"""
178-
# Iterate over all motors
179-
for i, motor_name in enumerate(sorted(self.motors)):
180+
# Iterate over all motors (we iterate over the flat hierarchy to get the correct order of the motors)
181+
for i, motor_name in enumerate(self._motor_hierarchy_flat.values()):
180182
# Create a group of UI elements for each motor
181183
group = QGroupBox()
182184
layout = QVBoxLayout()
185+
# Horizontally center the group
186+
layout.setAlignment(Qt.AlignHCenter)
183187
# Create a label for the motor name
184188
label = QLabel()
185189
label.setText(motor_name)
@@ -192,7 +196,15 @@ def create_motor_controller(self) -> None:
192196
layout.addWidget(textfield)
193197
self._motor_controller_text_fields[motor_name] = textfield
194198

199+
# Put a torque checkbox below the motor enable checkbox
200+
torque_checkbox = QCheckBox()
201+
torque_checkbox.setText("Torque")
202+
torque_checkbox.setCheckState(Qt.Checked)
203+
layout.addWidget(torque_checkbox)
204+
self._motor_controller_torque_checkbox[motor_name] = torque_checkbox
205+
195206
# Add the layout to the group and the group to the main layout (at the correct position in the 5 x n grid)
207+
layout.setAlignment(Qt.AlignCenter)
196208
group.setLayout(layout)
197209
self._widget.motorControlLayout.addWidget(group, i // 5, i % 5)
198210

@@ -229,19 +241,12 @@ def build_widget_tree(parent, hierarchy: dict) -> None:
229241
enable_checkbox.setCheckState(0, Qt.Checked)
230242
enable_checkbox.setExpanded(True)
231243
self._motor_switcher_active_checkbox[motor_name] = enable_checkbox
232-
233-
# Put a torque checkbox below the motor enable checkbox
234-
torque_checkbox = QTreeWidgetItem(enable_checkbox)
235-
torque_checkbox.setText(0, "Torque")
236-
torque_checkbox.setFlags(torque_checkbox.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
237-
torque_checkbox.setCheckState(0, Qt.Checked)
238-
self._motor_switcher_torque_checkbox[motor_name] = torque_checkbox
239244
else:
240245
raise ValueError("Invalid hierarchy")
241246

242247
# Build the tree
243248
build_widget_tree(self._widget.motorTree, self._motor_hierarchy)
244-
self._widget.motorTree.setHeaderLabel("Active / Stiff Motors")
249+
self._widget.motorTree.setHeaderLabel("Active Motors (for the current keyframe)")
245250

246251
# Register hook that executes our callback when the user clicks on a checkbox
247252
self._widget.motorTree.itemClicked.connect(self.react_to_motor_selection)
@@ -502,9 +507,9 @@ def record(self):
502507
{
503508
motor_name: self._working_angles[motor_name]
504509
for motor_name in self.motors
505-
if self._motor_switcher_active_checkbox[motor_name].checkState(0) == 2
510+
if self._motor_switcher_active_checkbox[motor_name].checkState(0) == Qt.CheckState.Checked
506511
},
507-
{motor_name: self._motor_switcher_torque_checkbox[motor_name].checkState(0) for motor_name in self.motors},
512+
{motor_name: self._motor_controller_torque_checkbox[motor_name].checkState() for motor_name in self.motors},
508513
new_name,
509514
self._widget.spinBoxDuration.value(),
510515
self._widget.spinBoxPause.value(),
@@ -588,7 +593,7 @@ def react_to_frame_change(self):
588593
stiff = "torques" not in selected_frame or (
589594
motor_name in selected_frame["torques"] and bool(selected_frame["torques"][motor_name])
590595
)
591-
self._motor_switcher_torque_checkbox[motor_name].setCheckState(0, Qt.Checked if stiff else Qt.Unchecked)
596+
self._motor_controller_torque_checkbox[motor_name].setCheckState(Qt.Checked if stiff else Qt.Unchecked)
592597

593598
# Update the motor angle controls (value and active state)
594599
if active:
@@ -636,9 +641,10 @@ def react_to_motor_selection(self):
636641
"""
637642
# Go through all motors
638643
for motor_name in self.motors:
639-
active = self._motor_switcher_active_checkbox[motor_name].checkState(0) == 2
644+
active = self._motor_switcher_active_checkbox[motor_name].checkState(0) == Qt.CheckState.Checked
640645
# Enable or disable the motor controls
641646
self._motor_controller_text_fields[motor_name].setEnabled(active)
647+
self._motor_controller_torque_checkbox[motor_name].setEnabled(active)
642648
# Pull working values from from the joint states if the motor is not active
643649
if not active and motor_name in self._joint_states.name:
644650
self._working_angles[motor_name] = self._joint_states.position[
@@ -663,7 +669,10 @@ def react_to_motor_selection(self):
663669
self.effort_pub.publish(
664670
JointTorque(
665671
joint_names=self.motors,
666-
on=[self._motor_switcher_torque_checkbox[motor_name].checkState(0) == 2 for motor_name in self.motors],
672+
on=[
673+
self._motor_controller_torque_checkbox[motor_name].checkState() == Qt.CheckState.Checked
674+
for motor_name in self.motors
675+
],
667676
)
668677
)
669678

0 commit comments

Comments
 (0)