Statistics
| Branch: | Revision:

root / scout / scoutsim / src / scout.cpp @ e5ac3afb

History | View | Annotate | Download (18 KB)

1 c492be62 Alex Zirbel
/**
2
 * The code in this package was developed using the structure of Willow
3
 * Garage's turtlesim package.  It was modified by the CMU Robotics Club
4
 * to be used as a simulator for the Colony Scout robot.
5 266ae7f2 Alex Zirbel
 *
6 c492be62 Alex Zirbel
 * All redistribution of this code is limited to the terms of Willow Garage's
7
 * licensing terms, as well as under permission from the CMU Robotics Club.
8
 * 
9
 * Copyright (c) 2011 Colony Project
10
 * 
11
 * Permission is hereby granted, free of charge, to any person
12
 * obtaining a copy of this software and associated documentation
13
 * files (the "Software"), to deal in the Software without
14
 * restriction, including without limitation the rights to use,
15
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
16
 * copies of the Software, and to permit persons to whom the
17
 * Software is furnished to do so, subject to the following
18
 * conditions:
19
 * 
20
 * The above copyright notice and this permission notice shall be
21
 * included in all copies or substantial portions of the Software.
22
 * 
23
 * Copyright (c) 2009, Willow Garage, Inc.
24 266ae7f2 Alex Zirbel
 * All rights reserved.
25 c492be62 Alex Zirbel
 * 
26
 * Redistribution and use in source and binary forms, with or without
27
 * modification, are permitted provided that the following conditions are met:
28
 * 
29
 *    Redistributions of source code must retain the above copyright
30
 *       notice, this list of conditions and the following disclaimer.
31
 *    Redistributions in binary form must reproduce the above copyright
32
 *       notice, this list of conditions and the following disclaimer in the
33
 *       documentation and/or other materials provided with the distribution.
34
 *    Neither the name of the Willow Garage, Inc. nor the names of its
35
 *       contributors may be used to endorse or promote products derived from
36
 *       this software without specific prior written permission.
37
 * 
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
39
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
40
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
41
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
42
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
43
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
44
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
45
 * OTHER DEALINGS IN THE SOFTWARE.
46 266ae7f2 Alex Zirbel
 */
