Project

General

Profile

Statistics
| Branch: | Revision:

robobuggy / buggysim / src / sim_frame.cpp @ 08be08ec

History | View | Annotate | Download (7.35 KB)

1
/*
2
 * Copyright (c) 2009, Willow Garage, Inc.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 *     * Redistributions of source code must retain the above copyright
9
 *       notice, this list of conditions and the following disclaimer.
10
 *     * Redistributions in binary form must reproduce the above copyright
11
 *       notice, this list of conditions and the following disclaimer in the
12
 *       documentation and/or other materials provided with the distribution.
13
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
14
 *       contributors may be used to endorse or promote products derived from
15
 *       this software without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
 * POSSIBILITY OF SUCH DAMAGE.
28
 */
29

    
30
#include "buggysim/sim_frame.h"
31

    
32
#include <QPointF>
33

    
34
#include <ros/package.h>
35
#include <cstdlib>
36
#include <ctime>
37

    
38
#define DEFAULT_BG_R 0x45
39
#define DEFAULT_BG_G 0x56
40
#define DEFAULT_BG_B 0xff
41

    
42
namespace buggysim
43
{
44

    
45
   TurtleFrame::TurtleFrame(QWidget* parent, Qt::WindowFlags f)
46
      : QFrame(parent, f)
47
      , path_image_(500, 500, QImage::Format_ARGB32)
48
      , path_painter_(&path_image_)
49
      , frame_count_(0)
50
      , id_counter_(0)
51
   {
52
      setFixedSize(500, 500);
53
      setWindowTitle("BuggySim Frame!");
54

    
55
      srand(time(NULL));
56

    
57
      update_timer_ = new QTimer(this);
58
      update_timer_->setInterval(16);
59
      update_timer_->start();
60

    
61
      connect(update_timer_, SIGNAL(timeout()), this, SLOT(onUpdate()));
62

    
63
      nh_.setParam("background_r", DEFAULT_BG_R);
64
      nh_.setParam("background_g", DEFAULT_BG_G);
65
      nh_.setParam("background_b", DEFAULT_BG_B);
66

    
67
      QVector<QString> turtles;
68
      turtles.append("box-turtle.png");
69
      turtles.append("robot-turtle.png");
70
      turtles.append("sea-turtle.png");
71
      turtles.append("diamondback.png");
72
      turtles.append("electric.png");
73
      turtles.append("fuerte.png");
74
      turtles.append("groovy.png");
75
      turtles.append("hydro.svg");
76

    
77
      QString images_path = (ros::package::getPath("buggysim") + "/images/").c_str();
78
      for (size_t i = 0; i < turtles.size(); ++i) {
79
         QImage img;
80
         img.load(images_path + turtles[i]);
81
         turtle_images_.append(img);
82
      }
83

    
84
      meter_ = turtle_images_[0].height();
85

    
86
      clear();
87

    
88
      clear_srv_ = nh_.advertiseService("clear", &TurtleFrame::clearCallback, this);
89
      reset_srv_ = nh_.advertiseService("reset", &TurtleFrame::resetCallback, this);
90
      spawn_srv_ = nh_.advertiseService("spawn", &TurtleFrame::spawnCallback, this);
91
      kill_srv_ = nh_.advertiseService("kill", &TurtleFrame::killCallback, this);
92

    
93
      ROS_INFO("Starting buggysim with node name %s",
94
               ros::this_node::getName().c_str()) ;
95

    
96
      width_in_meters_ = (width() - 1) / meter_;
97
      height_in_meters_ = (height() - 1) / meter_;
98
      spawnTurtle("", width_in_meters_ / 2.0, height_in_meters_ / 2.0, 0);
99
   }
100

    
101
   TurtleFrame::~TurtleFrame()
102
   {
103
      delete update_timer_;
104
   }
105

    
106
   bool TurtleFrame::spawnCallback(buggysim::Spawn::Request& req,
107
                                   buggysim::Spawn::Response& res)
108
   {
109
      std::string name = spawnTurtle(req.name, req.x, req.y, req.theta);
110
      if (name.empty()) {
111
         ROS_ERROR("A turtled named [%s] already exists", req.name.c_str());
112
         return false;
113
      }
114

    
115
      res.name = name;
116

    
117
      return true;
118
   }
119

    
120
   bool TurtleFrame::killCallback(buggysim::Kill::Request& req,
121
                                  buggysim::Kill::Response&)
122
   {
123
      M_Turtle::iterator it = turtles_.find(req.name);
124
      if (it == turtles_.end()) {
125
         ROS_ERROR("Tried to kill turtle [%s], which does not exist", req.name.c_str());
126
         return false;
127
      }
128

    
129
      turtles_.erase(it);
130
      update();
131

    
132
      return true;
133
   }
134

    
135
   bool TurtleFrame::hasTurtle(const std::string& name)
136
   {
137
      return turtles_.find(name) != turtles_.end();
138
   }
139

    
140
   std::string TurtleFrame::spawnTurtle(const std::string& name, float x, float y,
141
                                        float angle)
142
   {
143
      std::string real_name = name;
144
      if (real_name.empty()) {
145
         do {
146
            std::stringstream ss;
147
            // TODO: change how turtles are spawned
148
            ss << "buggy" << ++id_counter_;
149
            real_name = ss.str();
150
         } while (hasTurtle(real_name));
151
      } else {
152
         if (hasTurtle(real_name)) {
153
            return "";
154
         }
155
      }
156

    
157
      TurtlePtr t(new Turtle(ros::NodeHandle(real_name),
158
                             turtle_images_[rand() % turtle_images_.size()], QPointF(x, y), angle));
159
      turtles_[real_name] = t;
160
      update();
161

    
162
      ROS_INFO("Spawning turtle [%s] at x=[%f], y=[%f], theta=[%f]",
163
               real_name.c_str(), x, y, angle);
164

    
165
      return real_name;
166
   }
167

    
168
   void TurtleFrame::clear()
169
   {
170
      int r = DEFAULT_BG_R;
171
      int g = DEFAULT_BG_G;
172
      int b = DEFAULT_BG_B;
173

    
174
      nh_.param("background_r", r, r);
175
      nh_.param("background_g", g, g);
176
      nh_.param("background_b", b, b);
177

    
178
      path_image_.fill(qRgb(r, g, b));
179
      update();
180
   }
181

    
182
   void TurtleFrame::onUpdate()
183
   {
184
      ros::spinOnce();
185

    
186
      updateTurtles();
187

    
188
      if (!ros::ok()) {
189
         close();
190
      }
191
   }
192

    
193
   void TurtleFrame::paintEvent(QPaintEvent* event)
194
   {
195
      QPainter painter(this);
196

    
197
      painter.drawImage(QPoint(0, 0), path_image_);
198

    
199
      M_Turtle::iterator it = turtles_.begin();
200
      M_Turtle::iterator end = turtles_.end();
201
      for (; it != end; ++it) {
202
         it->second->paint(painter);
203
      }
204
   }
205

    
206
   void TurtleFrame::updateTurtles()
207
   {
208
      if (last_turtle_update_.isZero()) {
209
         last_turtle_update_ = ros::WallTime::now();
210
         return;
211
      }
212

    
213
      bool modified = false;
214
      M_Turtle::iterator it = turtles_.begin();
215
      M_Turtle::iterator end = turtles_.end();
216
      for (; it != end; ++it) {
217
         modified |= it->second->update(0.001 * update_timer_->interval(), path_painter_,
218
                                        path_image_, width_in_meters_, height_in_meters_);
219
      }
220
      if (modified) {
221
         update();
222
      }
223

    
224
      ++frame_count_;
225
   }
226

    
227

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

    
236
   bool TurtleFrame::resetCallback(std_srvs::Empty::Request&,
237
                                   std_srvs::Empty::Response&)
238
   {
239
      ROS_INFO("Resetting turtlesim.");
240
      turtles_.clear();
241
      id_counter_ = 0;
242
      spawnTurtle("", width_in_meters_ / 2.0, height_in_meters_ / 2.0, 0);
243
      clear();
244
      return true;
245
   }
246

    
247
}