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