Project

General

Profile

Revision 266ae7f2

ID266ae7f2731d6be5eefa284aa1d1682c15d6009f
Parent 3ec16d35
Child 73cd5944

Added by Alex Zirbel over 12 years ago

Added a template scout simulator class.

Scoutsim is modeled directly from turtlesim. At this point, the only changes are in names and indentation. A separate licensing file was also added to get rid of the junk at the top of the old turtlesim files.

View differences:

scout/scoutsim/CMakeLists.txt
1
if(ROSBUILD)
2
  include(rosbuild.cmake)
3
  return()
4
endif()
5
cmake_minimum_required(VERSION 2.4.6)
6
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
7

  
8
# Set the build type.  Options are:
9
#  Coverage       : w/ debug symbols, w/o optimization, w/ code-coverage
10
#  Debug          : w/ debug symbols, w/o optimization
11
#  Release        : w/o debug symbols, w/ optimization
12
#  RelWithDebInfo : w/ debug symbols, w/ optimization
13
#  MinSizeRel     : w/o debug symbols, w/ optimization, stripped binaries
14
#set(ROS_BUILD_TYPE RelWithDebInfo)
15

  
16
rosbuild_init()
17

  
18
#set the default path for built executables to the "bin" directory
19
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
20
#set the default path for built libraries to the "lib" directory
21
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
22

  
23
rosbuild_genmsg()
24
rosbuild_gensrv()
25

  
26
find_package(wxWidgets REQUIRED)
27
include(${wxWidgets_USE_FILE})
28
include_directories( ${wxWidgets_INCLUDE_DIRS} )
29

  
30
rosbuild_add_boost_directories()
31
rosbuild_add_executable(scoutsim_node src/scoutsim.cpp src/scout.cpp src/sim_frame.cpp)
32
rosbuild_link_boost(scoutsim_node thread)
33
target_link_libraries(scoutsim_node ${wxWidgets_LIBRARIES})
34

  
35
# @TODO are these useful or necessary? Determine; add as needed
36
#rosbuild_add_executable(turtle_teleop_key tutorials/teleop_turtle_key.cpp)
37
#rosbuild_add_executable(draw_square tutorials/draw_square.cpp)
38
#rosbuild_add_executable(mimic tutorials/mimic.cpp)
scout/scoutsim/Makefile
1
include $(shell rospack find mk)/cmake.mk
scout/scoutsim/include/scoutsim/scout.h
1
/*
2
 * This package was developed by the CMU Robotics Club project using code
3
 * from Willow Garage, Inc.  Please see licensing.txt for details.
4
 *
5
 * All rights reserved.
6
 *
7
 * @file scout.h
8
 * @author Colony Project, CMU Robotics Club
9
 * @author Alex Zirbel
10
 */
