@@ -71,6 +71,16 @@ def __init__(self, meshcat_provider, parent=None, dataset_loaded=False):
7171 self .ui .robotModelToolButton .clicked .connect (self .open_urdf_file )
7272 self .ui .packageDirToolButton .clicked .connect (self .open_package_directory )
7373
74+ # Force the arrowScaling_lineEdit to be a positive float
75+ self .ui .arrowScaling_lineEdit .setValidator (QtGui .QDoubleValidator (0 , 100 , 2 ))
76+
77+ # connect the arrowScaling_checkBox to the handle_arrow_scaling method
78+ self .ui .arrowScaling_checkBox .toggled .connect (self .handle_arrow_scaling )
79+
80+ self .clicked_button = None
81+ self .std_button = None
82+ self .ui .buttonBox .clicked .connect (self .buttonBox_on_click )
83+
7484 if dataset_loaded :
7585 frames = meshcat_provider .robot_frames ()
7686 self .ui .frameNameComboBox .addItems (frames )
@@ -94,6 +104,33 @@ def get_urdf_path(self):
94104 def get_package_directory (self ):
95105 return self .ui .packageDirLineEdit .text ()
96106
107+ def buttonBox_on_click (self , button ):
108+ self .clicked_button = button
109+
110+ self .std_button = self .ui .buttonBox .standardButton (button )
111+
112+ def get_clicked_button_role (self ):
113+ if self .clicked_button is not None :
114+ return self .ui .buttonBox .buttonRole (self .clicked_button )
115+ return None
116+
117+ def get_clicked_button_text (self ):
118+ if self .clicked_button is not None :
119+ return self .clicked_button .text ()
120+ return None
121+
122+ def get_clicked_standard_button (self ):
123+ return self .std_button
124+
125+ def handle_arrow_scaling (self ):
126+ # if arrowScaling_checkBox is checked the lineEdit must be disabled else it must be enabled
127+ if self .ui .arrowScaling_checkBox .isChecked ():
128+ self .ui .arrowScaling_lineEdit .setText ("" )
129+ self .ui .arrowScaling_lineEdit .setEnabled (False )
130+ else :
131+ self .ui .arrowScaling_lineEdit .setText ("" )
132+ self .ui .arrowScaling_lineEdit .setEnabled (True )
133+
97134
98135class About (QtWidgets .QMainWindow ):
99136 def __init__ (self ):
@@ -172,6 +209,7 @@ def __init__(self, signal_provider, meshcat_provider, animation_period):
172209 self .video_items = []
173210 self .visualized_3d_points = set ()
174211 self .visualized_3d_trajectories = set ()
212+ self .visualized_3d_arrows = set ()
175213 self .visualized_3d_points_colors_palette = ColorPalette ()
176214
177215 self .toolButton_on_click ()
@@ -690,9 +728,47 @@ def open_set_robot_model(self):
690728 )
691729 outcome = dlg .exec ()
692730 if outcome == QDialog .Accepted :
693- if not self .dataset_loaded :
694- self .meshcat_provider .model_path = dlg .get_urdf_path ()
695- self .meshcat_provider .custom_package_dir = dlg .get_package_directory ()
731+
732+ # check which button was clicked
733+ button_role = dlg .get_clicked_button_role ()
734+ button_text = dlg .get_clicked_button_text ()
735+ std_button = dlg .get_clicked_standard_button ()
736+
737+ if std_button == QtWidgets .QDialogButtonBox .SaveAll :
738+ if not self .dataset_loaded :
739+ self .meshcat_provider .model_path = dlg .get_urdf_path ()
740+ self .meshcat_provider .custom_package_dir = (
741+ dlg .get_package_directory ()
742+ )
743+
744+ arrow_scaling_value = dlg .ui .arrowScaling_lineEdit .text ()
745+ if not arrow_scaling_value :
746+ arrow_scaling_value = "1.0"
747+ else :
748+ arrow_scaling_value = float (arrow_scaling_value )
749+ self .signal_provider .set_custom_max_arrow (
750+ not dlg .ui .arrowScaling_checkBox .isChecked (), arrow_scaling_value
751+ )
752+ if std_button == QtWidgets .QDialogButtonBox .Save :
753+ # we need to check which tab is selected in the dlg
754+ if dlg .ui .tabWidget .currentIndex () == 0 :
755+ if not self .dataset_loaded :
756+ self .meshcat_provider .model_path = dlg .get_urdf_path ()
757+ self .meshcat_provider .custom_package_dir = (
758+ dlg .get_package_directory ()
759+ )
760+ else :
761+ arrow_scaling_value = dlg .ui .arrowScaling_lineEdit .text ()
762+ # if it is empty we set it to 1.0
763+ if not arrow_scaling_value :
764+ arrow_scaling_value = "1.0"
765+ else :
766+ arrow_scaling_value = float (arrow_scaling_value )
767+ self .signal_provider .set_custom_max_arrow (
768+ not dlg .ui .arrowScaling_checkBox .isChecked (),
769+ arrow_scaling_value ,
770+ )
771+
696772 else :
697773 self .meshcat_provider .load_model (
698774 self .signal_provider .joints_name ,
@@ -752,8 +828,10 @@ def variableTreeWidget_on_right_click(self, item_position):
752828
753829 add_3d_point_str = "Show as a 3D point"
754830 add_3d_trajectory_str = "Show as a 3D trajectory"
831+ add_3d_arrow_str = "Show as a 3D arrow"
755832 remove_3d_point_str = "Remove the 3D point"
756833 remove_3d_trajectory_str = "Remove the 3D trajectory"
834+ remove_3d_arrow_str = "Remove the 3D arrow"
757835 use_as_base_position_str = "Use as base position"
758836 use_as_base_orientation_str = "Use as base orientation"
759837 dont_use_as_base_position_str = "Don't use as base position"
@@ -805,14 +883,24 @@ def variableTreeWidget_on_right_click(self, item_position):
805883 else :
806884 menu .addAction (use_as_base_orientation_str + " (xyzw Quaternion)" )
807885
886+ if item_size == 6 :
887+ if item_key in self .visualized_3d_arrows :
888+ menu .addAction (remove_3d_arrow_str )
889+ else :
890+ menu .addAction (add_3d_arrow_str )
891+
808892 # show the menu
809893 action = menu .exec_ (self .ui .variableTreeWidget .mapToGlobal (item_position ))
810894 if action is None :
811895 return
812896
813897 item_path = self .get_item_path (item )
814898
815- if action .text () == add_3d_point_str or action .text () == add_3d_trajectory_str :
899+ if (
900+ action .text () == add_3d_point_str
901+ or action .text () == add_3d_trajectory_str
902+ or action .text () == add_3d_arrow_str
903+ ):
816904 color = next (self .visualized_3d_points_colors_palette )
817905
818906 item .setForeground (0 , QtGui .QBrush (QtGui .QColor (color .as_hex ())))
@@ -823,12 +911,20 @@ def variableTreeWidget_on_right_click(self, item_position):
823911 )
824912 self .signal_provider .register_3d_point (item_key , item_path )
825913 self .visualized_3d_points .add (item_key )
826- else :
914+ elif action . text () == add_3d_trajectory_str :
827915 self .meshcat_provider .register_3d_trajectory (
828916 item_key , list (color .as_normalized_rgb ())
829917 )
830918 self .signal_provider .register_3d_trajectory (item_key , item_path )
831919 self .visualized_3d_trajectories .add (item_key )
920+ elif action .text () == add_3d_arrow_str :
921+ self .meshcat_provider .register_3d_arrow (
922+ item_key , list (color .as_normalized_rgb ())
923+ )
924+ self .signal_provider .register_3d_arrow (item_key , item_path )
925+ self .visualized_3d_arrows .add (item_key )
926+ else :
927+ raise ValueError ("Unknown action" )
832928
833929 if action .text () == remove_3d_point_str :
834930 self .meshcat_provider .unregister_3d_point (item_key )
@@ -842,6 +938,12 @@ def variableTreeWidget_on_right_click(self, item_position):
842938 self .visualized_3d_trajectories .remove (item_key )
843939 item .setForeground (0 , QtGui .QBrush (QtGui .QColor (0 , 0 , 0 )))
844940
941+ if action .text () == remove_3d_arrow_str :
942+ self .meshcat_provider .unregister_3d_arrow (item_key )
943+ self .signal_provider .unregister_3d_arrow (item_key )
944+ self .visualized_3d_arrows .remove (item_key )
945+ item .setForeground (0 , QtGui .QBrush (QtGui .QColor (0 , 0 , 0 )))
946+
845947 if (
846948 use_as_base_orientation_str in action .text ()
847949 or action .text () == use_as_base_position_str
0 commit comments