00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 from __future__ import division
00032 import os
00033 import rospkg
00034
00035 from geometry_msgs.msg import Twist
00036 import rospy
00037 from python_qt_binding import loadUi
00038 from python_qt_binding.QtCore import Qt, QTimer, Slot
00039 from python_qt_binding.QtGui import QKeySequence
00040 from python_qt_binding.QtWidgets import QShortcut, QWidget
00041 from rqt_gui_py.plugin import Plugin
00042
00043
00044 class RobotSteering(Plugin):
00045
00046 slider_factor = 1000.0
00047
00048 def __init__(self, context):
00049 super(RobotSteering, self).__init__(context)
00050 self.setObjectName('RobotSteering')
00051
00052 self._publisher = None
00053
00054 self._widget = QWidget()
00055 rp = rospkg.RosPack()
00056 ui_file = os.path.join(rp.get_path('rqt_robot_steering'), 'resource', 'RobotSteering.ui')
00057 loadUi(ui_file, self._widget)
00058 self._widget.setObjectName('RobotSteeringUi')
00059 if context.serial_number() > 1:
00060 self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))
00061 context.add_widget(self._widget)
00062
00063 self._widget.topic_line_edit.textChanged.connect(self._on_topic_changed)
00064 self._widget.stop_push_button.pressed.connect(self._on_stop_pressed)
00065
00066 self._widget.x_linear_slider.valueChanged.connect(self._on_x_linear_slider_changed)
00067 self._widget.z_angular_slider.valueChanged.connect(self._on_z_angular_slider_changed)
00068
00069 self._widget.increase_x_linear_push_button.pressed.connect(self._on_strong_increase_x_linear_pressed)
00070 self._widget.reset_x_linear_push_button.pressed.connect(self._on_reset_x_linear_pressed)
00071 self._widget.decrease_x_linear_push_button.pressed.connect(self._on_strong_decrease_x_linear_pressed)
00072 self._widget.increase_z_angular_push_button.pressed.connect(self._on_strong_increase_z_angular_pressed)
00073 self._widget.reset_z_angular_push_button.pressed.connect(self._on_reset_z_angular_pressed)
00074 self._widget.decrease_z_angular_push_button.pressed.connect(self._on_strong_decrease_z_angular_pressed)
00075
00076 self._widget.max_x_linear_double_spin_box.valueChanged.connect(self._on_max_x_linear_changed)
00077 self._widget.min_x_linear_double_spin_box.valueChanged.connect(self._on_min_x_linear_changed)
00078 self._widget.max_z_angular_double_spin_box.valueChanged.connect(self._on_max_z_angular_changed)
00079 self._widget.min_z_angular_double_spin_box.valueChanged.connect(self._on_min_z_angular_changed)
00080
00081 self.shortcut_w = QShortcut(QKeySequence(Qt.Key_W), self._widget)
00082 self.shortcut_w.setContext(Qt.ApplicationShortcut)
00083 self.shortcut_w.activated.connect(self._on_increase_x_linear_pressed)
00084 self.shortcut_x = QShortcut(QKeySequence(Qt.Key_X), self._widget)
00085 self.shortcut_x.setContext(Qt.ApplicationShortcut)
00086 self.shortcut_x.activated.connect(self._on_reset_x_linear_pressed)
00087 self.shortcut_s = QShortcut(QKeySequence(Qt.Key_S), self._widget)
00088 self.shortcut_s.setContext(Qt.ApplicationShortcut)
00089 self.shortcut_s.activated.connect(self._on_decrease_x_linear_pressed)
00090 self.shortcut_a = QShortcut(QKeySequence(Qt.Key_A), self._widget)
00091 self.shortcut_a.setContext(Qt.ApplicationShortcut)
00092 self.shortcut_a.activated.connect(self._on_increase_z_angular_pressed)
00093 self.shortcut_z = QShortcut(QKeySequence(Qt.Key_Z), self._widget)
00094 self.shortcut_z.setContext(Qt.ApplicationShortcut)
00095 self.shortcut_z.activated.connect(self._on_reset_z_angular_pressed)
00096 self.shortcut_d = QShortcut(QKeySequence(Qt.Key_D), self._widget)
00097 self.shortcut_d.setContext(Qt.ApplicationShortcut)
00098 self.shortcut_d.activated.connect(self._on_decrease_z_angular_pressed)
00099
00100 self.shortcut_shift_w = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_W), self._widget)
00101 self.shortcut_shift_w.setContext(Qt.ApplicationShortcut)
00102 self.shortcut_shift_w.activated.connect(self._on_strong_increase_x_linear_pressed)
00103 self.shortcut_shift_x = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_X), self._widget)
00104 self.shortcut_shift_x.setContext(Qt.ApplicationShortcut)
00105 self.shortcut_shift_x.activated.connect(self._on_reset_x_linear_pressed)
00106 self.shortcut_shift_s = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_S), self._widget)
00107 self.shortcut_shift_s.setContext(Qt.ApplicationShortcut)
00108 self.shortcut_shift_s.activated.connect(self._on_strong_decrease_x_linear_pressed)
00109 self.shortcut_shift_a = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_A), self._widget)
00110 self.shortcut_shift_a.setContext(Qt.ApplicationShortcut)
00111 self.shortcut_shift_a.activated.connect(self._on_strong_increase_z_angular_pressed)
00112 self.shortcut_shift_z = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Z), self._widget)
00113 self.shortcut_shift_z.setContext(Qt.ApplicationShortcut)
00114 self.shortcut_shift_z.activated.connect(self._on_reset_z_angular_pressed)
00115 self.shortcut_shift_d = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_D), self._widget)
00116 self.shortcut_shift_d.setContext(Qt.ApplicationShortcut)
00117 self.shortcut_shift_d.activated.connect(self._on_strong_decrease_z_angular_pressed)
00118
00119 self.shortcut_space = QShortcut(QKeySequence(Qt.Key_Space), self._widget)
00120 self.shortcut_space.setContext(Qt.ApplicationShortcut)
00121 self.shortcut_space.activated.connect(self._on_stop_pressed)
00122 self.shortcut_space = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Space), self._widget)
00123 self.shortcut_space.setContext(Qt.ApplicationShortcut)
00124 self.shortcut_space.activated.connect(self._on_stop_pressed)
00125
00126 self._widget.stop_push_button.setToolTip(self._widget.stop_push_button.toolTip() + ' ' + self.tr('([Shift +] Space)'))
00127 self._widget.increase_x_linear_push_button.setToolTip(self._widget.increase_x_linear_push_button.toolTip() + ' ' + self.tr('([Shift +] W)'))
00128 self._widget.reset_x_linear_push_button.setToolTip(self._widget.reset_x_linear_push_button.toolTip() + ' ' + self.tr('([Shift +] X)'))
00129 self._widget.decrease_x_linear_push_button.setToolTip(self._widget.decrease_x_linear_push_button.toolTip() + ' ' + self.tr('([Shift +] S)'))
00130 self._widget.increase_z_angular_push_button.setToolTip(self._widget.increase_z_angular_push_button.toolTip() + ' ' + self.tr('([Shift +] A)'))
00131 self._widget.reset_z_angular_push_button.setToolTip(self._widget.reset_z_angular_push_button.toolTip() + ' ' + self.tr('([Shift +] Z)'))
00132 self._widget.decrease_z_angular_push_button.setToolTip(self._widget.decrease_z_angular_push_button.toolTip() + ' ' + self.tr('([Shift +] D)'))
00133
00134
00135 self._update_parameter_timer = QTimer(self)
00136 self._update_parameter_timer.timeout.connect(self._on_parameter_changed)
00137 self._update_parameter_timer.start(100)
00138 self.zero_cmd_sent = False
00139
00140 @Slot(str)
00141 def _on_topic_changed(self, topic):
00142 topic = str(topic)
00143 self._unregister_publisher()
00144 if topic == '':
00145 return
00146 try:
00147 self._publisher = rospy.Publisher(topic, Twist, queue_size=10)
00148 except TypeError:
00149 self._publisher = rospy.Publisher(topic, Twist)
00150
00151 def _on_stop_pressed(self):
00152 self._widget.x_linear_slider.setValue(0)
00153 self._widget.z_angular_slider.setValue(0)
00154
00155 def _on_x_linear_slider_changed(self):
00156 self._widget.current_x_linear_label.setText('%0.2f m/s' % (self._widget.x_linear_slider.value() / RobotSteering.slider_factor))
00157 self._on_parameter_changed()
00158
00159 def _on_z_angular_slider_changed(self):
00160 self._widget.current_z_angular_label.setText('%0.2f rad/s' % (self._widget.z_angular_slider.value() / RobotSteering.slider_factor))
00161 self._on_parameter_changed()
00162
00163 def _on_increase_x_linear_pressed(self):
00164 self._widget.x_linear_slider.setValue(self._widget.x_linear_slider.value() + self._widget.x_linear_slider.singleStep())
00165
00166 def _on_reset_x_linear_pressed(self):
00167 self._widget.x_linear_slider.setValue(0)
00168
00169 def _on_decrease_x_linear_pressed(self):
00170 self._widget.x_linear_slider.setValue(self._widget.x_linear_slider.value() - self._widget.x_linear_slider.singleStep())
00171
00172 def _on_increase_z_angular_pressed(self):
00173 self._widget.z_angular_slider.setValue(self._widget.z_angular_slider.value() + self._widget.z_angular_slider.singleStep())
00174
00175 def _on_reset_z_angular_pressed(self):
00176 self._widget.z_angular_slider.setValue(0)
00177
00178 def _on_decrease_z_angular_pressed(self):
00179 self._widget.z_angular_slider.setValue(self._widget.z_angular_slider.value() - self._widget.z_angular_slider.singleStep())
00180
00181 def _on_max_x_linear_changed(self, value):
00182 self._widget.x_linear_slider.setMaximum(value * RobotSteering.slider_factor)
00183
00184 def _on_min_x_linear_changed(self, value):
00185 self._widget.x_linear_slider.setMinimum(value * RobotSteering.slider_factor)
00186
00187 def _on_max_z_angular_changed(self, value):
00188 self._widget.z_angular_slider.setMaximum(value * RobotSteering.slider_factor)
00189
00190 def _on_min_z_angular_changed(self, value):
00191 self._widget.z_angular_slider.setMinimum(value * RobotSteering.slider_factor)
00192
00193 def _on_strong_increase_x_linear_pressed(self):
00194 self._widget.x_linear_slider.setValue(self._widget.x_linear_slider.value() + self._widget.x_linear_slider.pageStep())
00195
00196 def _on_strong_decrease_x_linear_pressed(self):
00197 self._widget.x_linear_slider.setValue(self._widget.x_linear_slider.value() - self._widget.x_linear_slider.pageStep())
00198
00199 def _on_strong_increase_z_angular_pressed(self):
00200 self._widget.z_angular_slider.setValue(self._widget.z_angular_slider.value() + self._widget.z_angular_slider.pageStep())
00201
00202 def _on_strong_decrease_z_angular_pressed(self):
00203 self._widget.z_angular_slider.setValue(self._widget.z_angular_slider.value() - self._widget.z_angular_slider.pageStep())
00204
00205 def _on_parameter_changed(self):
00206 self._send_twist(self._widget.x_linear_slider.value() / RobotSteering.slider_factor, self._widget.z_angular_slider.value() / RobotSteering.slider_factor)
00207
00208 def _send_twist(self, x_linear, z_angular):
00209 if self._publisher is None:
00210 return
00211 twist = Twist()
00212 twist.linear.x = x_linear
00213 twist.linear.y = 0
00214 twist.linear.z = 0
00215 twist.angular.x = 0
00216 twist.angular.y = 0
00217 twist.angular.z = z_angular
00218
00219
00220 if x_linear == 0 and z_angular == 0:
00221 if not self.zero_cmd_sent:
00222 self.zero_cmd_sent = True
00223 self._publisher.publish(twist)
00224 else:
00225 self.zero_cmd_sent = False
00226 self._publisher.publish(twist)
00227
00228 def _unregister_publisher(self):
00229 if self._publisher is not None:
00230 self._publisher.unregister()
00231 self._publisher = None
00232
00233 def shutdown_plugin(self):
00234 self._update_parameter_timer.stop()
00235 self._unregister_publisher()
00236
00237 def save_settings(self, plugin_settings, instance_settings):
00238 instance_settings.set_value('topic' , self._widget.topic_line_edit.text())
00239 instance_settings.set_value('vx_max', self._widget.max_x_linear_double_spin_box.value())
00240 instance_settings.set_value('vx_min', self._widget.min_x_linear_double_spin_box.value())
00241 instance_settings.set_value('vw_max', self._widget.max_z_angular_double_spin_box.value())
00242 instance_settings.set_value('vw_min', self._widget.min_z_angular_double_spin_box.value())
00243
00244 def restore_settings(self, plugin_settings, instance_settings):
00245
00246 value = instance_settings.value('topic', "/cmd_vel")
00247 value = rospy.get_param("~default_topic", value)
00248 self._widget.topic_line_edit.setText(value)
00249
00250 value = self._widget.max_x_linear_double_spin_box.value()
00251 value = instance_settings.value( 'vx_max', value)
00252 value = rospy.get_param("~default_vx_max", value)
00253 self._widget.max_x_linear_double_spin_box.setValue(float(value))
00254
00255 value = self._widget.min_x_linear_double_spin_box.value()
00256 value = instance_settings.value( 'vx_min', value)
00257 value = rospy.get_param("~default_vx_min", value)
00258 self._widget.min_x_linear_double_spin_box.setValue(float(value))
00259
00260 value = self._widget.max_z_angular_double_spin_box.value()
00261 value = instance_settings.value( 'vw_max', value)
00262 value = rospy.get_param("~default_vw_max", value)
00263 self._widget.max_z_angular_double_spin_box.setValue(float(value))
00264
00265 value = self._widget.min_z_angular_double_spin_box.value()
00266 value = instance_settings.value( 'vw_min', value)
00267 value = rospy.get_param("~default_vw_min", value)
00268 self._widget.min_z_angular_double_spin_box.setValue(float(value))
00269
00270
00271
00272
00273
00274
00275
00276