11

  
12
#ifndef SCOUTSIM_SCOUT_H
13
#define SCOUTSIM_SCOUT_H
14

  
15
#include <ros/ros.h>
16
#include <boost/shared_ptr.hpp>
17

  
18
#include <scoutsim/Pose.h>
19
#include <scoutsim/Velocity.h>
20
#include <scoutsim/SetPen.h>
21
#include <scoutsim/TeleportRelative.h>
22
#include <scoutsim/TeleportAbsolute.h>
23
#include <scoutsim/Color.h>
24

  
25
#include <wx/wx.h>
26

  
27
#define PI 3.14159265
28

  
29
namespace scoutsim
30
{
31

  
32
    struct Vector2
33
    {
34
        Vector2()
35
            : x(0.0)
36
              , y(0.0)
37
        {}
38

  
39
        Vector2(float _x, float _y)
40
            : x(_x)
41
              , y(_y)
42
        {}
43

  
44
        bool operator==(const Vector2& rhs)
45
        {
46
            return x == rhs.x && y == rhs.y;
47
        }
48

  
49
        bool operator!=(const Vector2& rhs)
50
        {
51
            return x != rhs.x || y != rhs.y;
52
        }
53

  
54
        float x;
55
        float y;
56
    };
57

  
58
    class Scout
59
    {
60
        public:
61
            Scout(const ros::NodeHandle& nh, const wxImage& scout_image,
62
                  const Vector2& pos, float orient);
63

  
64
            void update(double dt, wxMemoryDC& path_dc,
65
                        const wxImage& path_image, wxColour background_color,
66
                        float canvas_width, float canvas_height);
67
            void paint(wxDC& dc);
68

  
69
        private:
70
            void velocityCallback(const VelocityConstPtr& vel);
71
            bool setPenCallback(scoutsim::SetPen::Request&,
72
                                scoutsim::SetPen::Response&);
73
            bool teleportRelativeCallback(scoutsim::TeleportRelative::Request&,
74
                                          scoutsim::TeleportRelative::Response&);
75
            bool teleportAbsoluteCallback(scoutsim::TeleportAbsolute::Request&,
76
                                          scoutsim::TeleportAbsolute::Response&);
77

  
78
            ros::NodeHandle nh_;
79

  
80
            wxImage scout_image_;
81
            wxBitmap scout_;
82

  
83
            Vector2 pos_;
84
            float orient_;
85

  
86
            float lin_vel_;
87
            float ang_vel_;
88
            bool pen_on_;
89
            wxPen pen_;
90

  
91
            ros::Subscriber velocity_sub_;
92
            ros::Publisher pose_pub_;
93
            ros::Publisher color_pub_;
94
            ros::ServiceServer set_pen_srv_;
95
            ros::ServiceServer teleport_relative_srv_;
96
            ros::ServiceServer teleport_absolute_srv_;
97

  
98
            ros::WallTime last_command_time_;
99

  
100
            float meter_;
101

  
102
            struct TeleportRequest
103
            {
104
                TeleportRequest(float x, float y, float _theta,
105
                                float _linear, bool _relative)
106
                    : pos(x, y)
107
                      , theta(_theta)
108
                      , linear(_linear)
109
                      , relative(_relative)
110
                {}
111

  
112
                Vector2 pos;
113
                float theta;
114
                float linear;
115
                bool relative;
116
            };
117

  
118
            typedef std::vector<TeleportRequest> V_TeleportRequest;
119
            V_TeleportRequest teleport_requests_;
120
    };
121
    typedef boost::shared_ptr<Scout> ScoutPtr;
122

  
123
}
124

  
125
#endif
scout/scoutsim/include/scoutsim/sim_frame.h
1
/*
2
 * This package was developed by the CMU Robotics Club project using code
3
 * from Willow Garage, Inc.  Please see licensing.txt for details.
4
 *
5
 * All rights reserved.
6
 *
7
 * @file sim_frame.h
8
 * @author Colony Project, CMU Robotics Club
9
 * @author Alex Zirbel
10
 */
11

  
12
#include <wx/wx.h>
13
#include <wx/event.h>
14
#include <wx/timer.h>
15

  
16
#include <ros/ros.h>
17

  
18
#include <std_srvs/Empty.h>
19
#include <scoutsim/Spawn.h>
20
#include <scoutsim/Kill.h>
21
#include <map>
22

  
23
#include "scout.h"
24

  
25
#define SCOUTSIM_NUM_SCOUTS 5
26

  
27
namespace scoutsim
28
{
29
    class SimFrame : public wxFrame
30
    {
31
        public:
32
            SimFrame(wxWindow* parent);
33
            ~SimFrame();
34

  
35
            std::string spawnScout(const std::string& name,
36
                    float x, float y, float angle);
37

  
38
        private:
39
            void onUpdate(wxTimerEvent& evt);
40
            void onPaint(wxPaintEvent& evt);
41

  
42
            void updateScouts();
43
            void clear();
44
            bool hasScout(const std::string& name);
45

  
46
            bool clearCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
47
            bool resetCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
48
            bool spawnCallback(scoutsim::Spawn::Request&, scoutsim::Spawn::Response&);
49
            bool killCallback(scoutsim::Kill::Request&, scoutsim::Kill::Response&);
50

  
51
            ros::NodeHandle nh_;
52
            wxTimer* update_timer_;
53
            wxBitmap path_bitmap_;
54
            wxImage path_image_;
55
            wxMemoryDC path_dc_;
56

  
57
            uint64_t frame_count_;
58

  
59
            ros::WallTime last_scout_update_;
60

  
61
            ros::ServiceServer clear_srv_;
62
            ros::ServiceServer reset_srv_;
63
            ros::ServiceServer spawn_srv_;
64
            ros::ServiceServer kill_srv_;
65

  
66
            typedef std::map<std::string, ScoutPtr> M_Scout;
67
            M_Scout scouts_;
68
            uint32_t id_counter_;
69

  
70
            wxImage scout_images_[SCOUTSIM_NUM_SCOUTS];
71

  
72
            float meter_;
73
            float width_in_meters_;
74
            float height_in_meters_;
75
    };
76

  
77
}
scout/scoutsim/licensing.txt
1
The code in this package was developed using the structure of Willow
2
Garage's turtlesim package.  It was modified by the CMU Robotics Club
3
to be used as a simulator for the Colony Scout robot.
4

  
5
All redistribution of this code is limited to the terms of Willow Garage's
6
licensing terms, as well as under permission from the CMU Robotics Club.
7

  
8
Please see both licensing agreements below.
9

  
10
******************************************************************************
11
** BELOW IS THE LICENSING AGREEMENT FROM WILLOW GARAGE                      **
12
******************************************************************************
13

  
14
Copyright (c) 2009, Willow Garage, Inc.
15
All rights reserved.
16

  
17
Redistribution and use in source and binary forms, with or without
18
modification, are permitted provided that the following conditions are met:
19

  
20
   Redistributions of source code must retain the above copyright
