Skip to content

Commit 1ce10de

Browse files
committed
rviz_plugin_tutorials: drive_widget documentation
1 parent d630f69 commit 1ce10de

File tree

2 files changed

+61
-7
lines changed

2 files changed

+61
-7
lines changed

rviz_plugin_tutorials/src/drive_widget.cpp

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,18 @@ DriveWidget::DriveWidget( QWidget* parent )
4242
: QWidget( parent )
4343
, linear_velocity_( 0 )
4444
, angular_velocity_( 0 )
45-
, linear_max_( 10 )
46-
, angular_max_( 2 )
45+
, linear_scale_( 10 )
46+
, angular_scale_( 2 )
4747
{
4848
}
4949

50+
// This paintEvent() is complex because of the drawing of the two
51+
// wheel arc-arrows.
5052
void DriveWidget::paintEvent( QPaintEvent* event )
5153
{
54+
// The background color and crosshair lines are drawn differently
55+
// depending on whether this widget is enabled or not. This gives a
56+
// nice visual indication of whether the control is "live".
5257
QColor background;
5358
QColor crosshair;
5459
if( isEnabled() )
@@ -61,6 +66,10 @@ void DriveWidget::paintEvent( QPaintEvent* event )
6166
background = Qt::lightGray;
6267
crosshair = Qt::darkGray;
6368
}
69+
70+
// The main visual is a square, centered in the widget's area. Here
71+
// we compute the size of the square and the horizontal and vertical
72+
// offsets of it.
6473
int w = width();
6574
int h = height();
6675
int size = (( w > h ) ? h : w) - 1;
@@ -70,10 +79,17 @@ void DriveWidget::paintEvent( QPaintEvent* event )
7079
QPainter painter( this );
7180
painter.setBrush( background );
7281
painter.setPen( crosshair );
82+
83+
// Draw the background square.
7384
painter.drawRect( QRect( hpad, vpad, size, size ));
85+
86+
// Draw a cross-hair inside the square.
7487
painter.drawLine( hpad, height() / 2, hpad + size, height() / 2 );
7588
painter.drawLine( width() / 2, vpad, width() / 2, vpad + size );
7689

90+
// If the widget is enabled and the velocities are not zero, draw
91+
// some sweet green arrows showing possible paths that the wheels of
92+
// a diff-drive robot would take if it stayed at these velocities.
7793
if( isEnabled() && (angular_velocity_ != 0 || linear_velocity_ != 0 ))
7894
{
7995
QPen arrow;
@@ -83,6 +99,10 @@ void DriveWidget::paintEvent( QPaintEvent* event )
8399
arrow.setJoinStyle( Qt::RoundJoin );
84100
painter.setPen( arrow );
85101

102+
// This code steps along a central arc defined by the linear and
103+
// angular velocites. At each step, it computes where the left
104+
// and right wheels would be and collecting the resulting points
105+
// in the left_track and right_track arrays.
86106
int step_count = 100;
87107
QPointF left_track[ step_count ];
88108
QPointF right_track[ step_count ];
@@ -97,7 +117,7 @@ void DriveWidget::paintEvent( QPaintEvent* event )
97117
right_track[ 0 ].setY( cy );
98118
float angle = M_PI/2;
99119
float delta_angle = angular_velocity_ / step_count;
100-
float step_dist = linear_velocity_ * size/2 / linear_max_ / step_count;
120+
float step_dist = linear_velocity_ * size/2 / linear_scale_ / step_count;
101121
for( int step = 1; step < step_count; step++ )
102122
{
103123
angle += delta_angle / 2;
@@ -113,15 +133,23 @@ void DriveWidget::paintEvent( QPaintEvent* event )
113133
cx = next_cx;
114134
cy = next_cy;
115135
}
136+
// Now the track arrays are filled, so stroke each with a fat green line.
116137
painter.drawPolyline( left_track, step_count );
117138
painter.drawPolyline( right_track, step_count );
118139

140+
// Here we decide which direction each arrowhead will point
141+
// (forward or backward). This works by comparing the arc length
142+
// travelled by the center in one step (step_dist) with the arc
143+
// length travelled by the wheel (half_track_width * delta_angle).
119144
int left_arrow_dir = (-step_dist + half_track_width * delta_angle > 0);
120145
int right_arrow_dir = (-step_dist - half_track_width * delta_angle > 0);
121146

147+
// Use MiterJoin for the arrowheads so we get a nice sharp point.
122148
arrow.setJoinStyle( Qt::MiterJoin );
123149
painter.setPen( arrow );
124150

151+
// Compute and draw polylines for each arrowhead. This code could
152+
// probably be more elegant.
125153
float head_len = size / 8.0;
126154
QPointF arrow_head[ 3 ];
127155
float x, y;
@@ -152,6 +180,9 @@ void DriveWidget::paintEvent( QPaintEvent* event )
152180
}
153181
}
154182

