Project

General

Profile

Statistics
| Branch: | Revision:

scoutos / scout / scoutsim / src / scout.cpp @ c492be62

History | View | Annotate | Download (7.75 KB)

1
/**
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
 *
6
 * 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
 * All rights reserved.
25
 * 
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
 */
47

    
48
#include "scout.h"
49

    
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
namespace scoutsim
57
{
58
    Scout::Scout(const ros::NodeHandle& nh,
59
            const wxImage& scout_image,
60
            const Vector2& pos,
61
            float orient)
62
        : node (nh)
63
          , scout_image(scout_image)
64
          , pos(pos)
65
          , orient(orient)
66
          , lin_vel(0.0)
67
          , ang_vel(0.0)
68
          , pen_on(true)
69
          , pen(wxColour(DEFAULT_PEN_R, DEFAULT_PEN_G, DEFAULT_PEN_B))
70
    {
71
        pen.SetWidth(3);
72
        scout = wxBitmap(scout_image);
73

    
74
        motors_sub = node.subscribe("set_motors", 1, &Scout::setMotors, this);
75

    
76
        pose_pub = node.advertise<Pose>("pose", 1);
77
        color_pub = node.advertise<Color>("color_sensor", 1);
78
        set_pen_srv = node.advertiseService("set_pen",
79
                                            &Scout::setPenCallback,
80
                                            this);
81

    
82
        meter = scout.GetHeight();
83
    }
84

    
85
    /**
86
     * A callback function that sets velocity based on a set_motors
87
     * request.
88
     * @todo Use "callback" in all callback function names? Or remove?
89
     */
90
    void Scout::setMotors(const motors::set_motors::ConstPtr& msg)
91
    {
92
        last_command_time = ros::WallTime::now();
93

    
94
        if(msg->fl_set)
95
        {
96
            motor_fl_speed = msg->fl_speed;
97
        }
98
        if(msg->fr_set)
99
        {
100
            motor_fr_speed = msg->fr_speed;
101
        }
102
        if(msg->bl_set)
103
        {
104
            motor_bl_speed = msg->bl_speed;
105
        }
106
        if(msg->br_set)
107
        {
108
            motor_br_speed = msg->br_speed;
109
        }
110

    
111
        // Assume that the two motors on the same side will be set to
112
        // roughly the same speed. Does not account for slip conditions
113
        // when they are set to different speeds.
114
        float l_speed = (float (motor_fl_speed + motor_bl_speed)) / 2;
115
        float r_speed = (float (motor_fr_speed + motor_br_speed)) / 2;
116

    
117
        // Set the linear and angular speeds
118
        lin_vel = SPEED_SCALE_FACTOR * (l_speed + r_speed) / 2;
119
        ang_vel = SPEED_SCALE_FACTOR * (r_speed - l_speed);
120
    }
121

    
122
    float Scout::getSonar(float angle)
123
    {
124

    
125
        return 0.0;
126
    }
127

    
128
    bool Scout::setPenCallback(scoutsim::SetPen::Request& req,
129
                               scoutsim::SetPen::Response&)
130
    {
131
        pen_on = !req.off;
132
        if (req.off)
133
        {
134
            return true;
135
        }
136

    
137
        wxPen pen(wxColour(req.r, req.g, req.b));
138
        if (req.width != 0)
139
        {
140
            pen.SetWidth(req.width);
141
        }
142

    
143
        pen = pen;
144
        return true;
145
    }
146

    
147
    void Scout::update(double dt, wxMemoryDC& path_dc,
148
                        const wxImage& path_image, wxColour background_color,
149
                        float canvas_width, float canvas_height)
150
    {
151
        Vector2 old_pos = pos;
152

    
153
        orient = fmod(orient + ang_vel * dt, 2*PI);
154
        pos.x += sin(orient + PI/2.0) * lin_vel * dt;
155
        pos.y += cos(orient + PI/2.0) * lin_vel * dt;
156

    
157
        // Clamp to screen size
158
        if (pos.x < 0 || pos.x >= canvas_width
159
                || pos.y < 0 || pos.y >= canvas_height)
160
        {
161
            ROS_WARN("Oh no! I hit the wall! (Clamping from [x=%f, y=%f])", pos.x, pos.y);
162
        }
163

    
164
        pos.x = std::min(std::max(pos.x, 0.0f), canvas_width);
165
        pos.y = std::min(std::max(pos.y, 0.0f), canvas_height);
166

    
167
        int canvas_x = pos.x * meter;
168
        int canvas_y = pos.y * meter;
169

    
170
        {
171
            wxImage rotated_image =
172
                scout_image.Rotate(orient - PI/2.0,
173
                                   wxPoint(scout_image.GetWidth() / 2,
174
                                            scout_image.GetHeight() / 2),
175
                                    false);
176

    
177
            for (int y = 0; y < rotated_image.GetHeight(); ++y)
178
            {
179
                for (int x = 0; x < rotated_image.GetWidth(); ++x)
180
                {
181
                    if (rotated_image.GetRed(x, y) == 255
182
                            && rotated_image.GetBlue(x, y) == 255
183
                            && rotated_image.GetGreen(x, y) == 255)
184
                    {
185
                        rotated_image.SetAlpha(x, y, 0);
186
                    }
187
                }
188
            }
189

    
190
            scout = wxBitmap(rotated_image);
191
        }
192

    
193
        Pose p;
194
        p.x = pos.x;
195
        p.y = canvas_height - pos.y;
196
        p.theta = orient;
197
        p.linear_velocity = lin_vel;
198
        p.angular_velocity = ang_vel;
199
        pose_pub.publish(p);
200

    
201
        // Figure out (and publish) the color underneath the scout
202
        {
203
            wxSize scout_size = wxSize(scout.GetWidth(), scout.GetHeight());
204
            Color color;
205
            color.r = path_image.GetRed(canvas_x, canvas_y);
206
            color.g = path_image.GetGreen(canvas_x, canvas_y);
207
            color.b = path_image.GetBlue(canvas_x, canvas_y);
208
            color_pub.publish(color);
209
        }
210

    
211
        ROS_DEBUG("[%s]: pos_x: %f pos_y: %f theta: %f",
212
                  node.getNamespace().c_str(), pos.x, pos.y, orient);
213

    
214
        if (pen_on)
215
        {
216
            if (pos != old_pos)
217
            {
218
                path_dc.SetPen(pen);
219
                path_dc.DrawLine(pos.x * meter, pos.y * meter,
220
                                 old_pos.x * meter, old_pos.y * meter);
221
            }
222
        }
223
    }
224

    
225
    void Scout::paint(wxDC& dc)
226
    {
227
        wxSize scout_size = wxSize(scout.GetWidth(), scout.GetHeight());
228
        dc.DrawBitmap(scout, pos.x * meter - (scout_size.GetWidth() / 2),
229
                      pos.y * meter - (scout_size.GetHeight() / 2), true);
230
    }
231

    
232
}