diff --git a/source/RobotAPI/libraries/core/test/CMakeLists.txt b/source/RobotAPI/libraries/core/test/CMakeLists.txt
index 37fd064ee6553f8324c2fd2916c89dbb801f29e7..3f70ca0b8d1b201a90bc46e0d5bdf11d3241baf4 100644
--- a/source/RobotAPI/libraries/core/test/CMakeLists.txt
+++ b/source/RobotAPI/libraries/core/test/CMakeLists.txt
@@ -9,3 +9,5 @@ armarx_add_test(CartesianVelocityControllerTest CartesianVelocityControllerTest.
 
 armarx_add_test(CartesianVelocityRampTest CartesianVelocityRampTest.cpp "${LIBS}")
 armarx_add_test(CartesianVelocityControllerWithRampTest CartesianVelocityControllerWithRampTest.cpp "${LIBS}")
+
+armarx_add_test(DebugDrawerTopicTest    DebugDrawerTopicTest.cpp    "${LIBS}")
diff --git a/source/RobotAPI/libraries/core/test/DebugDrawerTopicTest.cpp b/source/RobotAPI/libraries/core/test/DebugDrawerTopicTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b6a2310df6ec38de4a5bb4f413636765212b5c0e
--- /dev/null
+++ b/source/RobotAPI/libraries/core/test/DebugDrawerTopicTest.cpp
@@ -0,0 +1,143 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    ArmarX
+ * @author     Mirko Waechter( mirko.waechter at kit dot edu)
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#define BOOST_TEST_MODULE RobotAPI::DebugDrawerTopicTest::Test
+
+#define ARMARX_BOOST_TEST
+
+#include <RobotAPI/Test.h>
+
+#include <ArmarXCore/core/test/IceTestHelper.h>
+
+#include <RobotAPI/libraries/core/visualization/DebugDrawerTopic.h>
+
+
+using namespace armarx;
+
+
+// PCL-like dummy types.
+
+struct PointXYZ
+{
+    float x, y, z;
+};
+
+struct PointXYZRGBA : public PointXYZ
+{
+    uint8_t r, g, b, a;
+};
+
+struct PointXYZRGBL : public PointXYZRGBA
+{
+    uint32_t label;
+};
+
+template <class PointT>
+struct PointCloud
+{
+private:
+    /// The point container type.
+    using VectorT = std::vector<PointT>;
+    
+public:
+    
+    PointCloud() {}
+    PointCloud(const VectorT& points) : points(points) {}
+    
+    // Container methods.
+    std::size_t size() const { return points.size(); }
+    
+    PointT& operator[](std::size_t i) { return points[i]; }
+    const PointT& operator[](std::size_t i) const { return points[i]; }
+    
+    // Iterators.
+    typename VectorT::iterator begin() { return points.begin(); }
+    typename VectorT::const_iterator begin() const { return points.begin(); }
+    typename VectorT::iterator end() { return points.end(); }
+    typename VectorT::const_iterator end() const { return points.end(); }
+    
+    
+    /// The points.
+    VectorT points;
+};
+
+
+/* These test do not actually check any behaviour, 
+ * but check whether this code compiles.
+ */
+
+template <class PointT>
+struct Fixture
+{
+    Fixture()
+    {
+    }
+    
+    const DebugDrawerTopic::VisuID id {"name", "layer"};
+    const int pointSize = 10;
+    
+    DebugDrawerTopic drawer;
+    
+    PointCloud<PointT> pointCloudMutable;
+    const PointCloud<PointT>& pointCloud = pointCloudMutable;
+};
+
+
+BOOST_FIXTURE_TEST_CASE(test_drawPointCloud_PointXYZ, Fixture<PointXYZ>)
+{
+    pointCloudMutable.points = { {1, 2, 3}, {2, 3, 4}, {3, 4, 5} };
+    
+    drawer.drawPointCloud(id, pointCloud);
+    drawer.drawPointCloud(id, pointCloud.points, DrawColor {0, 0.5, 1, 1});
+    
+    drawer.drawPointCloud(id, pointCloud, 
+                          [](const PointXYZ&) { return DrawColor{0, 0.5, 1, 1}; }, pointSize);
+}
+
+
+BOOST_FIXTURE_TEST_CASE(test_drawPointCloud_PointXYZRGBA, Fixture<PointXYZRGBA>)
+{
+    drawer.drawPointCloud(id, pointCloud);
+    drawer.drawPointCloud(id, pointCloud.points, DrawColor {0, 0.5, 1, 1});
+    
+    drawer.drawPointCloud(id, pointCloud, 
+                          [](const PointXYZRGBA&) { return DrawColor{0, 0.5, 1, 1}; }, pointSize);
+    
+    drawer.drawPointCloudRGBA(id, pointCloud, pointSize);
+}
+
+
+BOOST_FIXTURE_TEST_CASE(test_drawPointCloud_PointXYZRGBL, Fixture<PointXYZRGBL>)
+{
+    drawer.drawPointCloud(id, pointCloud);
+    drawer.drawPointCloud(id, pointCloud.points, DrawColor {0, 0.5, 1, 1});
+    
+    drawer.drawPointCloud(id, pointCloud,
+                          [](const PointXYZRGBL&) { return DrawColor{0, 0.5, 1, 1}; }, pointSize);
+    
+    drawer.drawPointCloudRGBA(id, pointCloud, pointSize);
+}
+
+
+
diff --git a/source/RobotAPI/libraries/core/visualization/DebugDrawerTopic.cpp b/source/RobotAPI/libraries/core/visualization/DebugDrawerTopic.cpp
index 70d18d468b472fffca2b7a0d0a6538c4afe2b0ab..ff170b8d9087bf73d5f86968a80e9bd2c815f1c1 100644
--- a/source/RobotAPI/libraries/core/visualization/DebugDrawerTopic.cpp
+++ b/source/RobotAPI/libraries/core/visualization/DebugDrawerTopic.cpp
@@ -533,6 +533,42 @@ namespace armarx
                                   faceColorsInner.at(i), colorEdge, lineWidth);
         }
     }