21
      notice, this list of conditions and the following disclaimer.
22
   Redistributions in binary form must reproduce the above copyright
23
      notice, this list of conditions and the following disclaimer in the
24
      documentation and/or other materials provided with the distribution.
25
   Neither the name of the Willow Garage, Inc. nor the names of its
26
      contributors may be used to endorse or promote products derived from
27
      this software without specific prior written permission.
28

  
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39
POSSIBILITY OF SUCH DAMAGE.
40

  
41

  
42
******************************************************************************
43
** BELOW IS THE LICENSING AGREEMENT FROM THE COLONY PROJECT                 **
44
******************************************************************************
45

  
46
Copyright (c) 2011 Colony Project
47

  
48
Permission is hereby granted, free of charge, to any person
49
obtaining a copy of this software and associated documentation
50
files (the "Software"), to deal in the Software without
51
restriction, including without limitation the rights to use,
52
copy, modify, merge, publish, distribute, sublicense, and/or sell
53
copies of the Software, and to permit persons to whom the
54
Software is furnished to do so, subject to the following
55
conditions:
56

  
57
The above copyright notice and this permission notice shall be
58
included in all copies or substantial portions of the Software.
59

  
60
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
61
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
62
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
63
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
64
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
65
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
66
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
67
OTHER DEALINGS IN THE SOFTWARE.
scout/scoutsim/mainpage.dox
1
/**
2
\mainpage
3
\htmlinclude manifest.html
4

  
5
\b scoutsim runs a simulator of the Scout robot for faster development.
6

  
7
<!-- 
8
In addition to providing an overview of your package,
9
this is the section where the specification and design/architecture 
10
should be detailed. While the original specification may be done on the
11
wiki, it should be transferred here once your package starts to take shape.
12
You can then link to this documentation page from the Wiki. 
13
-->
14

  
15

  
16
\section codeapi Code API
17

  
18
<!--
19
Provide links to specific auto-generated API documentation within your
20
package that is of particular interest to a reader. Doxygen will
21
document pretty much every part of your code, so do your best here to
22
point the reader to the actual API.
23

  
24
If your codebase is fairly large or has different sets of APIs, you
25
should use the doxygen 'group' tag to keep these APIs together. For
26
example, the roscpp documentation has 'libros' group.
27
-->
28

  
29

  
30
*/
scout/scoutsim/manifest.xml
1
<package>
2
  <description brief="scoutsim">
3

  
4
    scoutsim is a tool to simulate the Colony Scout platform, so that new
5
    behaviors can be prototyped rapidly.
6

  
7
  </description>
8
  <author>Alex Zirbel</author>
9
  <license>BSD</license>
10
  <review status="unreviewed" notes=""/>
11
  <url></url>
12
  <depend package="roscpp"/>
