$search
00001 /* 00002 * Copyright (c) 2009, Willow Garage, Inc. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of the Willow Garage, Inc. nor the names of its 00014 * contributors may be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 #include "turtlesim/turtle_frame.h" 00031 00032 #include <ros/package.h> 00033 #include <cstdlib> 00034 #include <ctime> 00035 00036 #define DEFAULT_BG_R 0x45 00037 #define DEFAULT_BG_G 0x56 00038 #define DEFAULT_BG_B 0xff 00039 00040 namespace turtlesim 00041 { 00042 00043 TurtleFrame::TurtleFrame(wxWindow* parent) 00044 : wxFrame(parent, wxID_ANY, wxT("TurtleSim"), wxDefaultPosition, wxSize(500, 500), wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER) 00045 , frame_count_(0) 00046 , id_counter_(0) 00047 { 00048 srand(time(NULL)); 00049 00050 update_timer_ = new wxTimer(this); 00051 update_timer_->Start(16); 00052 00053 Connect(update_timer_->GetId(), wxEVT_TIMER, wxTimerEventHandler(TurtleFrame::onUpdate), NULL, this); 00054 Connect(wxEVT_PAINT, wxPaintEventHandler(TurtleFrame::onPaint), NULL, this); 00055 00056 nh_.setParam("background_r", DEFAULT_BG_R); 00057 nh_.setParam("background_g", DEFAULT_BG_G); 00058 nh_.setParam("background_b", DEFAULT_BG_B); 00059 00060 std::string turtles[TURTLESIM_NUM_TURTLES] = 00061 { 00062 "box-turtle.png", 00063 "robot-turtle.png", 00064 "sea-turtle.png", 00065 "diamondback.png", 00066 "electric.png" 00067 }; 00068 00069 std::string images_path = ros::package::getPath("turtlesim") + "/images/"; 00070 for (size_t i = 0; i < TURTLESIM_NUM_TURTLES; ++i) 00071 { 00072 turtle_images_[i].LoadFile(wxString::FromAscii((images_path + turtles[i]).c_str())); 00073 turtle_images_[i].SetMask(true); 00074 turtle_images_[i].SetMaskColour(255, 255, 255); 00075 } 00076 00077 meter_ = turtle_images_[0].GetHeight(); 00078 00079 path_bitmap_ = wxBitmap(GetSize().GetWidth(), GetSize().GetHeight()); 00080 path_dc_.SelectObject(path_bitmap_); 00081 clear(); 00082 00083 clear_srv_ = nh_.advertiseService("clear", &TurtleFrame::clearCallback, this); 00084 reset_srv_ = nh_.advertiseService("reset", &TurtleFrame::resetCallback, this); 00085 spawn_srv_ = nh_.advertiseService("spawn", &TurtleFrame::spawnCallback, this); 00086 kill_srv_ = nh_.advertiseService("kill", &TurtleFrame::killCallback, this); 00087 00088 ROS_INFO("Starting turtlesim with node name %s", ros::this_node::getName().c_str()) ; 00089 00090 width_in_meters_ = GetSize().GetWidth() / meter_; 00091 height_in_meters_ = GetSize().GetHeight() / meter_; 00092 spawnTurtle("", width_in_meters_ / 2.0, height_in_meters_ / 2.0, 0); 00093 } 00094 00095 TurtleFrame::~TurtleFrame() 00096 { 00097 delete update_timer_; 00098 } 00099 00100 bool TurtleFrame::spawnCallback(turtlesim::Spawn::Request& req, turtlesim::Spawn::Response& res) 00101 { 00102 std::string name = spawnTurtle(req.name, req.x, req.y, req.theta); 00103 if (name.empty()) 00104 { 00105 ROS_ERROR("A turtled named [%s] already exists", req.name.c_str()); 00106 return false; 00107 } 00108 00109 res.name = name; 00110 00111 return true; 00112 } 00113 00114 bool TurtleFrame::killCallback(turtlesim::Kill::Request& req, turtlesim::Kill::Response&) 00115 { 00116 M_Turtle::iterator it = turtles_.find(req.name); 00117 if (it == turtles_.end()) 00118 { 00119 ROS_ERROR("Tried to kill turtle [%s], which does not exist", req.name.c_str()); 00120 return false; 00121 } 00122 00123 turtles_.erase(it); 00124 00125 return true; 00126 } 00127 00128 bool TurtleFrame::hasTurtle(const std::string& name) 00129 { 00130 return turtles_.find(name) != turtles_.end(); 00131 } 00132 00133 std::string TurtleFrame::spawnTurtle(const std::string& name, float x, float y, float angle) 00134 { 00135 std::string real_name = name; 00136 if (real_name.empty()) 00137 { 00138 do 00139 { 00140 std::stringstream ss; 00141 ss << "turtle" << ++id_counter_; 00142 real_name = ss.str(); 00143 } while (hasTurtle(real_name)); 00144 } 00145 else 00146 { 00147 if (hasTurtle(real_name)) 00148 { 00149 return ""; 00150 } 00151 } 00152 00153 TurtlePtr t(new Turtle(ros::NodeHandle(real_name), turtle_images_[rand() % TURTLESIM_NUM_TURTLES], Vector2(x, y), angle)); 00154 turtles_[real_name] = t; 00155 00156 ROS_INFO("Spawning turtle [%s] at x=[%f], y=[%f], theta=[%f]", real_name.c_str(), x, y, angle); 00157 00158 return real_name; 00159 } 00160 00161 void TurtleFrame::clear() 00162 { 00163 int r = DEFAULT_BG_R; 00164 int g = DEFAULT_BG_G; 00165 int b = DEFAULT_BG_B; 00166 00167 nh_.param("background_r", r, r); 00168 nh_.param("background_g", g, g); 00169 nh_.param("background_b", b, b); 00170 00171 path_dc_.SetBackground(wxBrush(wxColour(r, g, b))); 00172 path_dc_.Clear(); 00173 } 00174 00175 void TurtleFrame::onUpdate(wxTimerEvent& evt) 00176 { 00177 ros::spinOnce(); 00178 00179 updateTurtles(); 00180 00181 if (!ros::ok()) 00182 { 00183 Close(); 00184 } 00185 } 00186 00187 void TurtleFrame::onPaint(wxPaintEvent& evt) 00188 { 00189 wxPaintDC dc(this); 00190 00191 dc.DrawBitmap(path_bitmap_, 0, 0, true); 00192 00193 M_Turtle::iterator it = turtles_.begin(); 00194 M_Turtle::iterator end = turtles_.end(); 00195 for (; it != end; ++it) 00196 { 00197 it->second->paint(dc); 00198 } 00199 } 00200 00201 void TurtleFrame::updateTurtles() 00202 { 00203 if (last_turtle_update_.isZero()) 00204 { 00205 last_turtle_update_ = ros::WallTime::now(); 00206 return; 00207 } 00208 00209 if (frame_count_ % 3 == 0) 00210 { 00211 path_image_ = path_bitmap_.ConvertToImage(); 00212 Refresh(); 00213 } 00214 00215 M_Turtle::iterator it = turtles_.begin(); 00216 M_Turtle::iterator end = turtles_.end(); 00217 for (; it != end; ++it) 00218 { 00219 it->second->update(0.016, path_dc_, path_image_, path_dc_.GetBackground().GetColour(), width_in_meters_, height_in_meters_); 00220 } 00221 00222 ++frame_count_; 00223 } 00224 00225 00226 bool TurtleFrame::clearCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&) 00227 { 00228 ROS_INFO("Clearing turtlesim."); 00229 clear(); 00230 return true; 00231 } 00232 00233 bool TurtleFrame::resetCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&) 00234 { 00235 ROS_INFO("Resetting turtlesim."); 00236 turtles_.clear(); 00237 id_counter_ = 0; 00238 spawnTurtle("", width_in_meters_ / 2.0, height_in_meters_ / 2.0, 0); 00239 clear(); 00240 return true; 00241 } 00242 00243 }