+    
+    void DebugDrawerTopic::drawPointCloud(
+            const DebugDrawerTopic::VisuID& id,
+            const DebugDrawerPointCloud& pointCloud)
+    {
+        if (enabled())
+        {
+            topic->setPointCloudVisu(id.layer, id.name, pointCloud);
+        }
+    }
+    
+    void DebugDrawerTopic::drawPointCloud(
+            const DebugDrawerTopic::VisuID& id, 
+            const DebugDrawerColoredPointCloud& pointCloud)
+    {
+        if (enabled())
+        {
+            topic->setColoredPointCloudVisu(id.layer, id.name, pointCloud);
+        }
+    }
+    
+    void DebugDrawerTopic::drawPointCloud(
+            const DebugDrawerTopic::VisuID& id, 
+            const DebugDrawer24BitColoredPointCloud& pointCloud)
+    {
+        if (enabled())
+        {
+            topic->set24BitColoredPointCloudVisu(id.layer, id.name, pointCloud);
+        }
+    }
+    
+    void DebugDrawerTopic::clearColoredPointCloud(const DebugDrawerTopic::VisuID& id)
+    {
+        // Draw an empty point cloud.
+        drawPointCloud(id, DebugDrawerColoredPointCloud{});
+    }
 
     void DebugDrawerTopic::drawFloor(
         const VisuID& id,
diff --git a/source/RobotAPI/libraries/core/visualization/DebugDrawerTopic.h b/source/RobotAPI/libraries/core/visualization/DebugDrawerTopic.h
index d7a1a9045986d476b1e895cb6e76cf9f51c62b82..e775735e2031e48acd1b4d704e3ce4ae4b676fae 100644
--- a/source/RobotAPI/libraries/core/visualization/DebugDrawerTopic.h
+++ b/source/RobotAPI/libraries/core/visualization/DebugDrawerTopic.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <chrono>
+#include <functional>
 #include <thread>
 
 #include <Eigen/Geometry>
@@ -35,6 +36,7 @@ namespace armarx
      * is enabled (i.e. a topic proxy is set), use `enabled()` or just convert
      * `*this` to bool:
      * @code
+     * DebugDrawerTopic debugDrawer;
      * if (debugDrawer)  // equivalent: if (debugDrawer.enabled())
      * {
      *     // do stuff if visualization is enabled
@@ -42,11 +44,36 @@ namespace armarx
      * @endcode
      *
      * The `DebugDrawerTopic` allows to set a layer on constructor or via
-     * `setLayer()`. This layer will be used if none is passed to a drawing method.
+     * `setLayer()`. This layer will be used if none is passed to a drawing
+     * method. If no layer is passed or set, `DebugDrawerTopic::DEFAULT_LAYER`
+     * is used.
+     *
+     *
+     * @par Initialisation by Offering and Getting Topic
+     *
+     * A `DebugDrawerTopic` needs an underlying `DebugDrawerInterfacePrx` topic proxy.
+     * This proxy can be passed on construction or set via `setTopic()`.
+     * In a component (or any other `ManagedIceObject`), `DebugDrawerTopic`
+     * provides convenience functions to register and fetch the topics.
+     *
+     * In `onInitComponent()` (or equivalent method), call:
+     * @code
+     * debugDrawer.offeringTopic(*this);
+     * @endcode
+     * In `onConnectComponent()` (or equivalent), call:
+     * @code
+     * debugDrawer.getTopic(*this);
+     * @endcode
+     * where `*this` is a `ManagedIceObject`.
+     *
+     * This will call `this->offeringTopic("...")` and `this->getTopic("...")`
+     * with the correct topic name (`DebugDrawerTopic::TOPIC_NAME`) and
+     * enable the `DebugDrawerTopic`.
+     *
      *
      * @par Scaling
      *
-     * `DebugDrawerTopic` support length scaling and pose scaling.
+     * `DebugDrawerTopic` supports length scaling and pose scaling.
      *
      * If a length scale is set, all visualizations will be scaled up or down
      * by this value. This scaling affects positions, sizes / extents, and
@@ -87,7 +114,7 @@ namespace armarx
      * @endcode
      *
      * This will draw a pose on the preset layer (i.e. the layer passed to the
-     * constructor or set via `setLayer()`).
+     * constructor or set via `setLayer()`, or "debug" by default).
      * To specify both name and layer of a single visualization, pass both in
      * an initializer list:
      *
@@ -100,7 +127,7 @@ namespace armarx
      *
      *
      * After the VisuID, usually the essential geometric parameters follow,
-     * (e.g. position, size, lenght, point list, ...), depending on the type
+     * (e.g. position, size, length, point list, ...), depending on the type
      * of visualization.
      * Finally, decorative parameters like colors and width can be passed.
      * Most of the time, they have sensible default values and can be omitted
@@ -108,7 +135,7 @@ namespace armarx
      *
      * (Added methods should adhere to this pattern.)
      *
-     * @see DebugDrawerTopic::VisuID
+     * @see `DebugDrawerTopic::VisuID`
      */
     class DebugDrawerTopic
     {
@@ -118,7 +145,7 @@ namespace armarx
         {
             /// Empty constructor.
             VisuID();
-            
+
             /**
              * @brief Construct a VisuID.
              *
@@ -166,12 +193,19 @@ namespace armarx
             DrawColor colorPolygonEdge { .75, .75, .75, 1 };
 
             DrawColor colorFloor { .1f, .1f, .1f, 1 };
+
+            DrawColor colorPointCloud { .5, .5, .5, 1. };
+
+            // Default value of DebugDrawerColoredPointCloud etc.
+            float pointCloudPointSize = 3.0f;
         };
         static const Defaults DEFAULTS;
 
 
     public:
 
+        // CONSTRUCTION & SETUP
+
         /// Construct without topic, and optional layer.
         DebugDrawerTopic(const std::string& layer = DEFAULT_LAYER);
         /// Construct with given topic and optional layer.
@@ -188,9 +222,9 @@ namespace armarx
         /// Get the topic by calling getTopic([topicName]) on the given component.
         void getTopic(ManagedIceObject& component);
 
-        /// Get the default layer (used if no layer is passed to the method).
+        /// Get the default layer (used if no layer is passed to a method).
         const std::string& getLayer() const;
-        /// Set the default layer (used if no layer is passed to the method).
+        /// Set the default layer (used if no layer is passed to a method).
         void setLayer(const std::string& layer);
 
         /// Get the scaling for positions, lengths and distances.
@@ -250,6 +284,7 @@ namespace armarx
                       int size = 10, const DrawColor color = DEFAULTS.colorText,
                       bool ignoreLengthScale = false);
 
+
         /// Draw a box.
         void drawBox(const VisuID& id, const Eigen::Vector3f& position, const Eigen::Quaternionf& orientation,
                      const Eigen::Vector3f& extents, const DrawColor& color = DEFAULTS.colorBox,
@@ -271,6 +306,7 @@ namespace armarx
                      const DrawColor& color = DEFAULTS.colorBox,
                      bool ignoreLengthScale = false);
 
+
         /**
          * @brief Draw a cylinder with center and direction.
          * @param length the full length (not half-length)
@@ -430,6 +466,71 @@ namespace armarx
             bool ignoreLengthScale = false);
 
 
+        // POINT CLOUD
+        /* (By templating these functions, we can make them usable for PCL
+         * point clouds without a dependency on PCL.)
+         */
+
+        /**
+         * @brief Draw a unicolored point cloud.
+         *
+         * `pointCloud` must be iterable and its elements must provide members `x, y, z`.
+         */
+        template <class PointCloudT>
+        void drawPointCloud(
+            const VisuID& id,
+            const PointCloudT& pointCloud,
+            const DrawColor& color = DEFAULTS.colorPointCloud,
+            float pointSize = DEFAULTS.pointCloudPointSize,
+            bool ignoreLengthScale = false);
+
+        /**
+         * @brief Draw a colored point cloud with RGBA information.
+         *
+         * `pointCloud` must be iterable and its elements must provide
+         * members `x, y, z, r, g, b, a`.
+         */
+        template <class PointCloudT>
+        void drawPointCloudRGBA(
+            const VisuID& id,
+            const PointCloudT& pointCloud,
+            float pointSize = DEFAULTS.pointCloudPointSize,
+            bool ignoreLengthScale = false);
+
+        /**
+         * @brief Draw a colored point cloud with custom colors.
+         *
+         * `pointCloud` must be iterable and its elements must provide
+         * members `x, y, z`.
+         * The color of a point is specified by `colorFunc`, which must be
+         * a callable taking an element of `pointCloud` and returning its
+         * color as `armarx::DrawColor`.
+         */
+        template <class PointCloudT, class ColorFuncT>
+        void drawPointCloud(
+            const VisuID& id,
+            const PointCloudT& pointCloud,
+            const ColorFuncT& colorFunc,
+            float pointSize = DEFAULTS.pointCloudPointSize,
+            bool ignoreLengthScale = false);
+
+
+        // Debug Drawer Point Cloud Types
+
+        /// Draw a non-colored point cloud.
+        void drawPointCloud(const VisuID& id, const DebugDrawerPointCloud& pointCloud);
+
+        /// Draw a colored point cloud.
+        void drawPointCloud(const VisuID& id, const DebugDrawerColoredPointCloud& pointCloud);
+
+        /// Draw a 24 bit colored point cloud.
+        void drawPointCloud(const VisuID& id, const DebugDrawer24BitColoredPointCloud& pointCloud);
+
+
+        /// Forces the "deletion" of a point cloud by drawing an empty one.
+        void clearColoredPointCloud(const VisuID& id);
+
+
         // CUSTOM
 
         /**
@@ -446,10 +547,15 @@ namespace armarx
             bool ignoreLengthScale = false);
 
 
+        // STATUS
+        
         /// Indicate whether a topic is set, i.e. visualization is enabled.
         bool enabled() const;
         /// Indicate whether a topic is set, i.e. visualization is enabled.
         operator bool() const;
+        
+        
+        // OPERATORS
 
         /// Conversion operator to DebugDrawerInterfacePrx.
         operator DebugDrawerInterfacePrx& ();
@@ -460,7 +566,7 @@ namespace armarx
         const DebugDrawerInterfacePrx& operator->() const;
 
 
-        // STATIC
+    public:  // STATIC
 
         /**
          * @brief Convert a RGB color to HSV.
@@ -480,9 +586,10 @@ namespace armarx
         /**
          * @brief Construct a DrawColor from the given color type.
          *
-         * The used color type must have members named "r", "g" and "b".
+         * The used color type must have members named `r`, `g` and `b`.
          * Applicable types include:
          *  - pcl::RGB (byteToFloat = true)
+         *  - armarx::DrawColor (useful to get a color with a different alpha)
          *
          * @param alpha the alpha (default: 1)
          * @param byteToFloat If true, scale from range [0, 255] to [0, 1]
@@ -524,7 +631,7 @@ namespace armarx
         DebugDrawerInterfacePrx topic = nullptr;
 
         /// The default layer (used if none is passed to the method).
-        std::string _layer = "debug";
+        std::string _layer = DEFAULT_LAYER;
 
         /// Scaling for positions, lengths and distances.
         float _lengthScale = 1;
@@ -541,7 +648,7 @@ namespace armarx
     template <typename DurationT>
     void DebugDrawerTopic::sleepFor(const DurationT& duration)
     {
-        if (topic)
+        if (enabled())
         {
             std::this_thread::sleep_for(duration);
         }
@@ -556,8 +663,71 @@ namespace armarx
     template <class ColorT>
     DrawColor DebugDrawerTopic::toDrawColor(const ColorT& color, float alpha, bool byteToFloat)
     {
-        float scale = byteToFloat ? (1 / 255.f) : 1;
+        const float scale = byteToFloat ? (1 / 255.f) : 1;
         return { color.r * scale, color.g * scale, color.b * scale, alpha };
     }
 
+
+    template <class PointCloudT>
+    void DebugDrawerTopic::drawPointCloud(
+        const VisuID& id,
+        const PointCloudT& pointCloud,
+        const DrawColor& color,
+        float pointSize,
+        bool ignoreLengthScale)
+    {
+        drawPointCloud(id, pointCloud,
+                       [&color](const auto&)
+        {
+            return color;
+        },
+        pointSize, ignoreLengthScale);
+    }
+
+    template<class PointCloudT>
+    void DebugDrawerTopic::drawPointCloudRGBA(
+        const VisuID& id,
+        const PointCloudT& pointCloud,
+        float pointSize,
+        bool ignoreLengthScale)
+    {
+        drawPointCloud(id, pointCloud,
+                       [](const auto & p)
+        {
+            return toDrawColor(p, p.a);
+        },
+        pointSize, ignoreLengthScale);
+    }
+
+    template <class PointCloudT, class ColorFuncT>
+    void DebugDrawerTopic::drawPointCloud(
+        const VisuID& id,
+        const PointCloudT& pointCloud,
+        const ColorFuncT& colorFn,
+        float pointSize,
+        bool ignoreLengthScale)
+    {
+        if (!enabled())
+        {
+            return;
+        }
+
+        const float lf = ignoreLengthScale ? 1.0 : _lengthScale;
+
+        DebugDrawerColoredPointCloud dd;
+        dd.points.reserve(pointCloud.size());
+
+        dd.pointSize = pointSize;
+
+        for (const auto& p : pointCloud)
+        {
+            dd.points.push_back(DebugDrawerColoredPointCloudElement
+            {
+                lf * p.x, lf * p.y, lf * p.z, colorFn(p)
+            });
+        }
+
+        drawPointCloud(id, dd);
+    }
+
 }