183+
// Every mouse move event received here sends a velocity because Qt
184+
// only sends us mouse move events if there was previously a
185+
// mouse-down event while in the widget.
155186
void DriveWidget::mouseMoveEvent( QMouseEvent* event )
156187
{
157188
sendVelocitiesFromMouse( event->x(), event->y(), width(), height() );
@@ -162,19 +193,27 @@ void DriveWidget::mousePressEvent( QMouseEvent* event )
162193
sendVelocitiesFromMouse( event->x(), event->y(), width(), height() );
163194
}
164195

196+
// When the mouse leaves the widget but the button is still held down,
197+
// we don't get the leaveEvent(). However, when the mouse drags out
198+
// of the widget and then other buttons are pressed (or possibly other
199+
// window-manager things happen), we will get a leaveEvent() but not a
200+
// mouseReleaseEvent(). Without this you can have a robot stuck "on"
201+
// without the user controlling it.
165202
void DriveWidget::leaveEvent( QEvent* event )
166203
{
167204
stop();
168205
}
169206

207+
// Compute and emit linear and angular velocities based on Y and X
208+
// mouse positions relative to the central square.
170209
void DriveWidget::sendVelocitiesFromMouse( int x, int y, int width, int height )
171210
{
172211
int size = (( width > height ) ? height : width );
173212
int hpad = ( width - size ) / 2;
174213
int vpad = ( height - size ) / 2;
175214

176-
linear_velocity_ = (1.0 - float( y - vpad ) / float( size / 2 )) * linear_max_;
177-
angular_velocity_ = (1.0 - float( x - hpad ) / float( size / 2 )) * angular_max_;
215+
linear_velocity_ = (1.0 - float( y - vpad ) / float( size / 2 )) * linear_scale_;
216+
angular_velocity_ = (1.0 - float( x - hpad ) / float( size / 2 )) * angular_scale_;
178217
update();
179218
Q_EMIT outputVelocity( linear_velocity_, angular_velocity_ );
180219
}

rviz_plugin_tutorials/src/drive_widget.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,46 @@
3434
namespace rviz_plugin_tutorials
3535
{
3636

37+
// DriveWidget implements a control which translates mouse Y values
38+
// into linear velocities and mouse X values into angular velocities.
3739
class DriveWidget: public QWidget
3840
{
3941
Q_OBJECT
4042
public:
43+
// This class is not instantiated by pluginlib::ClassLoader, so the
44+
// constructor has no restrictions.
4145
DriveWidget( QWidget* parent = 0 );
4246

47+
// We override QWidget::paintEvent() to do custom painting.
4348
virtual void paintEvent( QPaintEvent* event );
49+
50+
// We override the mouse events and leaveEvent() to keep track of
51+
// what the mouse is doing.
4452
virtual void mouseMoveEvent( QMouseEvent* event );
4553
virtual void mousePressEvent( QMouseEvent* event );
4654
virtual void mouseReleaseEvent( QMouseEvent* event );
4755
virtual void leaveEvent( QEvent* event );
4856

57+
// Override sizeHint() to give the layout managers some idea of a
58+
// good size for this.
4959
virtual QSize sizeHint() const { return QSize( 150, 150 ); }
5060

5161
Q_SIGNALS:
62+
// We emit outputVelocity() whenever it changes.
5263
void outputVelocity( float linear, float angular );
5364

5465
protected:
66+
// mouseMoveEvent() and mousePressEvent() need the same math to
67+
// figure the velocities, so I put that in here.
5568
void sendVelocitiesFromMouse( int x, int y, int width, int height );
69+
70+
// Emit zero velocity.
5671
void stop();
5772

5873
float linear_velocity_; // In m/s
5974
float angular_velocity_; // In radians/s
60-
float linear_max_;
61-
float angular_max_;
75+
float linear_scale_; // In m/s
76+
float angular_scale_; // In radians/s
6277
};
6378

6479
} // end namespace rviz_plugin_tutorials

0 commit comments

Comments
 (0)