commit 0e1437375725a603024b971caa12b204c102b80a
Author: Hui Jun Tay <viki@c3po.(none)>
Date:   Sun Oct 13 12:41:02 2013 -0500

    Created Emitter class based on Scout class
    Added command 'spawn_em' to spawn emitters

diff --git a/scout/scoutsim/CMakeLists.txt b/scout/scoutsim/CMakeLists.txt
index 59058eb..faeec1c 100644
--- a/scout/scoutsim/CMakeLists.txt
+++ b/scout/scoutsim/CMakeLists.txt
@@ -28,6 +28,6 @@ include(${wxWidgets_USE_FILE})
 include_directories( ${wxWidgets_INCLUDE_DIRS} )
 
 rosbuild_add_boost_directories()
-rosbuild_add_executable(scoutsim_node src/scoutsim.cpp src/scout.cpp src/ghost_scout.cpp src/sim_frame.cpp)
+rosbuild_add_executable(scoutsim_node src/scoutsim.cpp src/scout.cpp src/ghost_scout.cpp src/sim_frame.cpp src/emitter.cpp)
 rosbuild_link_boost(scoutsim_node thread)
 target_link_libraries(scoutsim_node ${wxWidgets_LIBRARIES})
diff --git a/scout/scoutsim/src/sim_frame.cpp b/scout/scoutsim/src/sim_frame.cpp
index 31b9b15..34d29c5 100644
--- a/scout/scoutsim/src/sim_frame.cpp
+++ b/scout/scoutsim/src/sim_frame.cpp
@@ -119,6 +119,8 @@ namespace scoutsim
                                         &SimFrame::resetCallback, this);
         spawn_srv = nh.advertiseService("spawn",
                                         &SimFrame::spawnCallback, this);
+        spawn_em_srv = nh.advertiseService("spawn_em",
+                                        &SimFrame::spawnEmCallback, this);
         kill_srv = nh.advertiseService("kill",
                                         &SimFrame::killCallback, this);
         set_sonar_viz_srv = nh.advertiseService("set_sonar_viz",
@@ -134,6 +136,10 @@ namespace scoutsim
         wireless_send = nh.subscribe("/wireless/send", 1000,
             &SimFrame::wirelessCallback, this);
 
+        //Emitter default values
+        em_aperture = PI / 6.0;
+        em_distance = 2;
+
         // Teleop
         teleop_type = TELEOP_OFF;
         teleop_l_speed = 0;
@@ -196,6 +202,21 @@ namespace scoutsim
         return true;
     }
 
+
+    bool SimFrame::spawnEmCallback(scoutsim::Spawn::Request  &req,
+                                 scoutsim::Spawn::Response &res)
+    {
+        std::string name = spawnEmitter(req.name, req.x, req.y, req.theta);
+        if (name.empty())
+        {
+            ROS_WARN("An emitter named [%s] already exists", req.name.c_str());
+            return false;
+        }
+
+        res.name = name;
+        return true;
+    }
+
     bool SimFrame::killCallback(scoutsim::Kill::Request& req,
                                 scoutsim::Kill::Response&)
     {
@@ -261,6 +282,11 @@ namespace scoutsim
         return scouts.find(name) != scouts.end();
     }
 
+    bool SimFrame::hasEmitter(const std::string& name)
+    {
+        return emitters.find(name) != emitters.end();
+    }
+
     std::string SimFrame::spawnScout(const std::string& name,
                                      float x, float y, float angle)
     {
@@ -315,6 +341,61 @@ namespace scoutsim
         return real_name;
     }
 
+
+    std::string SimFrame::spawnEmitter(const std::string& name,
+                                     float x, float y, float angle)
+    {
+        std::string real_name = name;
+        if (real_name.empty())
+        {
+            // Generate the name emitterX, where X is an increasing number.
+            do
+            {
+                std::stringstream ss;
+                ss << "emitter" << ++id_counter;
+                real_name = ss.str();
+            }
+            while (hasEmitter(real_name));
+        }
+        else
+        {
+            if (hasEmitter(real_name))
+            {
+                return "";
+            }
+        }
+
+        wxImage emitter_image;
+
+        // Try to load a name-specific image; if not, load the default emitter
+        string specific_name = images_path + name + ".png";
+        if (fileExists(specific_name))
+        {
+            emitter_image.LoadFile(wxString::FromAscii(specific_name.c_str()));
+            emitter_image.SetMask(true);
+            emitter_image.SetMaskColour(255, 255, 255);
+        }
+        else
+        {
+            ROS_INFO("LOADED EMITTER IMAGE");
+            emitter_image.LoadFile(
+                wxString::FromAscii((images_path + "emitter.png").c_str()));
+            emitter_image.SetMask(true);
+            emitter_image.SetMaskColour(255, 255, 255);
+        }
+
+        EmitterPtr t(new Emitter(ros::NodeHandle(real_name),
+                   emitter_image, Vector2(x, y), &path_bitmap, 
+                   angle, em_aperture, em_distance));
+        emitters[real_name] = t;
+
+        ROS_INFO("Spawning emitter [%s] at x=[%f], y=[%f], theta=[%f]",
+                 real_name.c_str(), x, y, angle);
+
+        return real_name;
+    }
+
+
     void SimFrame::onQuit(wxCommandEvent& WXUNUSED(event))
     {
         Close(true);
@@ -397,6 +478,15 @@ namespace scoutsim
         {
             it->second->paint(dc);
         }
+
+
+        M_Emitter::iterator m_it = emitters.begin();
+        M_Emitter::iterator m_end = emitters.end();
+        for (; m_it != m_end; ++m_it)
+        {
+            m_it->second->paint(dc);
+        }
+
         for (unsigned int i=0; i < ghost_scouts.size(); ++i)
         {
             ghost_scouts.at(i)->paint(dc);
@@ -570,6 +660,9 @@ namespace scoutsim
         M_Scout::iterator it = scouts.begin();
         M_Scout::iterator end = scouts.end();
 
+        M_Emitter::iterator m_it = emitters.begin();
+        M_Emitter::iterator m_end = emitters.end();
+
         world_state state;
         state.canvas_width = width_in_meters;
         state.canvas_height = height_in_meters;
@@ -585,15 +678,28 @@ namespace scoutsim
                                state);
         }
 
