Project

General

Profile

Statistics
| Branch: | Revision:

robobuggy / turtlesim_ref / src / turtle_frame.cpp @ dd5d7f53

History | View | Annotate | Download (6.5 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 "turtlesim/turtle_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 turtlesim_ref
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("TurtleSim");
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("turtlesim") + "/images/").c_str();
78
  for (size_t i = 0; i < turtles.size(); ++i)
79
  {
80
    QImage img;
81
    img.load(images_path + turtles[i]);
82
    turtle_images_.append(img);
83
  }
84

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

    
87
  clear();
88

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

    
94
  ROS_INFO("Starting turtlesim with node name %s", 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(turtlesim_ref::Spawn::Request& req, 
107
                                turtlesim_ref::Spawn::Response& res)
108
{
109
  std::string name = spawnTurtle(req.name, req.x, req.y, req.theta);
110
  if (name.empty())
111
  {
112
    ROS_ERROR("A turtled named [%s] already exists", req.name.c_str());
113
    return false;
114
  }
115

    
116
  res.name = name;
117

    
118
  return true;
119
}
120

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

    
131
  turtles_.erase(it);
132
  update();
133

    
134
  return true;
135
}
136

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

    
142
std::string TurtleFrame::spawnTurtle(const std::string& name, float x, float y, float angle)
143
{
144
  std::string real_name = name;
145
  if (real_name.empty())
146
  {
147
    do
148
    {
149
      std::stringstream ss;
150
      ss << "turtle" << ++id_counter_;
151
      real_name = ss.str();
152
    } while (hasTurtle(real_name));
153
  }
154
  else
155
  {
156
    if (hasTurtle(real_name))
157
    {
158
      return "";
159
    }
160
  }
161

    
162
  TurtlePtr t(new Turtle(ros::NodeHandle(real_name), turtle_images_[rand() % turtle_images_.size()], QPointF(x, y), angle));
163
  turtles_[real_name] = t;
164
  update();
165

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

    
168
  return real_name;
169
}
170

    
171
void TurtleFrame::clear()
172
{
173
  int r = DEFAULT_BG_R;
174
  int g = DEFAULT_BG_G;
175
  int b = DEFAULT_BG_B;
176

    
177
  nh_.param("background_r", r, r);
178
  nh_.param("background_g", g, g);
179
  nh_.param("background_b", b, b);
180

    
181
  path_image_.fill(qRgb(r, g, b));
182
  update();
183
}
184

    
185
void TurtleFrame::onUpdate()
186
{
187
  ros::spinOnce();
188

    
189
  updateTurtles();
190

    
191
  if (!ros::ok())
192
  {
193
    close();
194
  }
195
}
196

    
197
void TurtleFrame::paintEvent(QPaintEvent* event)
198
{
199
  QPainter painter(this);
200

    
201
  painter.drawImage(QPoint(0, 0), path_image_);
202

    
203
  M_Turtle::iterator it = turtles_.begin();
204
  M_Turtle::iterator end = turtles_.end();
205
  for (; it != end; ++it)
206
  {
207
    it->second->paint(painter);
208
  }
209
}
210

    
211
void TurtleFrame::updateTurtles()
212
{
213
  if (last_turtle_update_.isZero())
214
  {
215
    last_turtle_update_ = ros::WallTime::now();
216
    return;
217
  }
218

    
219
  bool modified = false;
220
  M_Turtle::iterator it = turtles_.begin();
221
  M_Turtle::iterator end = turtles_.end();
222
  for (; it != end; ++it)
223
  {
224
    modified |= it->second->update(0.001 * update_timer_->interval(), path_painter_, path_image_, width_in_meters_, height_in_meters_);
225
  }
226
  if (modified)
227
  {
228
    update();
229
  }
230

    
231
  ++frame_count_;
232
}
233

    
234

    
235
bool TurtleFrame::clearCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
236
{
237
  ROS_INFO("Clearing turtlesim.");
238
  clear();
239
  return true;
240
}
241

    
242
bool TurtleFrame::resetCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&)
243
{
244
  ROS_INFO("Resetting turtlesim.");
245
  turtles_.clear();
246
  id_counter_ = 0;
247
  spawnTurtle("", width_in_meters_ / 2.0, height_in_meters_ / 2.0, 0);
248
  clear();
249
  return true;
250
}
251

    
252
}