13
  <depend package="roslib"/>
14
  <depend package="rosconsole"/>
15
  <depend package="std_srvs"/>
16
  
17
  <rosdep name="wxwidgets"/>
18

  
19
  <export>
20
    <cpp cflags="-I${prefix}/msg/cpp -I${prefix}/srv/cpp"/>
21
  </export>
22

  
23
  <platform os="ubuntu" version="9.04"/>
24
  <platform os="ubuntu" version="9.10"/>
25
  <platform os="ubuntu" version="10.04"/>
26

  
27
  <rosbuild2>
28
    <depend package="roscpp"/>
29
    <depend package="roslib"/>
30
    <depend package="rosconsole"/>
31
    <depend package="std_srvs"/>
32

  
33
    <msgs>
34
      msg/Color.msg  msg/Pose.msg  msg/Velocity.msg 
35
    </msgs>
36
    <srvs>
37
      srv/Kill.srv  
38
      srv/SetPen.srv  srv/Spawn.srv  srv/TeleportAbsolute.srv  srv/TeleportRelative.srv
39
    </srvs>
40
  </rosbuild2>
41
</package>
42

  
43

  
scout/scoutsim/msg/Color.msg
1
uint8 r
2
uint8 g
3
uint8 b
scout/scoutsim/msg/Pose.msg
1
float32 x
2
float32 y
3
float32 theta
4

  
5
float32 linear_velocity
6
float32 angular_velocity
scout/scoutsim/msg/Velocity.msg
1
float32 linear
2
float32 angular
scout/scoutsim/src/scout.cpp
1
/*
2
 * This package was developed by the CMU Robotics Club project using code
3
 * from Willow Garage, Inc.  Please see licensing.txt for details.
4
 *
5
 * All rights reserved.
6
 *
7
 * @brief Keeps track of a single scout robot.
8
 * @file scout.cpp
9
 * @author Colony Project, CMU Robotics Club
10
 * @author Alex Zirbel
11
 */