+
+        for (; m_it != m_end; ++m_it)
+        {
+
+            m_it->second->update(SIM_TIME_REFRESH_RATE,
+                               path_dc,
+                               path_image, lines_image, walls_image,
+                               path_dc.GetBackground().GetColour(),
+                               state);
+        }
+
         for (unsigned int i = 0; i < ghost_scouts.size(); ++i)
         {
             ghost_scouts.at(i)->update(SIM_TIME_REFRESH_RATE, path_dc, sonar_dc,
                 path_dc.GetBackground().GetColour(), state);
         }
 
+
         frame_count++;
     }
 
+
     bool SimFrame::clearCallback(std_srvs::Empty::Request&,
                                  std_srvs::Empty::Response&)
     {
@@ -617,6 +723,13 @@ namespace scoutsim
     {
         wireless_receive.publish(msg);
     }
+
+
+    void SimFrame::readBOM()
+    {
+
+    }
+
 }
 
 /** @} */
diff --git a/scout/scoutsim/src/sim_frame.h b/scout/scoutsim/src/sim_frame.h
index cf9d56c..4d74239 100644
--- a/scout/scoutsim/src/sim_frame.h
+++ b/scout/scoutsim/src/sim_frame.h
@@ -65,6 +65,7 @@
 #include <map>
 
 #include "scout.h"
+#include "emitter.h"
 #include "ghost_scout.h"
 #include "scoutsim_internal.h"
 #include "messages/WirelessPacket.h"
@@ -102,6 +103,8 @@ namespace scoutsim
 
             std::string spawnScout(const std::string& name,
                     float x, float y, float angle);
+            std::string spawnEmitter(const std::string& name,
+                    float x, float y, float angle);
 
             void onQuit(wxCommandEvent& event);
             void onAbout(wxCommandEvent& event);
@@ -117,6 +120,9 @@ namespace scoutsim
 
         private:
 
+            typedef std::map<std::string, ScoutPtr> M_Scout;
+            typedef std::map<std::string, EmitterPtr> M_Emitter;
+
             void onUpdate(wxTimerEvent& evt);
             void onPaint(wxPaintEvent& evt);
 
@@ -129,10 +135,12 @@ namespace scoutsim
             void updateScouts();
             void clear();
             bool hasScout(const std::string& name);
+            bool hasEmitter(const std::string& name);
 
             bool clearCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
             bool resetCallback(std_srvs::Empty::Request&, std_srvs::Empty::Response&);
             bool spawnCallback(Spawn::Request&, Spawn::Response&);
+            bool spawnEmCallback(Spawn::Request&, Spawn::Response&);
             bool killCallback(Kill::Request&, Kill::Response&);
 
             bool setSonarVizCallback(SetSonarViz::Request&, SetSonarViz::Response&);
@@ -140,10 +148,16 @@ namespace scoutsim
             bool setTeleopCallback(SetTeleop::Request&, SetTeleop::Response&);
 
             void wirelessCallback(const messages::WirelessPacket::ConstPtr& msg);
+            void readBOM(); 
+
 
             ros::Subscriber wireless_send;
             ros::Publisher wireless_receive;
 
+            //emitter
+            float em_aperture;
+            int em_distance;
+
             // Teleop
             short teleop_l_speed;
             short teleop_r_speed;
@@ -170,13 +184,14 @@ namespace scoutsim
             ros::ServiceServer clear_srv;
             ros::ServiceServer reset_srv;
             ros::ServiceServer spawn_srv;
+            ros::ServiceServer spawn_em_srv;
             ros::ServiceServer kill_srv;
             ros::ServiceServer set_sonar_viz_srv;
             ros::ServiceServer set_ghost_srv;
             ros::ServiceServer set_teleop_srv;
 
-            typedef std::map<std::string, ScoutPtr> M_Scout;
             M_Scout scouts;
+            M_Emitter emitters;
             std::vector<GhostScout*> ghost_scouts;
             uint32_t id_counter;
 
