Project

General

Profile

Statistics
| Branch: | Revision:

robobuggy / buggysim / src / buggy.cpp @ 005151be

History | View | Annotate | Download (7.26 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/buggy.h"
31

    
32
#include <QColor>
33
#include <QRgb>
34

    
35
#define DEFAULT_PEN_R 0xb3
36
#define DEFAULT_PEN_G 0xb8
37
#define DEFAULT_PEN_B 0xff
38

    
39
namespace turtlesim
40
{
41

    
42
Turtle::Turtle(const ros::NodeHandle& nh, const QImage& turtle_image, const QPointF& pos, float orient)
43
: nh_(nh)
44
, turtle_image_(turtle_image)
45
, pos_(pos)
46
, orient_(orient)
47
, lin_vel_(2.0)
48
  //, ang_vel_(0.0)
49
, turnAngle_(0.0)
50
, pen_on_(true)
51
, pen_(QColor(DEFAULT_PEN_R, DEFAULT_PEN_G, DEFAULT_PEN_B))
52
{
53
  pen_.setWidth(3);
54

    
55
  angle_sub_ = nh_.subscribe
56
         ("command_turnAngle", 1, &Turtle::turnAngleCallback, this);
57
  pose_pub_ = nh_.advertise<buggymsgs::Pose>("pose", 1);
58

    
59
  //color_pub_ = nh_.advertise<Color>("color_sensor", 1);
60
  set_pen_srv_ = nh_.advertiseService
61
         ("set_pen", &Turtle::setPenCallback, this);
62
  teleport_relative_srv_ = nh_.advertiseService
63
         ("teleport_relative", &Turtle::teleportRelativeCallback, this);
64
  teleport_absolute_srv_ = nh_.advertiseService
65
         ("teleport_absolute", &Turtle::teleportAbsoluteCallback, this);
66

    
67
  meter_ = turtle_image_.height();
68
  rotateImage();
69
}
70

    
71

    
72
  void Turtle::turnAngleCallback(const buggymsgs::DirectionConstPtr& dir)
73
{
74
  last_command_time_ = ros::WallTime::now();
75
  turnAngle_ = dir->turnAngle;
76
  //lin_vel_ = vel->linear;
77
  //ang_vel_ = vel->angular;
78
}
79

    
80
bool Turtle::setPenCallback(turtlesim::SetPen::Request& req, turtlesim::SetPen::Response&)
81
{
82
  pen_on_ = !req.off;
83
  if (req.off)
84
  {
85
    return true;
86
  }
87

    
88
  QPen pen(QColor(req.r, req.g, req.b));
89
  if (req.width != 0)
90
  {
91
    pen.setWidth(req.width);
92
  }
93

    
94
  pen_ = pen;
95
  return true;
96
}
97

    
98
bool Turtle::teleportRelativeCallback(turtlesim::TeleportRelative::Request& req, turtlesim::TeleportRelative::Response&)
99
{
100
  teleport_requests_.push_back(TeleportRequest(0, 0, req.angular, req.linear, true));
101
  return true;
102
}
103

    
104
bool Turtle::teleportAbsoluteCallback(turtlesim::TeleportAbsolute::Request& req, turtlesim::TeleportAbsolute::Response&)
105
{
106
  teleport_requests_.push_back(TeleportRequest(req.x, req.y, req.theta, 0, false));
107
  return true;
108
}
109

    
110
void Turtle::rotateImage()
111
{
112
  QTransform transform;
113
  transform.rotate(-orient_ * 180.0 / PI + 90.0);
114
  turtle_rotated_image_ = turtle_image_.transformed(transform);
115
}
116

    
117
/**
118
 * TODO: convert this to take just an angle. And include drag. 
119
 *       and include acceleration/joule dump
120
 */
121
bool Turtle::update(double dt, QPainter& path_painter, const QImage& path_image, qreal canvas_width, qreal canvas_height)
122
{
123
  bool modified = false;
124
  qreal old_orient = orient_;
125

    
126
  // first process any teleportation requests, in order
127
  V_TeleportRequest::iterator it = teleport_requests_.begin();
128
  V_TeleportRequest::iterator end = teleport_requests_.end();
129
  for (; it != end; ++it)
130
  {
131
    const TeleportRequest& req = *it;
132

    
133
    QPointF old_pos = pos_;
134
    if (req.relative)
135
    {
136
      orient_ += req.theta;
137
      pos_.rx() += std::sin(orient_ + PI/2.0) * req.linear;
138
      pos_.ry() += std::cos(orient_ + PI/2.0) * req.linear;
139
    }
140
    else
141
    {
142
      pos_.setX(req.pos.x());
143
      pos_.setY(std::max(0.0, static_cast<double>(canvas_height - req.pos.y())));
144
      orient_ = req.theta;
145
    }
146

    
147
    path_painter.setPen(pen_);
148
    path_painter.drawLine(pos_ * meter_, old_pos * meter_);
149
    modified = true;
150
  }
151

    
152
  teleport_requests_.clear();
153

    
154
  // Stop moving after 1 second since-last command.
155
  //if (ros::WallTime::now() - last_command_time_ > ros::WallDuration(1.0))
156
  //{
157
  //  lin_vel_ = 0.0;
158
  //  ang_vel_ = 0.0;
159
  //}
160

    
161
  // Update my position
162
  QPointF old_pos = pos_;
163

    
164
  /* Convert coordinate systens
165
  orient_ = std::fmod(orient_ + ang_vel_ * dt, 2*PI);
166
  pos_.rx() += std::sin(orient_ + PI/2.0) * lin_vel_ * dt;
167
  pos_.ry() += std::cos(orient_ + PI/2.0) * lin_vel_ * dt;
168
  */
169
  // TODO: what direction does orientation start at 0?
170
  // TODO: orient might have to become negative
171
  orient_ = std::fmod(orient_ - turnAngle_ * dt, 2*PI);
172
  // TODO: why add pi/2? is this just because they got the 
173
  //       sin/cos mixed up?
174
  pos_.rx() += std::sin(orient_ + PI/2.0) * lin_vel_ * dt;
175
  pos_.ry() += std::cos(orient_ + PI/2.0) * lin_vel_ * dt;
176

    
177
  // Find linear velocity
178
  //qreal lin_vel;
179
  // Find angular velocity
180
  //qreal ang_vel;
181

    
182
  // Clamp to screen size
183
  // TODO: change to use another image, to detect walls. 
184
  if (pos_.x() < 0 || pos_.x() > canvas_width ||
185
      pos_.y() < 0 || pos_.y() > canvas_height)
186
  {
187
    ROS_WARN("Oh no! I hit the wall! (Clamping from [x=%f, y=%f])", pos_.x(), pos_.y());
188
  }
189

    
190
  pos_.setX(std::min(std::max(static_cast<double>(pos_.x()), 0.0), 
191
                             static_cast<double>(canvas_width)));
192
  pos_.setY(std::min(std::max(static_cast<double>(pos_.y()), 0.0), 
193
                             static_cast<double>(canvas_height)));
194

    
195
  // Publish pose of the turtle
196
  buggymsgs::Pose p;
197
  p.x = pos_.x();
198
  p.y = canvas_height - pos_.y();
199
  p.angle = orient_;
200
  p.linear_velocity = lin_vel_;
201
  //p.angular_velocity = ang_vel;
202
  pose_pub_.publish(p);
203

    
204
  // Figure out (and publish) the color underneath the turtle
205
  /*{
206
    Color color;
207
    QRgb pixel = path_image.pixel((pos_ * meter_).toPoint());
208
    color.r = qRed(pixel);
209
    color.g = qGreen(pixel);
210
    color.b = qBlue(pixel);
211
    color_pub_.publish(color);
212
    }*/
213

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

    
216
  if (orient_ != old_orient)
217
  {
218
    rotateImage();
219
    modified = true;
220
  }
221
  if (pos_ != old_pos)
222
  {
223
    if (pen_on_)
224
    {
225
      path_painter.setPen(pen_);
226
      path_painter.drawLine(pos_ * meter_, old_pos * meter_);
227
    }
228
    modified = true;
229
  }
230

    
231
  return modified;
232
}
233

    
234
void Turtle::paint(QPainter& painter)
235
{
236
  QPointF p = pos_ * meter_;
237
  p.rx() -= 0.5 * turtle_rotated_image_.width();
238
  p.ry() -= 0.5 * turtle_rotated_image_.height();
239
  painter.drawImage(p, turtle_rotated_image_);
240
}
241

    
242
}