12

  
13
#include "scoutsim/scout.h"
14

  
15
#include <wx/wx.h>
16

  
17
#define DEFAULT_PEN_R 0xb3
18
#define DEFAULT_PEN_G 0xb8
19
#define DEFAULT_PEN_B 0xff
20

  
21
namespace scoutsim
22
{
23

  
24
    Scout::Scout(const ros::NodeHandle& nh,
25
            const wxImage& scout_image,
26
            const Vector2& pos,
27
            float orient)
28
        : nh_(nh)
29
          , scout_image_(scout_image)
30
          , pos_(pos)
31
          , orient_(orient)
32
          , lin_vel_(0.0)
33
          , ang_vel_(0.0)
34
          , pen_on_(true)
35
          , pen_(wxColour(DEFAULT_PEN_R, DEFAULT_PEN_G, DEFAULT_PEN_B))
36
    {
37
        pen_.SetWidth(3);
38
        scout_ = wxBitmap(scout_image_);
39

  
40
        velocity_sub_ =
41
            nh_.subscribe("command_velocity",
42
                          1,
43
                          &Scout::velocityCallback, this);
44
        pose_pub_ = nh_.advertise<Pose>("pose", 1);
45
        color_pub_ = nh_.advertise<Color>("color_sensor", 1);
46
        set_pen_srv_ = nh_.advertiseService("set_pen",
47
                                            &Scout::setPenCallback,
48
                                            this);
49
        teleport_relative_srv_ =
50
            nh_.advertiseService("teleport_relative",
51
                                 &Scout::teleportRelativeCallback,
52
                                 this);
53
        teleport_absolute_srv_ =
54
            nh_.advertiseService("teleport_absolute",
55
                                 &Scout::teleportAbsoluteCallback,
56
                                 this);
57

  
58
        meter_ = scout_.GetHeight();
59
    }
60

  
61

  
62
    void Scout::velocityCallback(const VelocityConstPtr& vel)
63
    {
64
        last_command_time_ = ros::WallTime::now();
65
        lin_vel_ = vel->linear;
66
        ang_vel_ = vel->angular;
67
    }
68

  
69
    bool Scout::setPenCallback(scoutsim::SetPen::Request& req,
70
                               scoutsim::SetPen::Response&)
71
    {
72
        pen_on_ = !req.off;
73
        if (req.off)
74
        {
75
            return true;
76
        }
77

  
78
        wxPen pen(wxColour(req.r, req.g, req.b));
79
        if (req.width != 0)
80
        {
81
            pen.SetWidth(req.width);
82
        }
83

  
84
        pen_ = pen;
85
        return true;
86
    }
87

  
88
    bool Scout::teleportRelativeCallback(scoutsim::TeleportRelative::Request& req,
89
                                         scoutsim::TeleportRelative::Response&)
90
    {
91
        teleport_requests_.push_back(TeleportRequest(0,
92
                                                     0,
93
                                                     req.angular,
94
                                                     req.linear,
95
                                                     true));
96
        return true;
97
    }
98

  
99
    bool Scout::teleportAbsoluteCallback(scoutsim::TeleportAbsolute::Request& req,
100
                                         scoutsim::TeleportAbsolute::Response&)
101
    {
102
        teleport_requests_.push_back(TeleportRequest(req.x,
103
                                                     req.y,
104
                                                     req.theta,
105
                                                     0,
106
                                                     false));
107
        return true;
108
    }
109

  
110
    void Scout::update(double dt, wxMemoryDC& path_dc,
111
                        const wxImage& path_image, wxColour background_color,
112
                        float canvas_width, float canvas_height)
113
    {
114
        // first process any teleportation requests, in order
115
        V_TeleportRequest::iterator it = teleport_requests_.begin();
116
        V_TeleportRequest::iterator end = teleport_requests_.end();
117
        for (; it != end; ++it)
118
        {
119
            const TeleportRequest& req = *it;
120

  
121
            Vector2 old_pos = pos_;
122
            if (req.relative)
123
            {
124
                orient_ += req.theta;
125
                pos_.x += sin(orient_ + PI/2.0) * req.linear;
126
                pos_.y += cos(orient_ + PI/2.0) * req.linear;
127
            }
128
            else
129
            {
130
                pos_.x = req.pos.x;
131
                pos_.y = std::max(0.0f, canvas_height - req.pos.y);
132
                orient_ = req.theta;
133
            }
134

  
135
            path_dc.SetPen(pen_);
136
            path_dc.DrawLine(pos_.x * meter_, pos_.y * meter_,
137
                             old_pos.x * meter_, old_pos.y * meter_);
138
        }
139

  
140
        teleport_requests_.clear();
141

  
142
        if (ros::WallTime::now() - last_command_time_ > ros::WallDuration(1.0))
143
        {
144
            lin_vel_ = 0.0f;
145
            ang_vel_ = 0.0f;
146
        }
147

  
148
        Vector2 old_pos = pos_;
149

  
150
        orient_ = fmod(orient_ + ang_vel_ * dt, 2*PI);
151
        pos_.x += sin(orient_ + PI/2.0) * lin_vel_ * dt;
152
        pos_.y += cos(orient_ + PI/2.0) * lin_vel_ * dt;
153

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

  
161
        pos_.x = std::min(std::max(pos_.x, 0.0f), canvas_width);
162
        pos_.y = std::min(std::max(pos_.y, 0.0f), canvas_height);
163

  
164
        int canvas_x = pos_.x * meter_;
165
        int canvas_y = pos_.y * meter_;
166

  
167
        {
168
            wxImage rotated_image =
169
                scout_image_.Rotate(orient_ - PI/2.0,
170
                                    wxPoint(scout_image_.GetWidth() / 2,
171
                                            scout_image_.GetHeight() / 2),
172
                                    false);
173

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

  
187
            scout_ = wxBitmap(rotated_image);
188
        }
189

  
190
        Pose p;
191
        p.x = pos_.x;
192
        p.y = canvas_height - pos_.y;
193
        p.theta = orient_;
194
        p.linear_velocity = lin_vel_;
195
        p.angular_velocity = ang_vel_;
196
        pose_pub_.publish(p);
197

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

  
208
        ROS_DEBUG("[%s]: pos_x: %f pos_y: %f theta: %f",
209
                  nh_.getNamespace().c_str(), pos_.x, pos_.y, orient_);
210

  
211
        if (pen_on_)
212
        {
213
            if (pos_ != old_pos)
214
            {
215
                path_dc.SetPen(pen_);
216
                path_dc.DrawLine(pos_.x * meter_, pos_.y * meter_,
217
                                 old_pos.x * meter_, old_pos.y * meter_);
218
            }
219
        }
220
    }
221

  
222
    void Scout::paint(wxDC& dc)
223
    {
224
        wxSize scout_size = wxSize(scout_.GetWidth(), scout_.GetHeight());
225
        dc.DrawBitmap(scout_, pos_.x * meter_ - (scout_size.GetWidth() / 2),
226
                      pos_.y * meter_ - (scout_size.GetHeight() / 2), true);
227
    }
228

  
229
}
scout/scoutsim/src/scoutsim.cpp
1
/*
2
 * This package was developed by the CMU Robotics Club project using code
3
 * from Willow Garage, Inc.  Please see licensing.txt for details.
4
 *
5
 * All rights reserved.
6
 *
7
 * @brief Runs the simulator, keeping track of all the scout robots.
8
 * @file scoutsim.cpp
9
 * @author Colony Project, CMU Robotics Club
10
 * @author Alex Zirbel
11
 */
