moteus-gui 0.3.67__py3-none-any.whl → 0.3.68__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
moteus_gui/tview.py CHANGED
@@ -611,6 +611,10 @@ class Device:
611
611
  self._config_tree_items = {}
612
612
  self._config_callback = None
613
613
 
614
+ self._events = {}
615
+ self._data_update_time = {}
616
+ self._data = {}
617
+
614
618
  self._updating_config = False
615
619
 
616
620
  async def start(self):
@@ -764,6 +768,26 @@ class Device:
764
768
  record.update(struct)
765
769
  _set_tree_widget_data(record.tree_item, struct, record.archive)
766
770
 
771
+ self._data[name] = struct
772
+ if name not in self._events:
773
+ self._events[name] = asyncio.Event()
774
+ self._events[name].set()
775
+ self._data_update_time[name] = time.time()
776
+
777
+ async def wait_for_data(self, name):
778
+ if name not in self._events:
779
+ self._events[name] = asyncio.Event()
780
+
781
+ await self._events[name].wait()
782
+ self._events[name].clear()
783
+ return self._data[name]
784
+
785
+ async def ensure_record_active(self, name):
786
+ now = time.time()
787
+ if (now - self._data_update_time.get(name, 0.0)) > 0.2:
788
+ print(f"trying to enable {name}")
789
+ self.write_line(f'tel rate {name} 100\r\n')
790
+
767
791
  async def read_sized_block(self):
768
792
  return await self._stream.read_sized_block()
769
793
 
@@ -902,6 +926,8 @@ class TviewMainWindow():
902
926
  self.devices = []
903
927
  self.default_rate = 100
904
928
 
929
+ self.user_task = None
930
+
905
931
  current_script_dir = os.path.dirname(os.path.abspath(__file__))
906
932
  uifilename = os.path.join(current_script_dir, "tview_main_window.ui")
907
933
 
@@ -1066,30 +1092,70 @@ class TviewMainWindow():
1066
1092
  return write
1067
1093
 
1068
1094
  def _handle_user_input(self, line):
1069
- device_lines = [x.strip() for x in line.split('&&')]
1070
- now = time.time()
1071
- current_delay_ms = 0
1072
- for line in device_lines:
1073
- delay_re = re.search(r"^:(\d+)$", line)
1074
- device_re = re.search(r"^(A|\d+)>(.*)$", line)
1075
- if delay_re:
1076
- current_delay_ms += int(delay_re.group(1))
1077
- continue
1078
- elif device_re:
1079
- if device_re.group(1) == 'A':
1080
- device_nums = [x.number for x in self.devices]
1081
- else:
1082
- device_nums = [int(device_re.group(1))]
1083
- line = device_re.group(2)
1084
- else:
1085
- device_nums = [self.devices[0].number]
1086
- devices = [x for x in self.devices if x.number in device_nums]
1087
- writer = self.make_writer(devices, line)
1095
+ if self.user_task is not None:
1096
+ # We have an outstanding one, so cancel it.
1097
+ self.user_task.cancel()
1098
+ self.user_task = None
1099
+
1100
+ self.user_task = asyncio.create_task(
1101
+ self._run_user_command_line(line))
1102
+
1103
+ async def _run_user_command_line(self, line):
1104
+ try:
1105
+ for command in [x.strip() for x in line.split('&&')]:
1106
+ await self._run_user_command(command)
1107
+ except Exception as e:
1108
+ print("Error:", str(e))
1109
+
1110
+ # Otherwise ignore problems so that tview keeps running.
1088
1111
 
1089
- if current_delay_ms > 0:
1090
- QtCore.QTimer.singleShot(current_delay_ms, writer)
1112
+ async def _wait_user_query(self, maybe_id):
1113
+ device_nums = [self.devices[0].number]
1114
+ if maybe_id:
1115
+ device_nums = [int(maybe_id)]
1116
+
1117
+ devices = [x for x in self.devices if x.number in device_nums]
1118
+
1119
+ record = 'servo_stats'
1120
+
1121
+ if len(devices) == 0:
1122
+ # Nothing to wait on, so return immediately
1123
+ return
1124
+
1125
+ for d in devices:
1126
+ await d.ensure_record_active(record)
1127
+ await d.wait_for_data(record)
1128
+ await d.wait_for_data(record)
1129
+
1130
+ while True:
1131
+ # Now look for at least to have trajectory_done == True
1132
+ for d in devices:
1133
+ servo_stats = await d.wait_for_data(record)
1134
+ if getattr(servo_stats, 'trajectory_done', False):
1135
+ return
1136
+
1137
+ async def _run_user_command(self, command):
1138
+ delay_re = re.search(r"^:(\d+)$", command)
1139
+ device_re = re.search(r"^(A|\d+)>(.*)$", command)
1140
+ traj_re = re.search(r"^(\?(\d+)?)$", command)
1141
+
1142
+ device_nums = [self.devices[0].number]
1143
+
1144
+ if traj_re:
1145
+ await self._wait_user_query(traj_re.group(2))
1146
+ return
1147
+ if delay_re:
1148
+ await asyncio.sleep(int(delay_re.group(2)) / 1000.0)
1149
+ return
1150
+ elif device_re:
1151
+ command = device_re.group(2)
1152
+ if device_re.group(1) == 'A':
1153
+ device_nums = [x.number for x in self.devices]
1091
1154
  else:
1092
- writer()
1155
+ device_nums = [int(device_re.group(1))]
1156
+
1157
+ for device in [x for x in self.devices if x.number in device_nums]:
1158
+ device.write((command + '\n').encode('latin1'))
1093
1159
 
1094
1160
  def _handle_tree_expanded(self, item):
1095
1161
  self.ui.telemetryTreeWidget.resizeColumnToContents(0)
moteus_gui/version.py CHANGED
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- VERSION="0.3.67"
15
+ VERSION="0.3.68"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: moteus-gui
3
- Version: 0.3.67
3
+ Version: 0.3.68
4
4
  Summary: moteus brushless controller graphical user interfaces
5
5
  Home-page: https://github.com/mjbots/moteus
6
6
  Author: mjbots Robotic Systems
@@ -18,7 +18,7 @@ Requires-Dist: matplotlib >=3.5
18
18
  Requires-Dist: numpy
19
19
  Requires-Dist: qtconsole >=0.5.2
20
20
  Requires-Dist: qtpy >=2.0.1
21
- Requires-Dist: PySide6 >=6.2 ; platform_system != "Linux"
21
+ Requires-Dist: PySide6 <6.7,>=6.2 ; platform_system != "Linux"
22
22
  Requires-Dist: PySide2 ; platform_system == "Linux"
23
23
  Requires-Dist: msvc-runtime ; platform_system == "Windows" and python_version < "3.12"
24
24
 
@@ -0,0 +1,9 @@
1
+ moteus_gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ moteus_gui/tview.py,sha256=IUYQOuB9dE_00bN9wB6mjE50CfaoKkXtyrMYp5CTZ2k,42094
3
+ moteus_gui/tview_main_window.ui,sha256=q_qA1sooIWzprVT8eYAe0EH9lfu7zg-QP1diETCNFh8,5556
4
+ moteus_gui/version.py,sha256=8rx1YUinZCom0pzbiJ3IcLDXrj5FEja3M79tr75nJJM,627
5
+ moteus_gui-0.3.68.dist-info/METADATA,sha256=rUBEN94YcDg8VZuRIVXA0TWtpl96o_Wy14rL1KFViHU,1077
6
+ moteus_gui-0.3.68.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
7
+ moteus_gui-0.3.68.dist-info/entry_points.txt,sha256=Y9PnhK_gNxr8CO7_POHieVaK1U_4fgu2EYoS6TyzSgk,48
8
+ moteus_gui-0.3.68.dist-info/top_level.txt,sha256=oPOkXR-zpPFhGiDcbnDY6scvNqQQAXWzV7oPD_GHMns,11
9
+ moteus_gui-0.3.68.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- moteus_gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- moteus_gui/tview.py,sha256=njykSaZC1urR0g3KEOuNvwVojJcxbk1J17P91sDi_7I,40032
3
- moteus_gui/tview_main_window.ui,sha256=q_qA1sooIWzprVT8eYAe0EH9lfu7zg-QP1diETCNFh8,5556
4
- moteus_gui/version.py,sha256=q4LPxNY63TQcpoLc62l1hxxwO8yOooz5ORImA1Tw6io,627
5
- moteus_gui-0.3.67.dist-info/METADATA,sha256=gYq-S3H_9XeKKBbc2ftl0OPR9lHAWdP960hvJxjXeYg,1072
6
- moteus_gui-0.3.67.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
7
- moteus_gui-0.3.67.dist-info/entry_points.txt,sha256=Y9PnhK_gNxr8CO7_POHieVaK1U_4fgu2EYoS6TyzSgk,48
8
- moteus_gui-0.3.67.dist-info/top_level.txt,sha256=oPOkXR-zpPFhGiDcbnDY6scvNqQQAXWzV7oPD_GHMns,11
9
- moteus_gui-0.3.67.dist-info/RECORD,,