47
48 a8480867 Alex Zirbel
#include "scout.h"
49 266ae7f2 Alex Zirbel
50
#include <wx/wx.h>
51
52
#define DEFAULT_PEN_R 0xb3
53
#define DEFAULT_PEN_G 0xb8
54
#define DEFAULT_PEN_B 0xff
55
56 af0d9743 Alex
using namespace std;
57
58 266ae7f2 Alex Zirbel
namespace scoutsim
59
{
60
    Scout::Scout(const ros::NodeHandle& nh,
61 9f547ef7 Alex Zirbel
                 const wxImage& scout_image,
62
                 const Vector2& pos,
63 6639ce9c viki
                 wxBitmap *path_bitmap,
64 9f547ef7 Alex Zirbel
                 float orient)
65 6639ce9c viki
        : path_bitmap(path_bitmap)
66 43811241 Alex
          , sonar_visual_on(false)
67 093a1aea Alex
          , sonar_on(true)
68 43811241 Alex
          , node (nh)
69 144137a1 Alex Zirbel
          , scout_image(scout_image)
70
          , pos(pos)
71
          , orient(orient)
72 9f547ef7 Alex Zirbel
          , motor_fl_speed(0)
73
          , motor_fr_speed(0)
74
          , motor_bl_speed(0)
75
          , motor_br_speed(0)
76
          , fl_ticks(0)
77
          , fr_ticks(0)
78
          , bl_ticks(0)
79
          , br_ticks(0)
80 144137a1 Alex Zirbel
          , pen_on(true)
81
          , pen(wxColour(DEFAULT_PEN_R, DEFAULT_PEN_G, DEFAULT_PEN_B))
82 266ae7f2 Alex Zirbel
    {
83 144137a1 Alex Zirbel
        pen.SetWidth(3);
84
        scout = wxBitmap(scout_image);
85
86
        motors_sub = node.subscribe("set_motors", 1, &Scout::setMotors, this);
87
88
        pose_pub = node.advertise<Pose>("pose", 1);
89
        color_pub = node.advertise<Color>("color_sensor", 1);
90 a2e6bd4c Alex
        sonar_pub = node.advertise<sonar::sonar_distance>("sonar_distance", 1);
91 144137a1 Alex Zirbel
        set_pen_srv = node.advertiseService("set_pen",
92 266ae7f2 Alex Zirbel
                                            &Scout::setPenCallback,
93
                                            this);
94 eb9cff77 Hui Jun Tay
        toggle_sonar_srv = node.advertiseService("sonar_toggle",
95
                                            &Scout::handle_sonar_toggle,
96
                                            this);
97
        set_sonar_srv = node.advertiseService("sonar_set_scan",
98
                                            &Scout::handle_sonar_set_scan,
99
                                            this);
100 9f547ef7 Alex Zirbel
        query_encoders_srv =
101
            node.advertiseService("query_encoders",
102
                                  &Scout::query_encoders_callback,
103
                                  this);
104 266ae7f2 Alex Zirbel
105 af0d9743 Alex
        query_linesensor_srv =
106
            node.advertiseService("query_linesensor",
107
                                  &Scout::query_linesensor_callback,
108
                                  this);
109
110 ade1b7f9 Alex
        for (unsigned int i = 0; i < NUM_LINESENSORS; i++)
111
        {
112
            linesensor_readings.push_back(0);
113
        }
114
115 a2e6bd4c Alex
        // Initialize sonar
116
        sonar_position = 0;
117
        sonar_stop_l = 0;
118
        sonar_stop_r = 23;
119
        sonar_direction = 1;
120
        sonar_tick_time = ros::Duration(scoutsim::SONAR_HALF_SPIN_TIME / 24.0);
121 266ae7f2 Alex Zirbel
    }
122
123 6257c97d Alex
    float Scout::absolute_to_mps(int absolute_speed)
124
    {
125
        return ((float) absolute_speed) * MAX_SPEED_MPS / MAX_ABSOLUTE_SPEED;
126
    }
127
128 a8480867 Alex Zirbel
    /**
129
     * A callback function that sets velocity based on a set_motors
130
     * request.
131 c492be62 Alex Zirbel
     * @todo Use "callback" in all callback function names? Or remove?
132 a8480867 Alex Zirbel
     */
133
    void Scout::setMotors(const motors::set_motors::ConstPtr& msg)
134
    {
135 144137a1 Alex Zirbel
        last_command_time = ros::WallTime::now();
136 a8480867 Alex Zirbel
137
        if(msg->fl_set)
138
        {
139 6257c97d Alex
            motor_fl_speed = absolute_to_mps(msg->fl_speed);
140 a8480867 Alex Zirbel
        }
141
        if(msg->fr_set)
142
        {
143 6257c97d Alex
            motor_fr_speed = absolute_to_mps(msg->fr_speed);
144 a8480867 Alex Zirbel
        }
145
        if(msg->bl_set)
146
        {
147 6257c97d Alex
            motor_bl_speed = absolute_to_mps(msg->bl_speed);
148 a8480867 Alex Zirbel
        }
149
        if(msg->br_set)
150
        {
151 6257c97d Alex
            motor_br_speed = absolute_to_mps(msg->br_speed);
152 a8480867 Alex Zirbel
        }
153 266ae7f2 Alex Zirbel
    }
154 eb9cff77 Hui Jun Tay
155
    bool Scout::handle_sonar_toggle(sonar::sonar_toggle::Request  &req,
156 04114d13 Alex
                         sonar::sonar_toggle::Response &res)
157 eb9cff77 Hui Jun Tay
    {
158
        if (req.set_on && !sonar_on)
159
        {
160 04114d13 Alex
            ROS_INFO("Turning on the sonar");
161 eb9cff77 Hui Jun Tay
            sonar_on = true;
162
163
        }
164
        else if (!req.set_on && sonar_on)
165
        {
166 04114d13 Alex
            ROS_INFO("Turning off the sonar");
167 eb9cff77 Hui Jun Tay
            sonar_on = false;
168
        }
169
        else
170
        {
171 04114d13 Alex
            ROS_INFO("Sonar state remains unchanged");
172 eb9cff77 Hui Jun Tay
        }
173 04114d13 Alex
        res.ack = true;
174
        return true;
175 eb9cff77 Hui Jun Tay
    }
176
177 04114d13 Alex
    bool Scout::handle_sonar_set_scan(sonar::sonar_set_scan::Request  &req,
178
                                      sonar::sonar_set_scan::Response &res)
179 eb9cff77 Hui Jun Tay
    {
180 04114d13 Alex
        // Code to set the sonar to scan from
181
        // req.stop_l to req.stop_r
182
        if (req.stop_l>=0 and req.stop_r<=23 and req.stop_l<=req.stop_r)
183
        {
184
            ROS_INFO("Setting sonar scan range to [%i, %i]",
185
                     req.stop_l,
186
                     req.stop_r);
187
            sonar_stop_l = req.stop_l;
188
            sonar_stop_r = req.stop_r;
189
            sonar_position = req.stop_l;
190
            sonar_direction = 1;
191
            res.ack = true;
192
        }
193
        else
194
        {
195
            ROS_INFO("Bad Input: Input should be integers 0-23, stop_l<stop_r");
196
        }
197
        return true;
198 eb9cff77 Hui Jun Tay
    }
199 266ae7f2 Alex Zirbel
200
    bool Scout::setPenCallback(scoutsim::SetPen::Request& req,
201
                               scoutsim::SetPen::Response&)
202
    {
203 144137a1 Alex Zirbel
        pen_on = !req.off;
204 266ae7f2 Alex Zirbel
        if (req.off)
205
        {
206
            return true;
207
        }
208
209
        wxPen pen(wxColour(req.r, req.g, req.b));
210
        if (req.width != 0)
211
        {
212
            pen.SetWidth(req.width);
213
        }
214
215 144137a1 Alex Zirbel
        pen = pen;
216 266ae7f2 Alex Zirbel
        return true;
217
    }
218
219 9f547ef7 Alex Zirbel
    bool Scout::query_encoders_callback(encoders::query_encoders::Request&,
220
                                        encoders::query_encoders::Response& res)
221
    {
222
        res.fl_distance = fl_ticks;
223
        res.fr_distance = fr_ticks;
224
        res.bl_distance = bl_ticks;
225
        res.br_distance = br_ticks;
226
227
        return true;
228
    }
229
230 af0d9743 Alex
    bool Scout::query_linesensor_callback(linesensor::query_linesensor::Request&,
231
                                          linesensor::query_linesensor::Response& res)
232
    {
233 ade1b7f9 Alex
        res.readings = linesensor_readings;
234
235
        return true;
236
    }
237 af0d9743 Alex
238 ade1b7f9 Alex
    // Scale to linesensor value
239 a2e6bd4c Alex
    unsigned int Scout::rgb_to_grey(unsigned char r,
240
                                    unsigned char g,
241
                                    unsigned char b)
242 ade1b7f9 Alex
    {
243
        // Should be 0 to 255
244
        unsigned int grey = ((unsigned int) r + (unsigned int) g + (unsigned int) b) / 3;
245
246
        /// @todo Convert to the proper range
247
        return 255 - grey;
248
    }
249
250 a2e6bd4c Alex
    unsigned int Scout::trace_sonar(const wxImage& walls_image, int x, int y,
251 96ec9388 Hui Jun Tay
                                    double robot_theta, int sonar_pos, 
252
                                    wxMemoryDC& sonar_dc)
253 a2e6bd4c Alex
    {
254 71e1154d Alex
        double angle = robot_theta + (PI * ((float) sonar_pos) / 24.0) - PI / 2;
255 a2e6bd4c Alex
        unsigned int d = 0;
256
257
        unsigned int reading = 0;
258 96ec9388 Hui Jun Tay
259 c63c9752 Alex
        int d_x = 0;
260
        int d_y = 0;
261
262 a2e6bd4c Alex
        do
263
        {
264 6639ce9c viki
            d_x = x + (int) floor(d * cos(angle));
265 eb9cff77 Hui Jun Tay
            d_y = y - (int) floor(d * sin(angle));
266 a2e6bd4c Alex
267
            // Out of image boundary
268
            if (d_x < 0 || d_x >= walls_image.GetWidth() ||
269
                d_y < 0 || d_y >= walls_image.GetHeight())
270
            {
271
                return d;
272
            }
273
274
            // Max range
275
            if (d > scoutsim::SONAR_MAX_RANGE)
276
            {
277
                return d;
278
            }
279
280
            // Get the sonar reading at the current position of the sonar
281
            unsigned char r = walls_image.GetRed(d_x, d_y);
282
            unsigned char g = walls_image.GetGreen(d_x, d_y);
283
            unsigned char b = walls_image.GetBlue(d_x, d_y);
284 04114d13 Alex
    
285 a2e6bd4c Alex
            reading = rgb_to_grey(r, g, b);
286 04114d13 Alex
        
287 a2e6bd4c Alex
288
            d++;
289
        }
290 71e1154d Alex
        /// @todo Consider using different cutoffs for different features
291
        while (reading < 128); /// @todo Get rid of hardcoded stuff like this
292 6639ce9c viki
        
293 04114d13 Alex
        if (sonar_visual_on)
294
        {   
295
            if (isFront)
296
            {
297
                // draw a circle at the wall_x, wall_y where reading > 128
298
                sonar_dc.SelectObject(*path_bitmap);
299
                sonar_dc.SetBrush(*wxRED_BRUSH); //old value
300 9cb9623b Alex
                sonar_dc.DrawCircle(wxPoint(old_front_dx, old_front_dy), 2);
301 04114d13 Alex
                old_front_dx = d_x;
302
                old_front_dy = d_y;
303
            }
304
            else
305
            {
306
                // draw a circle at the wall_x, wall_y where reading > 128
307
                sonar_dc.SelectObject(*path_bitmap);
308
                sonar_dc.SetBrush(*wxRED_BRUSH); //old value
309
                sonar_dc.DrawCircle(wxPoint(old_back_dx,old_back_dy), 2);
310
                old_back_dx = d_x;
311
                old_back_dy = d_y;
312
            }
313
314
            sonar_dc.SetBrush(*wxGREEN_BRUSH);  //newest value
315 43811241 Alex
            sonar_dc.DrawCircle(wxPoint(d_x,d_y), 2);
316
            if (isFront) // @todo for some reason isFront = (!isFront) is not working
317 04114d13 Alex
            {
318
                isFront = FALSE;
319
            }
320
            else
321
            {
322
                isFront = TRUE; 
323
            }
324
        }
325
326 e5ac3afb Alex
        // Convert from pixels to mm and return
327
        return (unsigned int) (1000 * d / PIX_PER_METER);
328 a2e6bd4c Alex
    }
329
330 71e1154d Alex
    // x and y is current position of the sonar
331 a2e6bd4c Alex
    void Scout::update_sonar(const wxImage& walls_image, int x, int y,
332 eb9cff77 Hui Jun Tay
                             double robot_theta,wxMemoryDC& sonar_dc)
333 a2e6bd4c Alex
    {
334
        // Only rotate the sonar at the correct rate.
335
        if (ros::Time::now() - last_sonar_time < sonar_tick_time)
336
        {
337
            return;
338
        }
339
        last_sonar_time = ros::Time::now();
340
341
        unsigned int d_front = trace_sonar(walls_image, x, y, robot_theta,
342 43811241 Alex
                                           sonar_position, sonar_dc);
343 a2e6bd4c Alex
        unsigned int d_back = trace_sonar(walls_image, x, y, robot_theta,
344 43811241 Alex
                                          sonar_position + 24, sonar_dc);
345 a2e6bd4c Alex
346
        // Publish
347
        sonar::sonar_distance msg;
348
        msg.pos = sonar_position;
349
        msg.distance0 = d_front;
350
        msg.distance1 = d_back;
351
352
        sonar_pub.publish(msg);
353
354
        // Update the sonar rotation
355
        if (sonar_position + sonar_direction <= sonar_stop_r &&
356
            sonar_position + sonar_direction >= sonar_stop_l)
357
        {
358
            sonar_position = sonar_position + sonar_direction;
359
        }
360
        else
361
        {
362
            sonar_direction = -sonar_direction;
363
        }
364
    }
365
366
    void Scout::update_linesensor(const wxImage& lines_image, int x, int y,
367
                                  double robot_theta)
368 ade1b7f9 Alex
    {
369
        linesensor_readings.clear();
370
371
        double spacing = scout_image.GetWidth() / (NUM_LINESENSORS - 1);
372
        for (int s = 0; s < NUM_LINESENSORS; s++)
373 af0d9743 Alex
        {
374 ade1b7f9 Alex
            double offset = -(scout_image.GetWidth() / 2) + s * spacing;
375 af0d9743 Alex
376 a2e6bd4c Alex
            int sensor_x = (int) (x - LNSNSR_D * cos(robot_theta) -
377
                                  offset * sin(robot_theta));
378
            int sensor_y = (int) (y + LNSNSR_D * sin(robot_theta) -
379
                                  offset * cos(robot_theta));
380 af0d9743 Alex
381 ade1b7f9 Alex
            unsigned char r = lines_image.GetRed(sensor_x, sensor_y);
382
            unsigned char g = lines_image.GetGreen(sensor_x, sensor_y);
383
            unsigned char b = lines_image.GetBlue(sensor_x, sensor_y);
384
385 a2e6bd4c Alex
            unsigned int reading = rgb_to_grey(r, g, b);
386 ade1b7f9 Alex
387
            linesensor_readings.push_back(reading);
388
        }
389 af0d9743 Alex
    }
390
391 9b3564f3 Alex Zirbel
    /// Sends back the position of this scout so scoutsim can save
392
    /// the world state
393 04114d13 Alex
    /// TODO remove dt param
394 9b3564f3 Alex Zirbel
    geometry_msgs::Pose2D Scout::update(double dt, wxMemoryDC& path_dc,
395 04114d13 Alex
                                        wxMemoryDC& sonar_dc,
396 9b3564f3 Alex Zirbel
                                        const wxImage& path_image,
397 ade1b7f9 Alex
                                        const wxImage& lines_image,
398 a2e6bd4c Alex
                                        const wxImage& walls_image,
399 9b3564f3 Alex Zirbel
                                        wxColour background_color,
400 c63c9752 Alex
                                        wxColour sonar_color,
401 9b3564f3 Alex Zirbel
                                        world_state state)
402 266ae7f2 Alex Zirbel
    {
403 9f547ef7 Alex Zirbel
        // Assume that the two motors on the same side will be set to
404
        // roughly the same speed. Does not account for slip conditions
405
        // when they are set to different speeds.
406
        float l_speed = (float (motor_fl_speed + motor_bl_speed)) / 2;
407
        float r_speed = (float (motor_fr_speed + motor_br_speed)) / 2;
408
409 c63c9752 Alex
        // Find linear and angular movement in m
410 7f095440 Priya
        float lin_dist = SIM_TIME_REFRESH_RATE * (l_speed + r_speed) / 2;
411
        float ang_dist = SIM_TIME_REFRESH_RATE * (r_speed - l_speed);
412 9f547ef7 Alex Zirbel
413 144137a1 Alex Zirbel
        Vector2 old_pos = pos;
414 266ae7f2 Alex Zirbel
415 9f547ef7 Alex Zirbel
        // Update encoders
416 7f095440 Priya
        fl_ticks += (unsigned int) (motor_fl_speed * SIM_TIME_REFRESH_RATE *
417 c63c9752 Alex
                                    ENCODER_TICKS_PER_METER);
418 7f095440 Priya
        fr_ticks += (unsigned int) (motor_fr_speed * SIM_TIME_REFRESH_RATE *
419 c63c9752 Alex
                                    ENCODER_TICKS_PER_METER);
420 7f095440 Priya
        bl_ticks += (unsigned int) (motor_bl_speed * SIM_TIME_REFRESH_RATE *
421 c63c9752 Alex
                                    ENCODER_TICKS_PER_METER);
422 7f095440 Priya
        br_ticks += (unsigned int) (motor_br_speed * SIM_TIME_REFRESH_RATE *
423 c63c9752 Alex
                                    ENCODER_TICKS_PER_METER);
424
425
        orient = fmod((float) (orient + ang_dist), (float) (2.0 * PI));
426 9f547ef7 Alex Zirbel
427 c63c9752 Alex
        pos.x += sin(orient + PI/2.0) * lin_dist;
428
        pos.y += cos(orient + PI/2.0) * lin_dist;
429 266ae7f2 Alex Zirbel
430
        // Clamp to screen size
431 e3f69e61 Alex
        if (pos.x < 0 || pos.x >= state.canvas_width
432
                || pos.y < 0 || pos.y >= state.canvas_height)
433 266ae7f2 Alex Zirbel
        {
434 c63c9752 Alex
            ROS_WARN("I hit the wall! (Clamping from [x=%f, y=%f])", pos.x, pos.y);
435 266ae7f2 Alex Zirbel
        }
436
437 af0d9743 Alex
        pos.x = min(max(pos.x, 0.0f), state.canvas_width);
438
        pos.y = min(max(pos.y, 0.0f), state.canvas_height);
439 266ae7f2 Alex Zirbel
440 c63c9752 Alex
        int canvas_x = pos.x * PIX_PER_METER;
441
        int canvas_y = pos.y * PIX_PER_METER;
442 266ae7f2 Alex Zirbel
443
        {
444
            wxImage rotated_image =
445 144137a1 Alex Zirbel
                scout_image.Rotate(orient - PI/2.0,
446
                                   wxPoint(scout_image.GetWidth() / 2,
447 ade1b7f9 Alex
                                           scout_image.GetHeight() / 2),
448 5e2c3dc1 Alex
                                   false);
449 266ae7f2 Alex Zirbel
450
            for (int y = 0; y < rotated_image.GetHeight(); ++y)
451
            {
452
                for (int x = 0; x < rotated_image.GetWidth(); ++x)
453
                {
454
                    if (rotated_image.GetRed(x, y) == 255
455
                            && rotated_image.GetBlue(x, y) == 255
456
                            && rotated_image.GetGreen(x, y) == 255)
457
                    {
458
                        rotated_image.SetAlpha(x, y, 0);
459
                    }
460
                }
461
            }
462
463 144137a1 Alex Zirbel
            scout = wxBitmap(rotated_image);
464 266ae7f2 Alex Zirbel
        }
465
466
        Pose p;
467 144137a1 Alex Zirbel
        p.x = pos.x;
468 ddfeb111 Priya
        p.y = pos.y;
469 144137a1 Alex Zirbel
        p.theta = orient;
470 c63c9752 Alex
        p.linear_velocity = l_speed;
471
        p.angular_velocity = r_speed;
472 144137a1 Alex Zirbel
        pose_pub.publish(p);
473 266ae7f2 Alex Zirbel
474 ade1b7f9 Alex
        update_linesensor(lines_image, canvas_x, canvas_y, p.theta);
475 eb9cff77 Hui Jun Tay
        if (sonar_on)
476
        {
477
            update_sonar(walls_image,
478
                         canvas_x + scoutsim::SCOUT_SONAR_X,
479
                         canvas_y + scoutsim::SCOUT_SONAR_Y,
480
                         p.theta,sonar_dc);
481 ade1b7f9 Alex
482 eb9cff77 Hui Jun Tay
        }
483 43811241 Alex
484 266ae7f2 Alex Zirbel
        // Figure out (and publish) the color underneath the scout
485
        {
486 23b8119f Alex
            //wxSize scout_size = wxSize(scout.GetWidth(), scout.GetHeight());
487 266ae7f2 Alex Zirbel
            Color color;
488
            color.r = path_image.GetRed(canvas_x, canvas_y);
489
            color.g = path_image.GetGreen(canvas_x, canvas_y);
490
            color.b = path_image.GetBlue(canvas_x, canvas_y);
491 144137a1 Alex Zirbel
            color_pub.publish(color);
492 266ae7f2 Alex Zirbel
        }
493
494
        ROS_DEBUG("[%s]: pos_x: %f pos_y: %f theta: %f",
495 144137a1 Alex Zirbel
                  node.getNamespace().c_str(), pos.x, pos.y, orient);
496 266ae7f2 Alex Zirbel
497 144137a1 Alex Zirbel
        if (pen_on)
498 266ae7f2 Alex Zirbel
        {
499 144137a1 Alex Zirbel
            if (pos != old_pos)
500 266ae7f2 Alex Zirbel
            {
501 6639ce9c viki
                path_dc.SelectObject(*path_bitmap);
502 144137a1 Alex Zirbel
                path_dc.SetPen(pen);
503 c63c9752 Alex
                path_dc.DrawLine(pos.x * PIX_PER_METER, pos.y * PIX_PER_METER,
504
                                 old_pos.x * PIX_PER_METER, old_pos.y * PIX_PER_METER);
505 266ae7f2 Alex Zirbel
            }
506
        }
507 e3f69e61 Alex
508
        geometry_msgs::Pose2D my_pose;
509
        my_pose.x = pos.x;
510
        my_pose.y = pos.y;
511
        my_pose.theta = orient;
512
513
        return my_pose;
514 266ae7f2 Alex Zirbel
    }
515
516
    void Scout::paint(wxDC& dc)
517
    {
518 144137a1 Alex Zirbel
        wxSize scout_size = wxSize(scout.GetWidth(), scout.GetHeight());
519 c63c9752 Alex
        dc.DrawBitmap(scout, pos.x * PIX_PER_METER - (scout_size.GetWidth() / 2),
520
                      pos.y * PIX_PER_METER - (scout_size.GetHeight() / 2), true);
521 266ae7f2 Alex Zirbel
    }
522 43811241 Alex
523
    void Scout::set_sonar_visual(bool on)
524
    {
525
        sonar_visual_on = on;
526
    }
527 266ae7f2 Alex Zirbel
}