12

  
13
#include <wx/app.h>
14
#include <wx/timer.h>
15

  
16
#include <ros/ros.h>
17

  
18
#include <boost/thread.hpp>
19

  
20
#include "scoutsim/sim_frame.h"
21

  
22
#ifdef __WXMAC__
23
#include <ApplicationServices/ApplicationServices.h>
24
#endif
25

  
26
class ScoutApp : public wxApp
27
{
28
public:
29
  char** local_argv_;
30
  ros::NodeHandlePtr nh_;
31

  
32
  ScoutApp()
33
  {
34
  }
35

  
36
  bool OnInit()
37
  {
38
#ifdef __WXMAC__
39
    ProcessSerialNumber PSN;
40
    GetCurrentProcess(&PSN);
41
    TransformProcessType(&PSN,kProcessTransformToForegroundApplication);
42
    SetFrontProcess(&PSN);
43
#endif
44

  
45
    // create our own copy of argv, with regular char*s.
46
    local_argv_ =  new char*[ argc ];
47
    for ( int i = 0; i < argc; ++i )
48
    {
49
      local_argv_[ i ] = strdup( wxString( argv[ i ] ).mb_str() );
50
    }
51

  
52
    ros::init(argc, local_argv_, "scoutsim");
53
    nh_.reset(new ros::NodeHandle);
54

  
55
    wxInitAllImageHandlers();
56

  
57
    scoutsim::SimFrame* frame = new scoutsim::SimFrame(NULL);
58

  
59
    SetTopWindow(frame);
60
    frame->Show();
61

  
62
    return true;
63
  }
64

  
65
  int OnExit()
66
  {
67
    for ( int i = 0; i < argc; ++i )
68
    {
69
      free( local_argv_[ i ] );
70
    }
71
    delete [] local_argv_;
72

  
73
    return 0;
74
  }
75
};
76

  
77
DECLARE_APP(ScoutApp);
78
IMPLEMENT_APP(ScoutApp);
79

  
scout/scoutsim/src/sim_frame.cpp
1
/*
2
 * This package was developed by the CMU Robotics Club project using code
3
 * from Willow Garage, Inc.  Please see licensing.txt for details.
4
 *
5
 * All rights reserved.
6
 *
7
 * @brief Keeps track of the frame (visualization of the whole environment).
8
 * @file sim_frame.cpp
9
 * @author Colony Project, CMU Robotics Club
10
 * @author Alex Zirbel
11
 */
