class Joint(object): def __init__(self, name, sensor_bias, control_bias, gearing_bias, controller): self.name = name self.sensor_bias = sensor_bias self.control_bias = control_bias self.controller = controller self.gearing_bias = gearing_bias print "Initial data for joint ",self.name, " biases=(",self.sensor_bias,", ",self.control_bias,")" self.max_sensor_bias = 3.5 self.min_sensor_bias = -3.5 self.range_sensor_bias = self.max_sensor_bias - self.min_sensor_bias self.max_control_bias = 0.3 self.min_control_bias = -0.3 self.max_gearing_bias = 1.3 self.min_gearing_bias = 0.7 self.range_gearing_bias = self.max_gearing_bias - self.min_gearing_bias self.range_control_bias = self.max_control_bias - self.min_control_bias self.sensor_bias_spinbox = QDoubleSpinBox() self.sensor_bias_spinbox.setDecimals(4); self.sensor_bias_spinbox.setRange(self.min_sensor_bias, self.max_sensor_bias) self.sensor_bias_spinbox.setValue(self.sensor_bias) self.sensor_bias_spinbox.setSingleStep(self.range_sensor_bias/500) self.sensor_bias_spinbox.valueChanged.connect(self.on_biasChanged) self.control_bias_spinbox = QDoubleSpinBox() self.control_bias_spinbox.setDecimals(4); self.control_bias_spinbox.setRange(self.min_control_bias, self.max_control_bias) self.control_bias_spinbox.setSingleStep(self.range_control_bias/50) self.control_bias_spinbox.setValue(self.control_bias) self.control_bias_spinbox.valueChanged.connect(self.on_biasChanged) self.gearing_bias_spinbox = QDoubleSpinBox() self.gearing_bias_spinbox.setDecimals(4); self.gearing_bias_spinbox.setRange(self.min_gearing_bias, self.max_gearing_bias) self.gearing_bias_spinbox.setSingleStep(self.range_gearing_bias/50) self.gearing_bias_spinbox.setValue(self.gearing_bias) self.gearing_bias_spinbox.valueChanged.connect(self.on_biasChanged) def on_biasChanged(self, value): # grab both if either change self.sensor_bias = self.sensor_bias_spinbox.value() self.control_bias = self.control_bias_spinbox.value() self.gearing_bias = self.gearing_bias_spinbox.value() joint_state = JointState() joint_state.name = [self.name]; joint_state.position = [self.sensor_bias]; joint_state.effort = [self.control_bias]; joint_state.velocity = [self.gearing_bias]; print "Set biases:\n ",joint_state self.controller.parent.parent.bias_pub.publish(joint_state) def saveData(self, saveFilePtr): saveFilePtr.write(","+self.name+"/"+str(self.sensor_bias)+"/"+str(self.control_bias)+"/"+str(self.gearing_bias))
class FootstepParamControlWidget(QObject): def __init__(self, context): #super(FootstepParamControlDialog, self).__init__(context) #self.setObjectName('FootstepParamControlDialog') super(FootstepParamControlWidget, self).__init__() self.name = 'FootstepParamControlWidget' #self._widget = QWidget() self._widget = context vbox = QVBoxLayout() ### STEP_COST_ESTIMATOR ######## self.step_cost_vbox = QVBoxLayout() self.step_cost_groupbox = QGroupBox( "Step Cost Estimator" ) self.step_cost_groupbox.setCheckable( True ) self.step_cost_groupbox.setChecked(False) self.step_cost_combobox = QComboBox() self.step_cost_combobox.addItem( "Euclidean" ) self.step_cost_combobox.addItem( "GPR" ) self.step_cost_combobox.addItem( "Map" ) self.step_cost_combobox.addItem( "Boundary" ) self.step_cost_combobox.addItem( "Dynamics" ) self.step_cost_vbox.addWidget( self.step_cost_combobox ) self.step_cost_groupbox.setLayout( self.step_cost_vbox ) vbox.addWidget( self.step_cost_groupbox ) # #HARD ### FOOTSTEP_SET ######## # # parameters for discret footstep planning mode # vigir_atlas_control_msgs/VigirBehaviorStepData[] footstep_set # set of footsteps (displacement vectors (in meter / rad)) # float32[] footstep_cost # cost for each footstep given in footstep set # # #HARD ### LOAD_GPR_STEP_COST ######## # # map step cost file # std_msgs/String map_step_cost_file # # #HARD ### LOAD_MAP_STEP_COST ######## # # destination of gpr file # std_msgs/String gpr_step_cost_file ### COLLISION_CHECK_TYPE ######## self.collision_check_groupbox = QGroupBox( "Collision Check Type" ) self.collision_check_groupbox.setCheckable( True ) self.collision_check_groupbox.setChecked( False) self.collision_check_vbox = QVBoxLayout() self.collision_check_feet_checkbox = QCheckBox( "Feet" ) self.collision_check_vbox.addWidget( self.collision_check_feet_checkbox ) self.collision_check_ub_checkbox = QCheckBox( "Upper Body" ) self.collision_check_vbox.addWidget( self.collision_check_ub_checkbox ) self.collision_check_fc_checkbox = QCheckBox( "Foot Contact Support" ) self.collision_check_vbox.addWidget( self.collision_check_fc_checkbox ) self.collision_check_groupbox.setLayout( self.collision_check_vbox ) vbox.addWidget( self.collision_check_groupbox ) ### FOOT_SIZE ######## self.foot_size_vbox = QVBoxLayout() self.foot_size_groupbox = QGroupBox( "Foot Size" ) self.foot_size_groupbox.setCheckable( True ) self.foot_size_groupbox.setChecked( False ) self.foot_size_hbox = QHBoxLayout() self.foot_size_label = QLabel("Foot Size") self.foot_size_hbox.addWidget( self.foot_size_label ) self.foot_size_x = QDoubleSpinBox() self.foot_size_x.setSingleStep(.01) self.foot_size_hbox.addWidget(self.foot_size_x) self.foot_size_y = QDoubleSpinBox() self.foot_size_y.setSingleStep(.01) self.foot_size_hbox.addWidget(self.foot_size_y) self.foot_size_z = QDoubleSpinBox() self.foot_size_z.setSingleStep(.01) self.foot_size_hbox.addWidget(self.foot_size_z) self.foot_size_vbox.addLayout( self.foot_size_hbox ) self.foot_shift_hbox = QHBoxLayout() self.foot_shift_label = QLabel("Foot Origin Shift") self.foot_shift_hbox.addWidget( self.foot_shift_label ) self.foot_shift_x = QDoubleSpinBox() self.foot_shift_x.setRange(-1.0, 1.0) self.foot_shift_x.setSingleStep(.01) self.foot_shift_hbox.addWidget(self.foot_shift_x) self.foot_shift_y = QDoubleSpinBox() self.foot_shift_y.setRange(-1.0, 1.0) self.foot_shift_y.setSingleStep(.01) self.foot_shift_hbox.addWidget(self.foot_shift_y) self.foot_shift_z = QDoubleSpinBox() self.foot_shift_z.setRange(-1.0, 1.0) self.foot_shift_z.setSingleStep(.01) self.foot_shift_hbox.addWidget(self.foot_shift_z) self.foot_size_vbox.addLayout( self.foot_shift_hbox ) self.foot_size_groupbox.setLayout( self.foot_size_vbox ) vbox.addWidget( self.foot_size_groupbox ) ### UPPER_BODY_SIZE ######## self.upper_vbox = QVBoxLayout() self.upper_groupbox = QGroupBox( "Upper Body Size" ) self.upper_groupbox.setCheckable( True ) self.upper_groupbox.setChecked( False ) self.upper_size_hbox = QHBoxLayout() self.upper_size_label = QLabel("Upper Body Size") self.upper_size_hbox.addWidget( self.upper_size_label ) self.upper_size_x = QDoubleSpinBox() self.upper_size_x.setSingleStep(.01) self.upper_size_hbox.addWidget(self.upper_size_x) self.upper_size_y = QDoubleSpinBox() self.upper_size_y.setSingleStep(.01) self.upper_size_hbox.addWidget(self.upper_size_y) self.upper_size_z = QDoubleSpinBox() self.upper_size_z.setSingleStep(.01) self.upper_size_hbox.addWidget(self.upper_size_z) self.upper_vbox.addLayout( self.upper_size_hbox ) self.upper_origin_hbox = QHBoxLayout() self.upper_origin_label = QLabel("Upper Body Origin") self.upper_origin_hbox.addWidget( self.upper_origin_label ) self.upper_origin_x = QDoubleSpinBox() self.upper_origin_x.setRange(-1.0, 1.0) self.upper_origin_x.setSingleStep(.01) self.upper_origin_hbox.addWidget(self.upper_origin_x) self.upper_origin_y = QDoubleSpinBox() self.upper_origin_y.setRange(-1.0, 1.0) self.upper_origin_y.setSingleStep(.01) self.upper_origin_hbox.addWidget(self.upper_origin_y) self.upper_origin_z = QDoubleSpinBox() self.upper_origin_z.setRange(-1.0, 1.0) self.upper_origin_z.setSingleStep(.01) self.upper_origin_hbox.addWidget(self.upper_origin_z) self.upper_vbox.addLayout( self.upper_origin_hbox ) self.upper_groupbox.setLayout( self.upper_vbox ) vbox.addWidget( self.upper_groupbox ) ### TERRAIN_MODEL ######## self.terrain_model_groupbox = QGroupBox( "Terrain Model" ) self.terrain_model_groupbox.setCheckable( True ) self.terrain_model_groupbox.setChecked( False ) self.terrain_model_vbox = QVBoxLayout() self.terrain_model_checkbox = QCheckBox( "Use Terrain Model" ) self.terrain_model_vbox.addWidget( self.terrain_model_checkbox ) self.terrain_min_ssx_hbox = QHBoxLayout() self.terrain_min_ssx_label = QLabel("Min Sampling Steps x") self.terrain_min_ssx_hbox.addWidget( self.terrain_min_ssx_label ) self.terrain_min_ssx_val = QDoubleSpinBox() self.terrain_min_ssx_val.setSingleStep(1) self.terrain_min_ssx_val.setRange(0,100) self.terrain_min_ssx_hbox.addWidget( self.terrain_min_ssx_val ) self.terrain_model_vbox.addLayout( self.terrain_min_ssx_hbox ) self.terrain_min_ssy_hbox = QHBoxLayout() self.terrain_min_ssy_label = QLabel("Min Sampling Steps y") self.terrain_min_ssy_hbox.addWidget( self.terrain_min_ssy_label ) self.terrain_min_ssy_val = QDoubleSpinBox() self.terrain_min_ssy_val.setSingleStep(1) self.terrain_min_ssy_val.setRange(0,100) self.terrain_min_ssy_hbox.addWidget( self.terrain_min_ssy_val ) self.terrain_model_vbox.addLayout( self.terrain_min_ssy_hbox ) self.terrain_max_ssx_hbox = QHBoxLayout() self.terrain_max_ssx_label = QLabel("Max Sampling Steps x") self.terrain_max_ssx_hbox.addWidget( self.terrain_max_ssx_label ) self.terrain_max_ssx_val = QDoubleSpinBox() self.terrain_max_ssx_val.setSingleStep(1) self.terrain_max_ssx_val.setRange(0,100) self.terrain_max_ssx_hbox.addWidget( self.terrain_max_ssx_val ) self.terrain_model_vbox.addLayout( self.terrain_max_ssx_hbox ) self.terrain_max_ssy_hbox = QHBoxLayout() self.terrain_max_ssy_label = QLabel("Max Sampling Steps y") self.terrain_max_ssy_hbox.addWidget( self.terrain_max_ssy_label ) self.terrain_max_ssy_val = QDoubleSpinBox() self.terrain_max_ssy_val.setSingleStep(1) self.terrain_max_ssy_val.setRange(0,100) self.terrain_max_ssy_hbox.addWidget( self.terrain_max_ssy_val ) self.terrain_model_vbox.addLayout( self.terrain_max_ssy_hbox ) self.terrain_max_iz_hbox = QHBoxLayout() self.terrain_max_iz_label = QLabel("Max Intrusion z") self.terrain_max_iz_hbox.addWidget( self.terrain_max_iz_label ) self.terrain_max_iz_val = QDoubleSpinBox() self.terrain_max_iz_val.setDecimals(4) self.terrain_max_iz_val.setSingleStep(.0001) self.terrain_max_iz_val.setRange(0,.25) self.terrain_max_iz_hbox.addWidget( self.terrain_max_iz_val ) self.terrain_model_vbox.addLayout( self.terrain_max_iz_hbox ) self.terrain_max_gc_hbox = QHBoxLayout() self.terrain_max_gc_label = QLabel("Max Ground Clearance") self.terrain_max_gc_hbox.addWidget( self.terrain_max_gc_label ) self.terrain_max_gc_val = QDoubleSpinBox() self.terrain_max_gc_val.setDecimals(4) self.terrain_max_gc_val.setSingleStep(.0001) self.terrain_max_gc_val.setRange(0,.25) self.terrain_max_gc_hbox.addWidget( self.terrain_max_gc_val ) self.terrain_model_vbox.addLayout( self.terrain_max_gc_hbox ) self.terrain_ms_hbox = QHBoxLayout() self.terrain_ms_label = QLabel("Minimal Support") self.terrain_ms_hbox.addWidget( self.terrain_ms_label ) self.terrain_ms_val = QDoubleSpinBox() self.terrain_ms_val.setDecimals(2) self.terrain_ms_val.setSingleStep(.01) self.terrain_ms_val.setRange(0,1) self.terrain_ms_hbox.addWidget( self.terrain_ms_val ) self.terrain_model_vbox.addLayout( self.terrain_ms_hbox ) self.terrain_model_groupbox.setLayout( self.terrain_model_vbox ) vbox.addWidget( self.terrain_model_groupbox ) ### STANDARD_STEP_PARAMS ######## self.std_step_vbox = QVBoxLayout() self.std_step_groupbox = QGroupBox( "Standard Step Parameters" ) self.std_step_groupbox.setCheckable( True ) self.std_step_groupbox.setChecked( False ) self.foot_sep_hbox = QHBoxLayout() self.foot_sep_label = QLabel("Foot Separation") self.foot_sep_hbox.addWidget( self.foot_sep_label ) self.foot_sep_val = QDoubleSpinBox() self.foot_sep_val.setSingleStep(.01) self.foot_sep_hbox.addWidget(self.foot_sep_val) self.std_step_vbox.addLayout( self.foot_sep_hbox ) self.std_step_step_duration_hbox = QHBoxLayout() self.std_step_step_duration_label = QLabel("Step Duration") self.std_step_step_duration_hbox.addWidget( self.std_step_step_duration_label ) self.std_step_step_duration_val = QDoubleSpinBox() self.std_step_step_duration_val.setSingleStep(.01) self.std_step_step_duration_hbox.addWidget( self.std_step_step_duration_val ) self.std_step_vbox.addLayout( self.std_step_step_duration_hbox ) self.std_step_sway_duration_hbox = QHBoxLayout() self.std_step_sway_duration_label = QLabel("Sway Duration") self.std_step_sway_duration_hbox.addWidget( self.std_step_sway_duration_label ) self.std_step_sway_duration_val = QDoubleSpinBox() self.std_step_sway_duration_val.setSingleStep(.01) self.std_step_sway_duration_hbox.addWidget( self.std_step_sway_duration_val ) self.std_step_vbox.addLayout( self.std_step_sway_duration_hbox ) self.std_step_swing_height_hbox = QHBoxLayout() self.std_step_swing_height_label = QLabel("Swing Height") self.std_step_swing_height_hbox.addWidget( self.std_step_swing_height_label ) self.std_step_swing_height_val = QDoubleSpinBox() self.std_step_swing_height_val.setSingleStep(.01) self.std_step_swing_height_hbox.addWidget( self.std_step_swing_height_val ) self.std_step_vbox.addLayout( self.std_step_swing_height_hbox ) self.std_step_lift_height_hbox = QHBoxLayout() self.std_step_lift_height_label = QLabel("Lift Height") self.std_step_lift_height_hbox.addWidget( self.std_step_lift_height_label ) self.std_step_lift_height_val = QDoubleSpinBox() self.std_step_lift_height_val.setSingleStep(.01) self.std_step_lift_height_hbox.addWidget( self.std_step_lift_height_val ) self.std_step_vbox.addLayout( self.std_step_lift_height_hbox ) self.std_step_groupbox.setLayout( self.std_step_vbox ) vbox.addWidget( self.std_step_groupbox ) button_hbox = QHBoxLayout() button_get = QPushButton("Get Current Values") button_hbox.addWidget( button_get ) button_submit = QPushButton("Send Values") button_hbox.addWidget( button_submit) vbox.addLayout( button_hbox ) vbox.addStretch(1) self._widget.setLayout(vbox) #context.add_widget(self._widget) # publishers and subscribers self.param_pub = rospy.Publisher('/flor/footstep_planner/set_params', FootstepPlannerParams, queue_size=10) button_submit.pressed.connect(self.sendParams) self.param_sub = self.stateSubscriber = rospy.Subscriber('/ros_footstep_planner/params', FootstepPlannerParams, self.getParamCallbackFcn) button_get.pressed.connect(self.getParams) def shutdown_plugin(self): print "Shutdown ..." self.param_pub.unregister() print "Done!" def getParams( self ): msg = FootstepPlannerParams() msg.change_mask = 0 self.param_pub.publish( msg ) def sendParams( self ): msg = FootstepPlannerParams() msg.change_mask = 0 if self.step_cost_groupbox.isChecked(): msg.change_mask = msg.change_mask | 0x001 if self.collision_check_groupbox.isChecked(): msg.change_mask = msg.change_mask | 0x010 if self.foot_size_groupbox.isChecked(): msg.change_mask = msg.change_mask | 0x020 if self.upper_groupbox.isChecked(): msg.change_mask = msg.change_mask | 0x040 if self.std_step_groupbox.isChecked(): msg.change_mask = msg.change_mask | 0x080 if self.terrain_model_groupbox.isChecked(): msg.change_mask = msg.change_mask | 0x100 ### STEP_COST_ESTIMATOR ######## msg.step_cost_type = self.step_cost_combobox.currentIndex() # #HARD ### FOOTSTEP_SET ######## # # parameters for discret footstep planning mode # vigir_atlas_control_msgs/VigirBehaviorStepData[] footstep_set # set of footsteps (displacement vectors (in meter / rad)) # float32[] footstep_cost # cost for each footstep given in footstep set # # #HARD ### LOAD_GPR_STEP_COST ######## # # map step cost file # std_msgs/String map_step_cost_file # # #HARD ### LOAD_MAP_STEP_COST ######## # # destination of gpr file # std_msgs/String gpr_step_cost_file ### COLLISION_CHECK_TYPE ######## msg.collision_check_type = 0 if self.collision_check_feet_checkbox.isChecked(): msg.collision_check_type = msg.collision_check_type | 0x01 if self.collision_check_ub_checkbox.isChecked(): msg.collision_check_type = msg.collision_check_type | 0x02 if self.collision_check_fc_checkbox.isChecked(): msg.collision_check_type = msg.collision_check_type | 0x04 ### FOOT_SIZE ######## msg.foot_size.x = self.foot_size_x.value() msg.foot_size.y = self.foot_size_y.value() msg.foot_size.z = self.foot_size_z.value() msg.foot_origin_shift.x = self.foot_shift_x.value() msg.foot_origin_shift.y = self.foot_shift_y.value() msg.foot_origin_shift.z = self.foot_shift_z.value() ### UPPER_BODY_SIZE ######## msg.upper_body_size.x = self.upper_size_x.value() msg.upper_body_size.y = self.upper_size_y.value() msg.upper_body_size.z = self.upper_size_z.value() msg.upper_body_origin_shift.x = self.upper_origin_x.value() msg.upper_body_origin_shift.y = self.upper_origin_y.value() msg.upper_body_origin_shift.z = self.upper_origin_z.value() ### TERRAIN_MODEL ######## msg.use_terrain_model = self.terrain_model_checkbox.isChecked() msg.min_sampling_steps_x = self.terrain_min_ssx_val.value() msg.min_sampling_steps_y = self.terrain_min_ssy_val.value() msg.max_sampling_steps_x = self.terrain_max_ssx_val.value() msg.max_sampling_steps_y = self.terrain_max_ssy_val.value() msg.max_intrusion_z = self.terrain_max_iz_val.value() msg.max_ground_clearance = self.terrain_max_gc_val.value() msg.minimal_support = self.terrain_ms_val.value() ### STANDARD_STEP_PARAMS ######## msg.foot_seperation = self.foot_sep_val.value() msg.step_duration = self.std_step_step_duration_val.value() msg.sway_duration = self.std_step_sway_duration_val.value() msg.swing_height = self.std_step_swing_height_val.value() msg.lift_height = self.std_step_lift_height_val.value() print msg self.param_pub.publish( msg ) def getParamCallbackFcn(self, msg): ### STEP_COST_ESTIMATOR ######## if msg.change_mask & 0x001: self.step_cost_combobox.setCurrentIndex( msg.step_cost_type ) # #HARD ### FOOTSTEP_SET ######## # # parameters for discret footstep planning mode # vigir_atlas_control_msgs/VigirBehaviorStepData[] footstep_set # set of footsteps (displacement vectors (in meter / rad)) # float32[] footstep_cost # cost for each footstep given in footstep set # # #HARD ### LOAD_GPR_STEP_COST ######## # # map step cost file # std_msgs/String map_step_cost_file # # #HARD ### LOAD_MAP_STEP_COST ######## # # destination of gpr file # std_msgs/String gpr_step_cost_file ### COLLISION_CHECK_TYPE ######## if msg.change_mask & 0x010: self.collision_check_feet_checkbox.setChecked( msg.collision_check_type & 0x01 ) self.collision_check_ub_checkbox.setChecked( msg.collision_check_type & 0x02 ) self.collision_check_fc_checkbox.setChecked( msg.collision_check_type & 0x04 ) ### FOOT_SIZE ######## if msg.change_mask & 0x020: self.foot_size_x.setValue( msg.foot_size.x ) self.foot_size_y.setValue( msg.foot_size.y ) self.foot_size_z.setValue( msg.foot_size.z ) self.foot_shift_x.setValue( msg.foot_origin_shift.x ) self.foot_shift_y.setValue( msg.foot_origin_shift.y ) self.foot_shift_z.setValue( msg.foot_origin_shift.z ) ### UPPER_BODY_SIZE ######## if msg.change_mask & 0x040: self.upper_size_x.setValue( msg.upper_body_size.x ) self.upper_size_y.setValue( msg.upper_body_size.y ) self.upper_size_z.setValue( msg.upper_body_size.z ) self.upper_origin_x.setValue( msg.upper_body_origin_shift.x ) self.upper_origin_y.setValue( msg.upper_body_origin_shift.y ) self.upper_origin_z.setValue( msg.upper_body_origin_shift.z ) ### STANDARD_STEP_PARAMS ######## if msg.change_mask & 0x080: self.foot_sep_val.setValue( msg.foot_seperation ) self.std_step_step_duration_val.setValue( msg.step_duration ) self.std_step_sway_duration_val.setValue( msg.sway_duration ) self.std_step_swing_height_val.setValue( msg.swing_height ) self.std_step_lift_height_val.setValue( msg.lift_height ) ### TERRAIN_MODEL ######## if msg.change_mask & 0x100: self.terrain_model_checkbox.setChecked( msg.use_terrain_model ) self.terrain_min_ssx_val.setValue( msg.min_sampling_steps_x ) self.terrain_min_ssy_val.setValue( msg.min_sampling_steps_y ) self.terrain_max_ssx_val.setValue( msg.max_sampling_steps_x ) self.terrain_max_ssy_val.setValue( msg.max_sampling_steps_y ) self.terrain_max_iz_val.setValue( msg.max_intrusion_z ) self.terrain_max_gc_val.setValue( msg.max_ground_clearance ) self.terrain_ms_val.setValue( msg.minimal_support )
class SpeakEasyGUI(QMainWindow): ''' One instance of this class builds the entire sound play UI. Instance variable that hold widgets of interest to controllers: - C{speechInputFld} - C{onceOrRepeatDict} - C{voicesRadioButtonsDict} - C{recorderDict} - C{programButtonDict} - C{soundButtonDict} ''' # ---------------------- Durations -------------------- # Number of seconds a program button must be pressed to # go into program mode: PROGRAM_BUTTON_HOLD_TIME = 3.0; # Amount of time the program button stays in alternate look # to indicate that it is changing to programming mode: PROGRAM_BUTTON_LOOK_CHANGE_DURATION = 0.2; # seconds # ---------------------- Button and Font Sizes -------------------- # Minimum height of buttons: BUTTON_MIN_HEIGHT = 30; # pixels # Pushbutton minimum font size: BUTTON_LABEL_FONT_SIZE = 16; # pixels # Radio button minimum font size: RADIO_BUTTON_LABEL_FONT_SIZE = 16; # pixels EDIT_FIELD_TEXT_SIZE = 18; # pixels NUM_OF_PROGRAM_BUTTON_COLUMNS = 4; NUM_OF_SOUND_BUTTON_COLUMNS = 4; # ---------------------- Names for Voices ---------------------- # Official names of voices as recognized by the # underlying text-to-speech engines: voices = {'VOICE_1': 'voice_kal_diphone', # Festival voice 'VOICE_2': 'David', # Cepstral voices 'VOICE_3': 'Amy', 'VOICE_4': 'Shouty', 'VOICE_5': 'Whispery', 'VOICE_6': 'Lawrence', 'VOICE_7': 'William' }; # ---------------------- Names for Widgets ---------------------- interactionWidgets = { 'PLAY_ONCE': 'Play once', 'PLAY_REPEATEDLY': 'Play repeatedly', 'PLAY_REPEATEDLY_PERIOD': 'Pause between plays', 'VOICE_1': 'Machine', 'VOICE_2': 'David', 'VOICE_3': 'Amy', 'VOICE_4': 'Shout', 'VOICE_5': 'Whisper', 'VOICE_6': 'Lawrence', 'VOICE_7': 'William', 'PLAY_TEXT': 'Play Text', 'STOP': 'Stop', 'STOP_ALL' : 'Stop All', 'SPEECH_1' : 'Speech 1', 'SPEECH_2' : 'Speech 2', 'SPEECH_3' : 'Speech 3', 'SPEECH_4' : 'Speech 4', 'SPEECH_5' : 'Speech 5', 'SPEECH_6' : 'Speech 6', 'SPEECH_7' : 'Speech 7', 'SPEECH_8' : 'Speech 8', 'SPEECH_9' : 'Speech 9', 'SPEECH_10' : 'Speech 10', 'SPEECH_11' : 'Speech 11', 'SPEECH_12' : 'Speech 12', 'SPEECH_13' : 'Speech 13', 'SPEECH_14' : 'Speech 14', 'SPEECH_15' : 'Speech 15', 'SPEECH_16' : 'Speech 16', 'SPEECH_17' : 'Speech 17', 'SPEECH_18' : 'Speech 18', 'SPEECH_19' : 'Speech 19', 'SPEECH_20' : 'Speech 20', 'SPEECH_21' : 'Speech 21', 'SPEECH_22' : 'Speech 22', 'SPEECH_23' : 'Speech 23', 'SPEECH_24' : 'Speech 24', 'SOUND_1' : 'Rooster', 'SOUND_2' : 'Drill', 'SOUND_3' : 'Bull call', 'SOUND_4' : 'Clown horn', 'SOUND_5' : 'Cash register', 'SOUND_6' : 'Glass breaking', 'SOUND_7' : 'Cell door', 'SOUND_8' : 'Cow', 'SOUND_9' : 'Birds', 'SOUND_10' : 'Big truck', 'SOUND_11' : 'Seagulls', 'SOUND_12' : 'Lift', 'NEW_SPEECH_SET' : 'Save speech set', 'PICK_SPEECH_SET' : 'Pick different speech set', 'PLAY_LOCALLY' : 'Play locally', 'PLAY_AT_ROBOT' : 'Play at robot', 'SPEECH_MODULATION' : 'Speech modulation', 'PASTE' : 'Paste', 'CLEAR' : 'Clear', } # ---------------------- Application Background styling -------------------- # Application background: veryLightBlue = QColor(230, 255,255); stylesheetAppBG = 'QDialog {background-color: %s}' % veryLightBlue.name(); defaultStylesheet = stylesheetAppBG; defaultStylesheetName = "Default"; # ---------------------- Edit field styling ----------------- editFieldBGColor = QColor(12,21,109); editFieldTextColor = QColor(244,244,246); inputFldStylesheet =\ 'TextPanel {background-color: ' + editFieldBGColor.name() +\ '; color: ' + editFieldTextColor.name() +\ '; font-size: ' + str(EDIT_FIELD_TEXT_SIZE) + 'pt' +\ '}'; # ---------------------- Pushbutton styling -------------------- # Button color definitions: recorderButtonBGColor = QColor(176,220,245); # Light blue recorderButtonDisabledBGColor = QColor(187,200,208); # Gray-blue recorderButtonTextColor = QColor(0,0,0); # Black programButtonBGColor = QColor(117,150,169); # Middle blue programButtonTextColor = QColor(251,247,247);# Off-white soundButtonBGColor = QColor(110,134,211); # Dark blue soundButtonTextColor = QColor(251,247,247); # Off-white # Button stylesheets: recorderButtonStylesheet =\ 'QPushButton {background-color: ' + recorderButtonBGColor.name() +\ '; color: ' + recorderButtonTextColor.name() +\ '; font-size: ' + str(BUTTON_LABEL_FONT_SIZE) + 'px' +\ '}'; recorderButtonDisabledStylesheet =\ 'QPushButton {background-color: ' + recorderButtonDisabledBGColor.name() +\ '; color: ' + recorderButtonTextColor.name() +\ '; font-size: ' + str(BUTTON_LABEL_FONT_SIZE) + 'px' +\ '}'; programButtonStylesheet =\ 'QPushButton {background-color: ' + programButtonBGColor.name() +\ '; color: ' + programButtonTextColor.name() +\ '; font-size: ' + str(BUTTON_LABEL_FONT_SIZE) + 'px' +\ '}'; # Stylesheet for when program button look is temporarily # changed to indicate transition to programming mode: programButtonModeTransitionStylesheet =\ 'QPushButton {background-color: ' + editFieldBGColor.name() +\ '; color: ' + programButtonTextColor.name() +\ '; font-size: ' + str(BUTTON_LABEL_FONT_SIZE) + 'px' +\ '}'; soundButtonStylesheet =\ 'QPushButton {background-color: ' + soundButtonBGColor.name() +\ '; color: ' + soundButtonTextColor.name() +\ '; font-size: ' + str(BUTTON_LABEL_FONT_SIZE) + 'px' +\ '}'; # ---------------------- Radiobutton and Play Repeat Delay Spinbox styling ----------------- # Radiobutton color definitions: playOnceRepeatButtonBGColor = QColor(121,229,230); # Very light cyan voicesButtonBGColor = QColor(97,164,165); # Darker cyan playOnceRepeatButtonStylesheet =\ 'font-size: ' + str(RADIO_BUTTON_LABEL_FONT_SIZE) + 'px' +\ '; color: ' + soundButtonTextColor.name() +\ '; background-color: ' + voicesButtonBGColor.name(); playRepeatSpinboxStylesheet =\ 'font-size: ' + str(RADIO_BUTTON_LABEL_FONT_SIZE) + 'px' +\ '; color: ' + soundButtonTextColor.name() +\ '; background-color: ' + voicesButtonBGColor.name(); # voiceButtonStylesheet =\ # 'font-size: ' + str(RADIO_BUTTON_LABEL_FONT_SIZE) + 'px' +\ # '; background-color: ' + voicesButtonBGColor.name(); voiceButtonStylesheet =\ 'font-size: ' + str(RADIO_BUTTON_LABEL_FONT_SIZE) + 'px' +\ '; color: ' + soundButtonTextColor.name() +\ '; background-color: ' + voicesButtonBGColor.name(); # ---------------------- Signals ----------------- hideButtonSignal = pyqtSignal(QPushButton); # hide the given button showButtonSignal = pyqtSignal(QPushButton); # show the hidden button #---------------------------------- # Initializer #-------------- def __init__(self, parent=None, mirrored=True, stand_alone=False, sound_effect_labels=None): super(SpeakEasyGUI, self).__init__(parent); self.stand_alone = stand_alone; self.sound_effect_labels = sound_effect_labels; if (sound_effect_labels is None): raise ValueError("Must pass in non-null array of sound effect button labels."); #self.setMaximumWidth(1360); #self.setMaximumHeight(760); # Vertical box to hold all top level widget groups appLayout = QVBoxLayout(); appWidget = QDialog(); appWidget.setStyleSheet(SpeakEasyGUI.defaultStylesheet); # Activate the window resize handle in the lower right corner # of the app window: appWidget.setSizeGripEnabled(True); self.setCentralWidget(appWidget); self.addTitle(appLayout); self.addTxtInputFld(appLayout); self.buildTapeRecorderButtons(appLayout); self.addOnceOrRepeat_And_VoiceRadioButtons(appLayout); self.buildHorizontalDivider(appLayout); self.buildProgramButtons(appLayout); self.buildSoundButtons(appLayout); self.buildButtonSetControls(appLayout); self.buildOptionsRadioButtons(appLayout); appWidget.setLayout(appLayout); #*******self.connectEvents(); self.show(); #---------------------------------- # programButtonIterator #-------------- def programButtonIterator(self, gridLayout=None): if gridLayout is None: gridLayout = self.programButtonGridLayout; programButtonArray = []; # Collect the buttons into a flat array: for row in range(gridLayout.rowCount()): for col in range(SpeakEasyGUI.NUM_OF_PROGRAM_BUTTON_COLUMNS): layoutItem = gridLayout.itemAtPosition(row, col); if layoutItem is not None: programButtonArray.append(layoutItem.widget()); return iter(programButtonArray); #---------------------------------- # replaceProgramButtons #-------------- def replaceProgramButtons(self, buttonProgramsArray): programButtonObjIt = self.programButtonIterator(); # Remove the existing program buttons from the application's # layout, and mark them for deletion: try: while True: programButtonObj = programButtonObjIt.next(); self.programButtonGridLayout.removeWidget(programButtonObj); programButtonObj.deleteLater(); except StopIteration: pass # Make an array of button labels from the ButtonProgram # instances in buttonProgramsArray: buttonLabelArr = []; for buttonProgram in buttonProgramsArray: buttonLabelArr.append(buttonProgram.getLabel()); # No more program buttons present. Make # new ones, and add them to the grid layout: (newProgramButtonGridLayout, self.programButtonDict) =\ SpeakEasyGUI.buildButtonGrid(buttonLabelArr, SpeakEasyGUI.NUM_OF_PROGRAM_BUTTON_COLUMNS); for buttonObj in self.programButtonDict.values(): buttonObj.setStyleSheet(SpeakEasyGUI.programButtonStylesheet); buttonObj.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); # Transfer the buttons from this new gridlayout object to the # original layout that is embedded in the application Dialog: newButtonsIt = self.programButtonIterator(gridLayout=newProgramButtonGridLayout); try: while True: self.programButtonGridLayout.addWidget(newButtonsIt.next()); except StopIteration: pass; #---------------------------------- # connectEvents #-------------- def connectEvents(self): mousePressEvent.connect(self.textAreaMouseClick); def textAreaMouseClick(self, event): print('Text area clicked.') #---------------------------------- # connectSignalsToWidgets #-------------- # def connectSignalsToWidgets(self): # self.commChannel = CommChannel(); # self.commChannel.hideButtonSignal.connect(SpeakEasyGUI.hideButtonHandler); # self.commChannel.showButtonSignal.connect(SpeakEasyGUI.showButtonHandler); #---------------------------------- # addTitle #-------------- def addTitle(self,layout): title = QLabel("<H1>SpeakEasy</H1>"); hbox = QHBoxLayout(); hbox.addStretch(1); hbox.addWidget(title); hbox.addStretch(1); layout.addLayout(hbox); #---------------------------------- # addTxtInputFld #-------------- def addTxtInputFld(self, layout): ''' Creates text input field label and text field in a horizontal box layout. Adds that hbox layout to the passed-in layout. Sets instance variables: 1. C{self.speechInputFld} @param layout: Layout object to which the label/txt-field C{hbox} is to be added. @type layout: QLayout ''' speechControlsLayout = QHBoxLayout(); speechControlsLayout.addStretch(1); speechInputFldLabel = QLabel("<b>What to say:</b>") speechControlsLayout.addWidget(speechInputFldLabel); self.speechInputFld = TextPanel(numLines=5); self.speechInputFld.setStyleSheet(SpeakEasyGUI.inputFldStylesheet); self.speechInputFld.setFontPointSize(SpeakEasyGUI.EDIT_FIELD_TEXT_SIZE); speechControlsLayout.addWidget(self.speechInputFld); layout.addLayout(speechControlsLayout); # Create and hide the dialog for adding Cepstral voice modulation # markup to text in the text input field: self.speechControls = MarkupManagementUI(textPanel=self.speechInputFld, parent=self); #---------------------------------- # addVoiceRadioButtons #-------------- def addOnceOrRepeat_And_VoiceRadioButtons(self, layout): ''' Creates radio buttons for selecting whether a sound is to play once, or repeatedly until stopped. Also adds radio buttons for selecting voices. Places all in a horizontal box layout. Adds that hbox layout to the passed-in layout. Sets instance variables: 1. C{self.onceOrRepeatDict} 2. C{self.voicesRadioButtonsDict} @param layout: Layout object to which the label/txt-field C{hbox} is to be added. @type layout: QLayout ''' hbox = QHBoxLayout(); (self.onceOrRepeatGroup, onceOrRepeatButtonLayout, self.onceOrRepeatDict) =\ self.buildRadioButtons([SpeakEasyGUI.interactionWidgets['PLAY_ONCE'], SpeakEasyGUI.interactionWidgets['PLAY_REPEATEDLY'] ], Orientation.HORIZONTAL, Alignment.LEFT, activeButtons=[SpeakEasyGUI.interactionWidgets['PLAY_ONCE']], behavior=CheckboxGroupBehavior.RADIO_BUTTONS); self.replayPeriodSpinBox = QDoubleSpinBox(self); self.replayPeriodSpinBox.setRange(0.0, 99.9); # seconds self.replayPeriodSpinBox.setSingleStep(0.5); self.replayPeriodSpinBox.setDecimals(1); onceOrRepeatButtonLayout.addWidget(self.replayPeriodSpinBox); secondsLabel = QLabel("secs delay"); onceOrRepeatButtonLayout.addWidget(secondsLabel); # Create an array of voice radio button labels: voiceRadioButtonLabels = []; for voiceKey in SpeakEasyGUI.voices.keys(): voiceRadioButtonLabels.append(SpeakEasyGUI.interactionWidgets[voiceKey]); (self.voicesGroup, voicesButtonLayout, self.voicesRadioButtonsDict) =\ self.buildRadioButtons(voiceRadioButtonLabels, Orientation.HORIZONTAL, Alignment.RIGHT, activeButtons=[SpeakEasyGUI.interactionWidgets['VOICE_1']], behavior=CheckboxGroupBehavior.RADIO_BUTTONS); # Style all the radio buttons: for playFreqButton in self.onceOrRepeatDict.values(): playFreqButton.setStyleSheet(SpeakEasyGUI.playOnceRepeatButtonStylesheet); for playFreqButton in self.voicesRadioButtonsDict.values(): playFreqButton.setStyleSheet(SpeakEasyGUI.voiceButtonStylesheet); #...and the replay delay spinbox: self.replayPeriodSpinBox.setStyleSheet(SpeakEasyGUI.playRepeatSpinboxStylesheet); #****** replayPeriodSpinBox styling hbox.addLayout(onceOrRepeatButtonLayout); hbox.addStretch(1); hbox.addLayout(voicesButtonLayout); layout.addLayout(hbox); #---------------------------------- # buildTapeRecorderButtons #-------------- def buildTapeRecorderButtons(self, layout): ''' Creates tape recorder buttons (Play Text, Stop,etc.). Places all in a row, though the layout is a QGridLayout. Adds QGridLayout to the passed-in layout. Sets instance variables: 1. C{self.recorderDict} @param layout: Layout object to which the label/txt-field C{QGridlayout} is to be added. @type layout: QLayout ''' (buttonGridLayout, self.recorderButtonDict) =\ SpeakEasyGUI.buildButtonGrid([SpeakEasyGUI.interactionWidgets['PLAY_TEXT'], SpeakEasyGUI.interactionWidgets['STOP'], #SpeakEasyGUI.interactionWidgets['STOP_ALL'] # Stop button already stops all. ], 2); # Two columns for buttonObj in self.recorderButtonDict.values(): buttonObj.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); buttonObj.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); layout.addLayout(buttonGridLayout); #---------------------------------- # buildProgramButtons #-------------- def buildProgramButtons(self, layout): ''' Creates grid of buttons for saving sounds. Adds the resulting QGridLayout to the passed-in layout. Sets instance variables: 1. C{self.programButtonDict} @param layout: Layout object to which the label/txt-field C{QGridlayout} is to be added. @type layout: QLayout ''' buttonLabelArr = []; for i in range(NUM_SPEECH_PROGRAM_BUTTONS): key = "SPEECH_" + str(i+1); buttonLabelArr.append(SpeakEasyGUI.interactionWidgets[key]); (self.programButtonGridLayout, self.programButtonDict) =\ SpeakEasyGUI.buildButtonGrid(buttonLabelArr, SpeakEasyGUI.NUM_OF_PROGRAM_BUTTON_COLUMNS); for buttonObj in self.programButtonDict.values(): buttonObj.setStyleSheet(SpeakEasyGUI.programButtonStylesheet); buttonObj.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); layout.addLayout(self.programButtonGridLayout); #---------------------------------- # buildSoundButtons #-------------- def buildSoundButtons(self, layout): ''' Creates grid of buttons for playing canned sounds. Adds the resulting QGridLayout to the passed-in layout. Sets instance variables: 1. C{self.soundButtonDict} @param layout: Layout object to which the label/txt-field C{QGridlayout} is to be added. @type layout: QLayout ''' for i in range(len(self.sound_effect_labels)): key = "SOUND_" + str(i); SpeakEasyGUI.interactionWidgets[key] = self.sound_effect_labels[i]; (buttonGridLayout, self.soundButtonDict) =\ SpeakEasyGUI.buildButtonGrid(self.sound_effect_labels, SpeakEasyGUI.NUM_OF_SOUND_BUTTON_COLUMNS); for buttonObj in self.soundButtonDict.values(): buttonObj.setStyleSheet(SpeakEasyGUI.soundButtonStylesheet); buttonObj.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); layout.addLayout(buttonGridLayout); #---------------------------------- # buildButtonSetControls #-------------- def buildButtonSetControls(self, layout): buttonLabelArray = [self.interactionWidgets['NEW_SPEECH_SET'], self.interactionWidgets['PICK_SPEECH_SET']]; # Two columns of buttons: (buttonGridLayout, self.speechSetButtonDict) = SpeakEasyGUI.buildButtonGrid(buttonLabelArray, 2); for buttonObj in self.speechSetButtonDict.values(): buttonObj.setStyleSheet(SpeakEasyGUI.programButtonStylesheet); buttonObj.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); layout.addLayout(buttonGridLayout); #---------------------------------- # buildOptionsRadioButtons #-------------- def buildOptionsRadioButtons(self, layout): hbox = QHBoxLayout(); (self.playLocalityGroup, playLocalityButtonLayout, self.playLocalityRadioButtonsDict) =\ self.buildRadioButtons([SpeakEasyGUI.interactionWidgets['PLAY_LOCALLY'], SpeakEasyGUI.interactionWidgets['PLAY_AT_ROBOT'] ], Orientation.HORIZONTAL, Alignment.LEFT, activeButtons=[SpeakEasyGUI.interactionWidgets[DEFAULT_PLAY_LOCATION]], behavior=CheckboxGroupBehavior.RADIO_BUTTONS); #behavior=CheckboxGroupBehavior.CHECKBOXES); # Style all the radio buttons: for playLocalityButton in self.playLocalityRadioButtonsDict.values(): playLocalityButton.setStyleSheet(SpeakEasyGUI.voiceButtonStylesheet); hbox.addLayout(playLocalityButtonLayout); hbox.addStretch(1); self.buildConvenienceButtons(hbox); layout.addLayout(hbox); #---------------------------------- # buildConvenienceButtons #-------------- def buildConvenienceButtons(self, layout): ''' Creates buttons meant for accessibility convenience. Example: Paste. Places all in a row, though the layout is a QGridLayout. Adds QGridLayout to the passed-in layout. Sets instance variables: 1. C{self.convenienceButtonDict} @param layout: Layout object to which the label/txt-field C{QGridlayout} is to be added. @type layout: QLayout ''' (buttonGridLayout, self.convenienceButtonDict) =\ SpeakEasyGUI.buildButtonGrid([SpeakEasyGUI.interactionWidgets['SPEECH_MODULATION'], SpeakEasyGUI.interactionWidgets['PASTE'], SpeakEasyGUI.interactionWidgets['CLEAR'], ], 2); # Two columns for buttonObj in self.convenienceButtonDict.values(): buttonObj.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); buttonObj.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); layout.addLayout(buttonGridLayout); #---------------------------------- # buildHorizontalDivider #-------------- def buildHorizontalDivider(self, layout): frame = QFrame(); frame.setFrameShape(QFrame.HLine); #*******frame.setFrameStyle(QFrame.Shadow.Sunken.value()); frame.setLineWidth(3); frame.setMidLineWidth(3); layout.addWidget(frame); #---------------------------------- # buildRadioButtons #-------------- # Note: Whenever a button is switched on or off it emits the # PySide.QtGui.QAbstractButton.toggled() signal. Connect to this # signal if you want to trigger an action each time the button changes state. def buildRadioButtons(self, labelTextArray, orientation, alignment, activeButtons=None, behavior=CheckboxGroupBehavior.RADIO_BUTTONS): ''' @param labelTextArray: Names of buttons @type labelTextArray: [string] @param orientation: Whether to arrange the buttons vertically or horizontally. @type orientation: Orientation @param alignment: whether buttons should be aligned Left/Center/Right for horizontal, Top/Center/Bottom for vertical:/c @type alignment: Alignment @param activeButtons: Name of the buttons that is to be checked initially. Or None. @type activeButtons: [string] @param behavior: Indicates whether the button group is to behave like Radio Buttons, or like Checkboxes. @type behavior: CheckboxGroupBehavior @return 1. The button group that contains the related buttons. Caller: ensure that this object does not go out of scope. 2. The button layout, which callers will need to add to their own layouts. 3. and a dictionary mapping button names to button objects that were created within this method. This dict is needed by the controller. @rtype (QButtonGroup, QLayout, dict<string,QRadioButton>). ''' # Button control management group. It has no visible # representation. It allows the radio button bahavior, for instance: buttonGroup = QButtonGroup(); if behavior == CheckboxGroupBehavior.CHECKBOXES: buttonGroup.setExclusive(False); else: buttonGroup.setExclusive(True); if orientation == Orientation.VERTICAL: buttonCompLayout = QVBoxLayout(); # Arrange for the alignment (Part 1): if (alignment == Alignment.CENTER) or\ (alignment == Alignment.BOTTOM): buttonCompLayout.addStretch(1); else: buttonCompLayout = QHBoxLayout(); # Arrange for the alignment (Part 1): if (alignment == Alignment.CENTER) or\ (alignment == Alignment.RIGHT): buttonCompLayout.addStretch(1); # Build the buttons: buttonDict = {}; for label in labelTextArray: button = QRadioButton(label); buttonDict[label] = button; # Add button to the button management group: buttonGroup.addButton(button); # Add the button to the visual group: buttonCompLayout.addWidget(button); if label in activeButtons: button.setChecked(True); if orientation == Orientation.VERTICAL: buttonCompLayout = QVBoxLayout(); # Arrange for the alignment (Part 2): if (alignment == Alignment.CENTER) or\ (alignment == Alignment.TOP): buttonCompLayout.addStretch(1); else: # Arrange for the alignment (Part 2): if (alignment == Alignment.CENTER) or\ (alignment == Alignment.LEFT): buttonCompLayout.addStretch(1); return (buttonGroup, buttonCompLayout, buttonDict); #---------------------------------- # buildButtonGrid #-------------- @staticmethod def buildButtonGrid(labelTextArray, numColumns): ''' Creates a grid of QPushButton widgets. They will be @param labelTextArray: Button labels. @type labelTextArray: [string] @param numColumns: The desired width of the button grid. @type numColumns: int @return: 1. a grid layout with the button objects inside. 2. a dictionary mapping button labels to button objects. @rtype: QGridLayout ''' buttonLayout = QGridLayout(); # Compute number of button rows: numRows = len(labelTextArray) / numColumns; # If this number of rows leaves a few buttons left over (< columnNum), # then add a row for those: if (len(labelTextArray) % numColumns) > 0: numRows += 1; buttonDict = {} row = 0; col = 0; for buttonLabel in labelTextArray: button = QPushButton(buttonLabel); buttonDict[buttonLabel] = button; buttonLayout.addWidget(button, row, col); col += 1; if (col > (numColumns - 1)): col = 0; row += 1; return (buttonLayout, buttonDict); #---------------------------------- # getNewButtonLabel #-------------- def getNewButtonLabel(self): ''' Requests a new button label from the user. Returns None if user canceled out, or a string with the new button label. @return: None if user canceled, else string from input field. @rtype: {None | string} ''' prompt = "New label for this button:"; dialogBox = QInputDialog(parent=self); dialogBox.setStyleSheet(SpeakEasyGUI.stylesheetAppBG); dialogBox.setLabelText(prompt); dialogBox.setCancelButtonText("Keep existing label"); userChoice = dialogBox.exec_(); if userChoice == QDialog.Accepted: return dialogBox.textValue(); else: return None; #---------------------------------- # playOnceChecked #-------------- def playOnceChecked(self): return self.onceOrRepeatDict[SpeakEasyGUI.interactionWidgets['PLAY_ONCE']].isChecked(); #---------------------------------- # setPlayOnceChecked #-------------- def setPlayOnceChecked(self): self.onceOrRepeatDict[SpeakEasyGUI.interactionWidgets['PLAY_ONCE']].setChecked(True); #---------------------------------- # playRepeatedlyChecked #-------------- def playRepeatedlyChecked(self): return self.onceOrRepeatDict[SpeakEasyGUI.interactionWidgets['PLAY_REPEATEDLY']].isChecked(); #---------------------------------- # setPlayRepeatedlyChecked #-------------- def setPlayRepeatedlyChecked(self): self.onceOrRepeatDict[SpeakEasyGUI.interactionWidgets['PLAY_REPEATEDLY']].setChecked(True); #---------------------------------- # playRepeatPeriod #-------------- def getPlayRepeatPeriod(self): return self.replayPeriodSpinBox.value(); #---------------------------------- # activeVoice #-------------- def activeVoice(self): ''' Return the official name of the voice that is currently checked in the UI. This is the name that will be recognized by the underlying text-to-speech engine(s). @return: Name of voice as per the SpeakEasyGUI.voices dict. @rtype: string ''' for voiceKey in SpeakEasyGUI.voices.keys(): if self.voicesRadioButtonsDict[SpeakEasyGUI.interactionWidgets[voiceKey]].isChecked(): return SpeakEasyGUI.voices[voiceKey]; #---------------------------------- # whereToPlay #-------------- def whereToPlay(self): ''' Returns which of the play location options is selected: Locally or Robot. @return: Selection of where sound and text-to-speech output is to occur. @rtype: PlayLocation ''' if self.playLocalityRadioButtonsDict[SpeakEasyGUI.interactionWidgets['PLAY_LOCALLY']].isChecked(): return PlayLocation.LOCALLY; else: return PlayLocation.ROBOT; #---------------------------------- # setWhereToPlay #-------------- def setWhereToPlay(self, playLocation): ''' Set the option radio button that determines where sound is produced, locally, or at the robot. No action is taken. This method merely sets the appropriate radio button. @param playLocation: PlayLocation.LOCALLY, or PlayLocation.ROBOT @type playLocation: PlayLocation ''' if playLocation == PlayLocation.LOCALLY: radioButton = self.playLocalityRadioButtonsDict[SpeakEasyGUI.interactionWidgets['PLAY_LOCALLY']]; else: radioButton = self.playLocalityRadioButtonsDict[SpeakEasyGUI.interactionWidgets['PLAY_AT_ROBOT']]; radioButton.setChecked(True); #---------------------------------- # setButtonLabel #-------------- def setButtonLabel(self, buttonObj, label): buttonObj.setText(label); #---------------------------------- # blinkButton #-------------- def blinkButton(self, buttonObj, turnOn): ''' Used to make a program button blink in some way to indicate that it is changing into programming mode. Since this method is triggered by a timer thread, it cannot make any GUI changes. Instead, it sends a signal to have the GUI thread place the button into an alternative look. It then schedules a call to itself for a short time later. At that point it sends a signal to the GUI thread to return the button to its usual look: @param buttonObj: The button to be blinked @type buttonObj: QPushButton @param turnOn: Indicates whether to turn the button back into its normal state, or whether to make it take on its alternate look. @type turnOn: bool ''' if turnOn: self.showButtonSignal.emit(buttonObj); else: self.hideButtonSignal.emit(buttonObj); self.buttonBlinkTimer = Timer(SpeakEasyGUI.PROGRAM_BUTTON_LOOK_CHANGE_DURATION, partial(self.blinkButton, buttonObj, True)); self.buttonBlinkTimer.start();
class FootstepTerrainControlDialog(Plugin): def __init__(self, context): super(FootstepTerrainControlDialog, self).__init__(context) self.setObjectName('FootstepTerrainControlDialog') self.request_seq = 0 self._widget = QWidget() vbox = QVBoxLayout() self.cube_vbox = QVBoxLayout() self.cube_groupbox = QGroupBox( "Terrain Box" ) self.cube_min_hbox = QHBoxLayout() self.cube_min_label = QLabel("Bottom Left") self.cube_min_hbox.addWidget( self.cube_min_label ) self.cube_min_x = QDoubleSpinBox() self.cube_min_x.setSingleStep(.01) self.cube_min_x.setRange(-10.0, 10.0) self.cube_min_x.setValue(-3.0) self.cube_min_hbox.addWidget(self.cube_min_x) self.cube_min_y = QDoubleSpinBox() self.cube_min_y.setSingleStep(.01) self.cube_min_y.setRange(-10.0, 10.0) self.cube_min_y.setValue(-3.0) self.cube_min_hbox.addWidget(self.cube_min_y) self.cube_min_z = QDoubleSpinBox() self.cube_min_z.setSingleStep(.01) self.cube_min_z.setRange(-10.0, 10.0) self.cube_min_z.setValue(-1.0) self.cube_min_hbox.addWidget(self.cube_min_z) self.cube_vbox.addLayout( self.cube_min_hbox ) self.cube_max_hbox = QHBoxLayout() self.cube_max_label = QLabel("Top Right") self.cube_max_hbox.addWidget( self.cube_max_label ) self.cube_max_x = QDoubleSpinBox() self.cube_max_x.setSingleStep(.01) self.cube_max_x.setRange(-10.0, 10.0) self.cube_max_x.setValue(3.0) self.cube_max_hbox.addWidget(self.cube_max_x) self.cube_max_y = QDoubleSpinBox() self.cube_max_y.setSingleStep(.01) self.cube_max_y.setRange(-10.0, 10.0) self.cube_max_y.setValue(3.0) self.cube_max_hbox.addWidget(self.cube_max_y) self.cube_max_z = QDoubleSpinBox() self.cube_max_z.setSingleStep(.01) self.cube_max_z.setRange(-10.0, 10.0) self.cube_max_z.setValue(1.0) self.cube_max_hbox.addWidget(self.cube_max_z) self.cube_vbox.addLayout( self.cube_max_hbox ) self.cube_groupbox.setLayout( self.cube_vbox ) vbox.addWidget( self.cube_groupbox ) self.type_hbox = QHBoxLayout() # self.type_label = QLabel( "Type" ) # self.type_hbox.addWidget( self.type_label ) # # self.type_combobox = QComboBox() # # self.type_combobox.addItem( "Type 1" ) # self.type_combobox.addItem( "Type 2" ) # self.type_combobox.addItem( "Type 3" ) # # self.type_hbox.addWidget( self.type_combobox ) # # vbox.addLayout( self.type_hbox ) self.scan_number_hbox = QHBoxLayout() self.scan_number_label = QLabel("Number of Scans Used") self.scan_number_hbox.addWidget( self.scan_number_label ) self.scan_number_val = QDoubleSpinBox() self.scan_number_val.setDecimals(0) self.scan_number_val.setRange(0,10000) self.scan_number_val.setValue(2000) self.scan_number_hbox.addWidget(self.scan_number_val) vbox.addLayout( self.scan_number_hbox ) # self.use_terrain_checkbox = QCheckBox( "Use Terrain" ) # vbox.addWidget( self.use_terrain_checkbox ) button_hbox = QHBoxLayout() # button_get = QPushButton("Get Current Values") # button_hbox.addWidget( button_get ) button_submit = QPushButton("Send Values") button_hbox.addWidget( button_submit) vbox.addLayout( button_hbox ) vbox.addStretch(1) self._widget.setLayout(vbox) context.add_widget(self._widget) # publishers and subscribers self.terrain_pub = rospy.Publisher("/flor/terrain_classifier/generate_terrain_model", TerrainModelRequest, queue_size=10 ) button_submit.pressed.connect(self.sendParams) # self.terrain_sub = self.stateSubscriber = rospy.Subscriber('/ros_footstep_planner/terrains', FootstepPlannerParams, self.getParamCallbackFcn) # button_submit.pressed.connect(self.getParams) def shutdown_plugin(self): print "Shutdown ..." print "Done!" # def getParams( self ): # msg = FootstepPlannerParams() # # # self.terrain_pub.publish( msg ) def sendParams( self ): msg = TerrainModelRequest() msg.use_default_region_request = False rr = EnvironmentRegionRequest() rr.header.seq = self.request_seq self.request_seq = self.request_seq+1 rr.header.stamp = rospy.get_rostime() rr.header.frame_id = "/world" rr.bounding_box_min.x = self.cube_min_x.value() rr.bounding_box_min.y = self.cube_min_y.value() rr.bounding_box_min.z = self.cube_min_z.value() rr.bounding_box_max.x = self.cube_max_x.value() rr.bounding_box_max.y = self.cube_max_y.value() rr.bounding_box_max.z = self.cube_max_z.value() rr.resolution = 0 rr.request_augment = 0 msg.region_req = rr msg.aggregation_size = self.scan_number_val.value() print msg self.terrain_pub.publish( msg ) def getParamCallbackFcn(self, msg): print "Not Defined Yet"
class SensorParamControlDialog(Plugin): def __init__(self, context): super(SensorParamControlDialog, self).__init__(context) self.setObjectName('SensorParamControlDialog') self._widget = QWidget() vbox = QVBoxLayout() ### Multisense ### ms_groupbox = QGroupBox( "Multisense" ) ms_vbox = QVBoxLayout() ms_gain_hbox = QHBoxLayout() self.ms_gain_label = QLabel("Image Gain [1, 1, 8]") ms_gain_hbox.addWidget( self.ms_gain_label ) self.ms_gain = QDoubleSpinBox() self.ms_gain.setSingleStep(.01) self.ms_gain.setRange(1,8) ms_gain_hbox.addWidget( self.ms_gain ) ms_vbox.addLayout( ms_gain_hbox ) ms_exp_hbox = QHBoxLayout() self.ms_exp_auto = QCheckBox("Image Exposure [.03, 0.5]") ms_exp_hbox.addWidget( self.ms_exp_auto ) self.ms_exp = QDoubleSpinBox() self.ms_exp.setSingleStep( .001 ) self.ms_exp.setRange( .025,.5 ) ms_exp_hbox.addWidget( self.ms_exp ) ms_vbox.addLayout( ms_exp_hbox ) ms_spindle_hbox = QHBoxLayout() ms_spindle_label = QLabel("Spindle Speed [0, 5.2]") ms_spindle_hbox.addWidget( ms_spindle_label ) self.ms_spindle = QDoubleSpinBox() self.ms_spindle.setSingleStep(.01) self.ms_spindle.setRange( 0,15.2 ) ms_spindle_hbox.addWidget( self.ms_spindle ) ms_vbox.addLayout( ms_spindle_hbox ) ms_light_hbox = QHBoxLayout() ms_light_label = QLabel("Light Brightness") ms_light_hbox.addWidget(ms_light_label) self.ms_light = QSlider(Qt.Horizontal) self.ms_light.setRange(0,100) ms_light_hbox.addWidget( self.ms_light ) ms_vbox.addLayout( ms_light_hbox ) ms_button_hbox = QHBoxLayout() ms_button_hbox.addStretch(1) ms_button_get = QPushButton("Get Settings") ms_button_get.pressed.connect(self.ms_get_callback) #ms_button_hbox.addWidget( ms_button_get ) ms_button_set = QPushButton("Set Settings") ms_button_set.pressed.connect(self.ms_set_callback) ms_button_hbox.addWidget( ms_button_set ) ms_vbox.addLayout( ms_button_hbox ) ms_groupbox.setLayout( ms_vbox ) vbox.addWidget( ms_groupbox ) ### Left SA ### sa_left_groupbox = QGroupBox( "Left SA Camera" ) sa_left_vbox = QVBoxLayout() sa_left_gain_hbox = QHBoxLayout() sa_left_gain_label = QLabel("Image Gain [0, 0, 25]") sa_left_gain_hbox.addWidget( sa_left_gain_label ) self.sa_left_gain = QDoubleSpinBox() self.sa_left_gain.setSingleStep(.01) self.sa_left_gain.setRange( 0, 25 ) sa_left_gain_hbox.addWidget( self.sa_left_gain ) sa_left_vbox.addLayout( sa_left_gain_hbox ) sa_left_exp_hbox = QHBoxLayout() sa_left_exp_label = QLabel("Image Shutter [0, 5.5, 25]") sa_left_exp_hbox.addWidget( sa_left_exp_label ) self.sa_left_exp = QDoubleSpinBox() self.sa_left_exp.setSingleStep(.01) self.sa_left_exp.setRange( 0, 25 ) sa_left_exp_hbox.addWidget( self.sa_left_exp ) sa_left_vbox.addLayout( sa_left_exp_hbox ) sa_left_button_hbox = QHBoxLayout() sa_left_button_hbox.addStretch(1) sa_left_button_get = QPushButton("Get Settings") sa_left_button_get.pressed.connect(self.sa_left_get_callback) #sa_left_button_hbox.addWidget( sa_left_button_get ) sa_left_button_set = QPushButton("Set Settings") sa_left_button_set.pressed.connect(self.sa_left_set_callback) sa_left_button_hbox.addWidget( sa_left_button_set ) sa_left_vbox.addLayout( sa_left_button_hbox ) sa_left_groupbox.setLayout( sa_left_vbox ) vbox.addWidget(sa_left_groupbox) ### Right SA ### sa_right_groupbox = QGroupBox( "Right SA Camera" ) sa_right_vbox = QVBoxLayout() sa_right_gain_hbox = QHBoxLayout() sa_right_gain_label = QLabel("Image Gain [0, 0, 25]") sa_right_gain_hbox.addWidget( sa_right_gain_label ) self.sa_right_gain = QDoubleSpinBox() self.sa_right_gain.setSingleStep(.01) self.sa_right_gain.setRange( 0, 25 ) sa_right_gain_hbox.addWidget( self.sa_right_gain ) sa_right_vbox.addLayout( sa_right_gain_hbox ) sa_right_exp_hbox = QHBoxLayout() sa_right_exp_label = QLabel("Image Shutter [0, 5.5, 25]") sa_right_exp_hbox.addWidget( sa_right_exp_label ) self.sa_right_exp = QDoubleSpinBox() self.sa_right_exp.setSingleStep(.01) self.sa_right_exp.setRange( 0, 25 ) sa_right_exp_hbox.addWidget( self.sa_right_exp ) sa_right_vbox.addLayout( sa_right_exp_hbox ) sa_right_button_hbox = QHBoxLayout() sa_right_button_hbox.addStretch(1) sa_right_button_get = QPushButton("Get Settings") sa_right_button_get.pressed.connect(self.sa_right_get_callback) #sa_right_button_hbox.addWidget( sa_right_button_get ) sa_right_button_set = QPushButton("Set Settings") sa_right_button_set.pressed.connect(self.sa_right_set_callback) sa_right_button_hbox.addWidget( sa_right_button_set ) sa_right_vbox.addLayout( sa_right_button_hbox ) sa_right_groupbox.setLayout( sa_right_vbox ) vbox.addWidget(sa_right_groupbox) vbox.addStretch(1) self._widget.setLayout(vbox) context.add_widget(self._widget) # publishers and subscribers self.ms_cam_pub = rospy.Publisher( '/multisense_sl/set_cam_parameters', Float64MultiArray, queue_size=10) self.ms_light_pub = rospy.Publisher( '/multisense_sl/set_light_brightness', Float64, queue_size=10) self.ms_spindle_pub = rospy.Publisher( '/multisense_sl/set_spindle_speed', Float64, queue_size=10) self.sa_left_cam_pub = rospy.Publisher( '/sa/left/set_cam_parameters', Float64MultiArray, queue_size=10) self.sa_right_cam_pub = rospy.Publisher( '/sa/right/set_cam_parameters', Float64MultiArray, queue_size=10) # self.param_sub = self.stateSubscriber = rospy.Subscriber('/ros_footstep_planner/params', FootstepPlannerParams, self.getParamCallbackFcn) def shutdown_plugin(self): print "Shutdown ..." # self.param_pub.unregister() print "Done!" def ms_get_callback(self): print "fill values" def ms_set_callback(self): ms_cam = Float64MultiArray() ms_cam_dim_h = MultiArrayDimension() ms_cam_dim_h.label = "height" ms_cam_dim_h.size = 1 ms_cam_dim_h.stride = 2 ms_cam.layout.dim.append( ms_cam_dim_h ) ms_cam_dim_w = MultiArrayDimension() ms_cam_dim_w.label = "width" ms_cam_dim_w.size = 2 ms_cam_dim_w.stride = 2 ms_cam.layout.dim.append(ms_cam_dim_w) ms_cam.data.append( self.ms_gain.value() ) if self.ms_exp_auto.isChecked() : ms_cam.data.append( 1 ) else: ms_cam.data.append( self.ms_exp.value() ) self.ms_cam_pub.publish( ms_cam ) light = Float64() light.data = self.ms_light.value()/100.0 self.ms_light_pub.publish( light ) spindle_speed = Float64() spindle_speed.data = self.ms_spindle.value() self.ms_spindle_pub.publish( spindle_speed ) def sa_left_get_callback(self): print "fill values" def sa_left_set_callback(self): sa_left_cam = Float64MultiArray() sa_left_cam_dim_h = MultiArrayDimension() sa_left_cam_dim_h.label = "height" sa_left_cam_dim_h.size = 1 sa_left_cam_dim_h.stride = 2 sa_left_cam.layout.dim.append( sa_left_cam_dim_h ) sa_left_cam_dim_w = MultiArrayDimension() sa_left_cam_dim_w.label = "width" sa_left_cam_dim_w.size = 2 sa_left_cam_dim_w.stride = 2 sa_left_cam.layout.dim.append(sa_left_cam_dim_w) sa_left_cam.data.append( self.sa_left_gain.value() ) sa_left_cam.data.append( self.sa_left_exp.value() ) self.sa_left_cam_pub.publish( sa_left_cam ) def sa_right_get_callback(self): print "fill values" def sa_right_set_callback(self): sa_right_cam = Float64MultiArray() sa_right_cam_dim_h = MultiArrayDimension() sa_right_cam_dim_h.label = "height" sa_right_cam_dim_h.size = 1 sa_right_cam_dim_h.stride = 2 sa_right_cam.layout.dim.append( sa_right_cam_dim_h ) sa_right_cam_dim_w = MultiArrayDimension() sa_right_cam_dim_w.label = "width" sa_right_cam_dim_w.size = 2 sa_right_cam_dim_w.stride = 2 sa_right_cam.layout.dim.append(sa_right_cam_dim_w) sa_right_cam.data.append( self.sa_right_gain.value() ) sa_right_cam.data.append( self.sa_right_exp.value() ) self.sa_right_cam_pub.publish( sa_right_cam )