12

  
13
#include "scoutsim/sim_frame.h"
14

  
15
#include <ros/package.h>
16
#include <cstdlib>
17
#include <ctime>
18

  
19
#define DEFAULT_BG_R 0x45
20
#define DEFAULT_BG_G 0x56
21
#define DEFAULT_BG_B 0xff
22

  
23
namespace scoutsim
24
{
25

  
26
    SimFrame::SimFrame(wxWindow* parent)
27
        : wxFrame(parent, wxID_ANY, wxT("ScoutSim"), wxDefaultPosition,
28
                  wxSize(500, 500), wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER)
29
          , frame_count_(0)
30
          , id_counter_(0)
31
    {
32
        srand(time(NULL));
33

  
34
        update_timer_ = new wxTimer(this);
35
        update_timer_->Start(16);
36

  
37
        Connect(update_timer_->GetId(), wxEVT_TIMER,
38
                wxTimerEventHandler(SimFrame::onUpdate), NULL, this);
39
        Connect(wxEVT_PAINT, wxPaintEventHandler(SimFrame::onPaint),
40
                NULL, this);
41

  
42
        nh_.setParam("background_r", DEFAULT_BG_R);
43
        nh_.setParam("background_g", DEFAULT_BG_G);
44
        nh_.setParam("background_b", DEFAULT_BG_B);
45

  
46
        std::string scouts[SCOUTSIM_NUM_SCOUTS] = 
47
        {
48
            "box-turtle.png",
49
            "robot-turtle.png",
50
            "sea-turtle.png",
51
            "diamondback.png",
52
            "electric.png"
53
        };
54

  
55
        std::string images_path = ros::package::getPath("scoutsim")+"/images/";
56
        for (size_t i = 0; i < SCOUTSIM_NUM_SCOUTS; ++i)
57
        {
58
            scout_images_[i].LoadFile(
59
                wxString::FromAscii((images_path + scouts[i]).c_str()));
60
            scout_images_[i].SetMask(true);
61
            scout_images_[i].SetMaskColour(255, 255, 255);
62
        }
63

  
64
        meter_ = scout_images_[0].GetHeight();
65

  
66
        path_bitmap_ = wxBitmap(GetSize().GetWidth(), GetSize().GetHeight());
67
        path_dc_.SelectObject(path_bitmap_);
68
        clear();
69

  
70
        clear_srv_ = nh_.advertiseService("clear",
71
                                          &SimFrame::clearCallback, this);
72
        reset_srv_ = nh_.advertiseService("reset",
73
                                          &SimFrame::resetCallback, this);
74
        spawn_srv_ = nh_.advertiseService("spawn",
75
                                          &SimFrame::spawnCallback, this);
76
        kill_srv_ = nh_.advertiseService("kill",
77
                                         &SimFrame::killCallback, this);
78

  
79
        ROS_INFO("Starting scoutsim with node name %s",
80
                 ros::this_node::getName().c_str()) ;
81

  
82
        width_in_meters_ = GetSize().GetWidth() / meter_;
83
        height_in_meters_ = GetSize().GetHeight() / meter_;
84
        spawnScout("", width_in_meters_ / 2.0, height_in_meters_ / 2.0, 0);
85
    }
86

  
87
    SimFrame::~SimFrame()
88
    {
89
        delete update_timer_;
90
    }
91

  
92
    bool SimFrame::spawnCallback(scoutsim::Spawn::Request& req,
93
                                 scoutsim::Spawn::Response& res)
94
    {
95
        std::string name = spawnScout(req.name, req.x, req.y, req.theta);
96
        if (name.empty())
97
        {
98
            ROS_ERROR("A scout named [%s] already exists", req.name.c_str());
99
            return false;
100
        }
101

  
102
        res.name = name;
103

  
104
        return true;
105
    }
106

  
107
    bool SimFrame::killCallback(scoutsim::Kill::Request& req,
108
                                scoutsim::Kill::Response&)
109
    {
110
        M_Scout::iterator it = scouts_.find(req.name);
111
        if (it == scouts_.end())
112
        {
113
            ROS_ERROR("Tried to kill scout [%s], which does not exist",
114
                      req.name.c_str());
115
            return false;
116
        }
117

  
118
        scouts_.erase(it);
119

  
120
        return true;
121
    }
122

  
123
    bool SimFrame::hasScout(const std::string& name)
124
    {
125
        return scouts_.find(name) != scouts_.end();
126
    }
127

  
128
    std::string SimFrame::spawnScout(const std::string& name, float x,
129
                                       float y, float angle)
130
    {
131
        std::string real_name = name;
132
        if (real_name.empty())
133
        {
134
            do
135
            {
136
                std::stringstream ss;
137
                ss << "scout" << ++id_counter_;
138
                real_name = ss.str();
139
            } while (hasScout(real_name));
140
        }
141
        else
142
        {
143
            if (hasScout(real_name))
144
            {
145
                return "";
146
            }
147
        }
148

  
149
        ScoutPtr t(new Scout(ros::NodeHandle(real_name),
150
                   scout_images_[rand() % SCOUTSIM_NUM_SCOUTS],
151
                   Vector2(x, y), angle));
152
        scouts_[real_name] = t;
153

  
154
        ROS_INFO("Spawning scout [%s] at x=[%f], y=[%f], theta=[%f]",
155
                 real_name.c_str(), x, y, angle);
156

  
157
        return real_name;
158
    }
159

  
160
    void SimFrame::clear()
161
    {
162
        int r = DEFAULT_BG_R;
163
        int g = DEFAULT_BG_G;
164
        int b = DEFAULT_BG_B;
165

  
166
        nh_.param("background_r", r, r);
167
        nh_.param("background_g", g, g);
168
        nh_.param("background_b", b, b);
169

  
170
        path_dc_.SetBackground(wxBrush(wxColour(r, g, b)));
171
        path_dc_.Clear();
172
    }
173

  
174
    void SimFrame::onUpdate(wxTimerEvent& evt)
175
    {
176
        ros::spinOnce();
177

  
178
        updateScouts();
179

  
180
        if (!ros::ok())
181
        {
182
            Close();
183
        }
184
    }
185

  
186
    void SimFrame::onPaint(wxPaintEvent& evt)
187
    {
188
        wxPaintDC dc(this);
189

  
190
        dc.DrawBitmap(path_bitmap_, 0, 0, true);
191

  
192
        M_Scout::iterator it = scouts_.begin();
193
        M_Scout::iterator end = scouts_.end();
194
        for (; it != end; ++it)
195
        {
196
            it->second->paint(dc);
197
        }
198
    }
199

  
200
    void SimFrame::updateScouts()
201
    {
202
        if (last_scout_update_.isZero())
203
        {
204
            last_scout_update_ = ros::WallTime::now();
205
            return;
206
        }
207

  
208
        if (frame_count_ % 3 == 0)
209
        {
210
            path_image_ = path_bitmap_.ConvertToImage();
211
            Refresh();
212
        }
213

  
214
        M_Scout::iterator it = scouts_.begin();
215
        M_Scout::iterator end = scouts_.end();
216
        for (; it != end; ++it)
217
        {
218
            it->second->update(0.016, path_dc_, path_image_,
219
                               path_dc_.GetBackground().GetColour(),
220
                               width_in_meters_, height_in_meters_);
221
        }
222

  
223
        ++frame_count_;
224
    }
225

  
226

  
227
    bool SimFrame::clearCallback(std_srvs::Empty::Request&,
228
                                 std_srvs::Empty::Response&)
229
    {
230
        ROS_INFO("Clearing scoutsim.");
231
        clear();
232
        return true;
233
    }
234

  
235
    bool SimFrame::resetCallback(std_srvs::Empty::Request&,
236
                                 std_srvs::Empty::Response&)
237
    {
238
        ROS_INFO("Resetting scoutsim.");
239
        scouts_.clear();
240
        id_counter_ = 0;
241
        spawnScout("", width_in_meters_ / 2.0, height_in_meters_ / 2.0, 0);
242
        clear();
243
        return true;
244
    }
245

  
246
}
scout/scoutsim/srv/Kill.srv
1
string name
2
---
scout/scoutsim/srv/SetPen.srv
1
uint8 r
2
uint8 g
3
uint8 b
4
uint8 width
5
uint8 off
6
---
scout/scoutsim/srv/Spawn.srv
1
float32 x
2
float32 y
3
float32 theta
4
string name # Optional.  A unique name will be created and returned if this is empty
5
---
6
string name
scout/scoutsim/srv/TeleportAbsolute.srv
1
float32 x
2
float32 y
3
float32 theta
4
---
scout/scoutsim/srv/TeleportRelative.srv
1
float32 linear
2
float32 angular
3
---

Also available in: Unified diff