diff --git a/source/ArmarXGui/applications/ArmarXGui/ArmarXGuiApp.h b/source/ArmarXGui/applications/ArmarXGui/ArmarXGuiApp.h
index 99998cb83406455e91d4060e5b393ce40f11afce..59014ea8ce3897f374ed9a5d34117e6580ac51f9 100644
--- a/source/ArmarXGui/applications/ArmarXGui/ArmarXGuiApp.h
+++ b/source/ArmarXGui/applications/ArmarXGui/ArmarXGuiApp.h
@@ -23,22 +23,16 @@
 
 #pragma once
 
-// ArmarX
-
-#include <ArmarXCore/core/system/ImportExportComponent.h>
-#include <ArmarXGui/applications/ArmarXGui/Widgets/ui_ExceptionDialog.h>
-
-//SoQt
-#include <Inventor/Qt/SoQt.h>
+#include <string>
 
-//Qt
 #include <QApplication>
 
-#include "ArmarXMainWindow.h"
-
-#include <string>
+#include <ArmarXCore/core/system/ImportExportComponent.h>
 
+#include <ArmarXGui/applications/ArmarXGui/ArmarXMainWindow.h>
+#include <ArmarXGui/applications/ArmarXGui/Widgets/ui_ExceptionDialog.h>
 
+#include <Inventor/Qt/SoQt.h>
 
 namespace armarx
 {
@@ -48,16 +42,13 @@ namespace armarx
     /**
      * ArmarXGuiApp property definition container.
      */
-    class ArmarXGuiAppPropertyDefinitions:
-        public ApplicationPropertyDefinitions
+    class ArmarXGuiAppPropertyDefinitions : public ApplicationPropertyDefinitions
     {
     public:
         ArmarXGuiAppPropertyDefinitions(std::string prefix);
     };
 
-
-    class ArmarXQApplication :
-        public  QApplication
+    class ArmarXQApplication : public QApplication
     {
         Q_OBJECT
     public:
@@ -70,12 +61,12 @@ namespace armarx
 
     public slots:
         void showException(QString exceptionReason);
+
     protected:
         QDialog exceptionDialog;
         Ui_ExceptionDialog exceptionDialogHandler;
     };
 
-
     /**
       \class ArmarXGuiApp
       \brief The main ArmarX gui application.
@@ -103,7 +94,8 @@ namespace armarx
         /**
         * Configures the app, sets Qt up
         */
-        void setup(const ManagedIceObjectRegistryInterfacePtr& registry, Ice::PropertiesPtr properties) override;
+        void setup(const ManagedIceObjectRegistryInterfacePtr& registry,
+                   Ice::PropertiesPtr properties) override;
 
         int run(int argc, char* argv[]) override;
         /**
@@ -114,9 +106,11 @@ namespace armarx
         /**
          * @see PropertyUser::createPropertyDefinitions()
          */
-        armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
+        armarx::PropertyDefinitionsPtr
+        createPropertyDefinitions() override
         {
-            return armarx::PropertyDefinitionsPtr(new ArmarXGuiAppPropertyDefinitions(getDomainName()));
+            return armarx::PropertyDefinitionsPtr(
+                new ArmarXGuiAppPropertyDefinitions(getDomainName()));
         }
 
     private slots:
@@ -136,5 +130,4 @@ namespace armarx
         int argc;
         char** argv;
     };
-}
-
+} // namespace armarx
diff --git a/source/ArmarXGui/applications/ArmarXGui/ArmarXMainWindow.cpp b/source/ArmarXGui/applications/ArmarXGui/ArmarXMainWindow.cpp
index 299e2841bd8c8ff1104c8580ae75e6e80ff959b8..15efec06d8841eba075db4c008c5fc597a04ced9 100644
--- a/source/ArmarXGui/applications/ArmarXGui/ArmarXMainWindow.cpp
+++ b/source/ArmarXGui/applications/ArmarXGui/ArmarXMainWindow.cpp
@@ -21,24 +21,9 @@
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
  */
-#include "ArmarXMainWindow.h"
-
-#include <ArmarXGui/applications/ArmarXGui/ui_ArmarXMainWindow.h>
-
-#include "Widgets/TitlebarWidget.h"
-#include "Widgets/ViewerWidget.h"
-#include "Widgets/WidgetNameDialog.h"
 
-// ArmarX
-#include <ArmarXCore/core/ArmarXObjectScheduler.h>
-#include <ArmarXCore/core/Component.h>
-#include <ArmarXCore/core/logging/LogSender.h>
-#include <ArmarXCore/core/system/ArmarXDataPath.h>
-#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
-
-#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXComponentWidgetController.h>
+#include "ArmarXMainWindow.h"
 
-// Qt
 #include <filesystem>
 #include <optional>
 #include <sstream>
@@ -89,11 +74,22 @@
 
 #include <SimoxUtility/algorithm/string/string_tools.h>
 
+#include <ArmarXCore/core/ArmarXObjectScheduler.h>
+#include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/core/logging/LogSender.h>
+#include <ArmarXCore/core/system/ArmarXDataPath.h>
+#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
+
 #include <ArmarXGui/applications/ArmarXGui/Widgets/GuiUseCaseSelector.h>
+#include <ArmarXGui/applications/ArmarXGui/ui_ArmarXMainWindow.h>
+#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXComponentWidgetController.h>
 #include <ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixCompleter.h>
 #include <ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.h>
 #include <ArmarXGui/libraries/ArmarXGuiBase/widgets/TipDialog.h>
 
+#include "Widgets/TitlebarWidget.h"
+#include "Widgets/ViewerWidget.h"
+#include "Widgets/WidgetNameDialog.h"
 #include <Inventor/Qt/viewers/SoQtExaminerViewer.h>
 #include <Inventor/nodes/SoPerspectiveCamera.h>
 //#include <omp.h>
@@ -191,6 +187,11 @@ namespace armarx
             ArmarXComponentWidgetController::createInstance<EmergencyStopWidget>());
         this->registry->addObject(ManagedIceObjectPtr::dynamicCast(emergencyStopWidget));
 
+        // Battery widget
+        batteryWidget = BatteryWidgetPtr::dynamicCast(
+            ArmarXComponentWidgetController::createInstance<BatteryWidget>());
+        this->registry->addObject(ManagedIceObjectPtr::dynamicCast(batteryWidget));
+
         // plugins
         QSet<QString> pluginDirs;
 
@@ -1250,6 +1251,11 @@ namespace armarx
         // EmergencyStop
         ui->toolBar->addWidget(emergencyStopWidget->getButtonWidget());
 
+        // Battery Widget
+        ui->toolBar->addWidget(batteryWidget->getBatteryWidget());
+
+        ui->toolBar->addSeparator();
+
         ui->toolBar->setIconSize(QSize(256, 24));
 
         QMap<QString, QAction*> actionsForToolBar;
diff --git a/source/ArmarXGui/applications/ArmarXGui/ArmarXMainWindow.h b/source/ArmarXGui/applications/ArmarXGui/ArmarXMainWindow.h
index d274cba2c857ead6947f8d977c4c92e87b62e2f1..b3152ba29fdf939c713bc5e2caff351d683c2255 100644
--- a/source/ArmarXGui/applications/ArmarXGui/ArmarXMainWindow.h
+++ b/source/ArmarXGui/applications/ArmarXGui/ArmarXMainWindow.h
@@ -23,29 +23,25 @@
  */
 #pragma once
 
-#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXGuiPlugin.h>
-#include <ArmarXGui/libraries/ArmarXGuiBase/PluginCache.h>
-
-// Qt
 #include <QAction>
 #include <QDir>
 #include <QDockWidget>
 #include <QMainWindow>
 #include <QPluginLoader>
-
-// Coin3D & SoQt
-#include <Inventor/nodes/SoNode.h>
-#include <Inventor/nodes/SoSeparator.h>
-
-// ArmarX
 #include <QSplashScreen>
 
 #include <ArmarXCore/core/application/Application.h>
 #include <ArmarXCore/core/logging/Logging.h>
 #include <ArmarXCore/core/services/tasks/RunningTask.h>
 
-#include "Widgets/EmergencyStopWidget.h"
-#include "Widgets/ViewerWidget.h"
+#include <ArmarXGui/applications/ArmarXGui/Widgets/BatteryWidget.h>
+#include <ArmarXGui/applications/ArmarXGui/Widgets/EmergencyStopWidget.h>
+#include <ArmarXGui/applications/ArmarXGui/Widgets/ViewerWidget.h>
+#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXGuiPlugin.h>
+#include <ArmarXGui/libraries/ArmarXGuiBase/PluginCache.h>
+
+#include <Inventor/nodes/SoNode.h>
+#include <Inventor/nodes/SoSeparator.h>
 
 class QToolButton;
 class QLabel;
@@ -246,6 +242,7 @@ namespace armarx
 
         // Emergency Stop
         EmergencyStopWidgetPtr emergencyStopWidget;
+        BatteryWidgetPtr batteryWidget;
 
         QAction* leaveFullScreenActionF11;
         QAction* leaveFullScreenActionEsc;
diff --git a/source/ArmarXGui/applications/ArmarXGui/CMakeLists.txt b/source/ArmarXGui/applications/ArmarXGui/CMakeLists.txt
index a060898531cd9d9de8c35d087a99bfa395f0ba96..48a5431048eb7c0dcbb33af3d3f74f5809a55683 100644
--- a/source/ArmarXGui/applications/ArmarXGui/CMakeLists.txt
+++ b/source/ArmarXGui/applications/ArmarXGui/CMakeLists.txt
@@ -21,6 +21,7 @@ set(SOURCES ArmarXGuiApp.cpp
             Widgets/UseCaseSelectorItem.cpp
             Widgets/GuiUseCaseSelector.cpp
             Widgets/EmergencyStopWidget.cpp
+            Widgets/BatteryWidget.cpp
             )
 
 set(HEADERS ArmarXGuiApp.h
@@ -31,6 +32,7 @@ set(HEADERS ArmarXGuiApp.h
             Widgets/UseCaseSelectorItem.h
             Widgets/GuiUseCaseSelector.h
             Widgets/EmergencyStopWidget.h
+            Widgets/BatteryWidget.h
 
     ArmarXMainWindow.ui
     Widgets/ViewerWidget.ui
diff --git a/source/ArmarXGui/applications/ArmarXGui/Widgets/BatteryWidget.cpp b/source/ArmarXGui/applications/ArmarXGui/Widgets/BatteryWidget.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad94bcbb62724831ef69a5461a398544283480ab
--- /dev/null
+++ b/source/ArmarXGui/applications/ArmarXGui/Widgets/BatteryWidget.cpp
@@ -0,0 +1,364 @@
+#include "BatteryWidget.h"
+
+#include <QToolTip>
+
+namespace armarx
+{
+
+    constexpr std::string_view battery_master_default_name = "DiagnosticsUnit";
+
+    BatteryIcon::BatteryIcon(QWidget* parent) : QWidget(parent)
+    {
+        QSizePolicy policy{QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed};
+        setSizePolicy(policy);
+    }
+
+    void
+    BatteryIcon::paintEvent(QPaintEvent* event)
+    {
+        QWidget::paintEvent(event);
+
+        int filled = std::clamp(percentage, 0, 100); // between 0 and 100
+        QColor fg(0, 200, 0);
+
+        if (filled < 15)
+        {
+            fg = QColor(200, 0, 0);
+        }
+        else if (filled < 45)
+        {
+            fg = QColor(200, 100, 0);
+        }
+
+        if (state != dto::BatteryState::discharging)
+        {
+            fg = QColor(255, 255, 255);
+        }
+
+        // Draw inner and cap.
+        QColor bg(fg.red() * .6, fg.green() * .6, fg.blue() * .6);
+        int ht = event->rect().height();
+        int wd = ht / 2 - 1;
+        QPainter painter;
+        painter.setRenderHint(QPainter::Antialiasing, true);
+        painter.begin(this);
+        int m = 1 * ht / 10 + 1;
+        QRect cap(QPoint(m, m), QPoint(wd - m, 2 * m));
+        painter.fillRect(cap, filled == 100 ? fg : bg);
+        QRect body(QPoint(0, 2 * m), QPoint(wd, ht - m));
+        painter.fillRect(body, bg);
+        float dist = (1.0 - filled * .01);
+        QRect bodyFull(QPoint(0, 2 * m + dist * (ht - 3 * m)), QPoint(wd, ht - m));
+        painter.fillRect(bodyFull, fg);
+
+        // Draw a border.
+        int lWd = ht / 40;
+        QRect a;
+        a = QRect(QPoint(m, m), QPoint(wd - m, m + lWd));
+        painter.fillRect(a, bg);
+        a = QRect(QPoint(wd - m - lWd, m), QPoint(wd - m, 2 * m + lWd));
+        painter.fillRect(a, bg);
+        a = QRect(QPoint(wd - m - lWd, 2 * m), QPoint(wd, 2 * m + lWd));
+        painter.fillRect(a, bg);
+        a = QRect(QPoint(wd - lWd, 2 * m), QPoint(wd, ht - m));
+        painter.fillRect(a, bg);
+        a = QRect(QPoint(0, ht - m - lWd), QPoint(wd, ht - m));
+        painter.fillRect(a, bg);
+        a = QRect(QPoint(0, 2 * m), QPoint(lWd, ht - m));
+        painter.fillRect(a, bg);
+        a = QRect(QPoint(0, 2 * m), QPoint(m + lWd, 2 * m + lWd));
+        painter.fillRect(a, bg);
+        a = QRect(QPoint(m, m), QPoint(m + lWd, 2 * m + lWd));
+        painter.fillRect(a, bg);
+
+        // Draw lightning if charging.
+        if (state == dto::BatteryState::charging)
+        {
+            QPolygon poly;
+            float lHeight = .6 * ht;
+            int xOff = .1 * ht + 1;
+            int yOff = .2 * ht + 1;
+            poly << QPoint(xOff + 7 * lHeight / 20, yOff)
+                 << QPoint(xOff + 5 * lHeight / 20, yOff + 4.5 * lHeight / 10)
+                 << QPoint(xOff + 10 * lHeight / 20, yOff + 4.5 * lHeight / 10)
+                 << QPoint(xOff + 3 * lHeight / 20, yOff + lHeight)
+                 << QPoint(xOff + 5 * lHeight / 20, yOff + 5.5 * lHeight / 10)
+                 << QPoint(xOff + 0 * lHeight / 20, yOff + 5.5 * lHeight / 10)
+                 << QPoint(xOff + 7 * lHeight / 20, yOff);
+            QPainterPath path;
+            path.addPolygon(poly);
+            painter.fillPath(path, QColor(40, 40, 40));
+        }
+
+        // Draw cross if unavailable.
+        if (state == dto::BatteryState::unavailable)
+        {
+            int u = .1 * wd;
+            QPolygon poly;
+            poly << QPoint(u, .1 * ht) << QPoint(wd - 2 * u, .9 * ht) << QPoint(wd - u, .9 * ht)
+                 << QPoint(2 * u, .1 * ht) << QPoint(u, .1 * ht);
+            QPainterPath path;
+            path.addPolygon(poly);
+            painter.fillPath(path, QColor(200, 0, 0));
+            QPolygon poly2;
+            poly2 << QPoint(wd - 2 * u, .1 * ht) << QPoint(wd - u, .1 * ht)
+                  << QPoint(2 * u, .9 * ht) << QPoint(u, .9 * ht) << QPoint(wd - 2 * u, .1 * ht);
+            QPainterPath path2;
+            path2.addPolygon(poly2);
+            painter.fillPath(path2, QColor(200, 0, 0));
+        }
+
+        painter.end();
+    }
+
+    void
+    BatteryIcon::setPercentage(int percentage)
+    {
+        this->percentage = std::clamp(percentage, 0, 100);
+    }
+
+    void
+    BatteryIcon::setState(dto::BatteryState state)
+    {
+        this->state = state;
+    }
+
+    QSize
+    BatteryIcon::sizeHint() const
+    {
+        return QSize{16, 32};
+    }
+
+    BatteryWidget::BatteryWidget(QWidget* parent, ArmarXMainWindow* mainWindow) :
+        mainWindow(mainWindow), timer(new QTimer(this))
+    {
+        qRegisterMetaType<dto::BatteryStatus>("dto::BatteryStatus");
+        QGridLayout* layout = new QGridLayout(this->getWidget());
+        this->getWidget()->setContentsMargins(4, 0, 0, 0);
+        icon = new BatteryIcon();
+        layout->addWidget(icon, 0, 0);
+        layout->setContentsMargins(0, 0, 0, 0);
+        this->getWidget()->setLayout(layout);
+        icon->setVisible(true);
+        lbl = new QLabel();
+        txtPercentage = QString("%1%").arg(lastStatus.energyFromFullCharge_pct);
+        lbl->setText(txtPercentage);
+        lbl->setVisible(false);
+        layout->addWidget(lbl, 0, 1);
+
+        qRegisterMetaType<dto::BatteryState>("BatteryState");
+
+        timer->setInterval(std::chrono::milliseconds(1'000));
+        connect(timer, &QTimer::timeout, this, &BatteryWidget::updateBatteryStatus);
+        connect(this, &BatteryWidget::startPeriodicStateUpdate, timer, qOverload<>(&QTimer::start));
+        connect(this, &BatteryWidget::stopPeriodicStateUpdate, timer, &QTimer::stop);
+
+        QString style = QString("QToolTip {"
+                                // StyleSheet for tool tip
+                                "    background: white;"
+                                "    padding: 3px;"
+                                "}");
+        getWidget()->setStyleSheet(style);
+
+        updateTooltip();
+    }
+
+    QWidget*
+    BatteryWidget::getBatteryWidget()
+    {
+        return this->getWidget();
+    }
+
+    void
+    BatteryWidget::updateTooltip()
+    {
+        dto::BatteryState state = lastStatus.state;
+
+        QString text;
+
+        if (state == dto::BatteryState::unavailable)
+        {
+            text = "No battery detected.";
+        }
+        else if (state == dto::BatteryState::full)
+        {
+            text = "Battery fully charged.";
+        }
+        else
+        {
+            QString status;
+            switch (state)
+            {
+                case dto::BatteryState::charging:
+                    status = "charging";
+                    break;
+                case dto::BatteryState::discharging:
+                    status = "discharging";
+                    break;
+                case dto::BatteryState::full:
+                    status = "full";
+                    break;
+                case dto::BatteryState::notCharging:
+                    status = "not charging";
+                    break;
+                case dto::BatteryState::unavailable:
+                    status = "unavailable";
+                    break;
+            }
+
+            QString detailedReport;
+            {
+                QString charge = QString("&nbsp;- Charge: %1<br>").arg(txtPercentage);
+
+                QString energy = QString("&nbsp;- Energy: %2 Wh / %3 Wh<br>")
+                                     .arg(lastStatus.energy_Wh, 0, 'f', 1)
+                                     .arg(lastStatus.fullChargeEnergy_Wh, 0, 'f', 1);
+
+                QString power = QString("&nbsp;- %1: %2 W (%3 A, %4 V)<br>")
+                                    .arg(state == dto::BatteryState::charging ? "Charging power"
+                                                                              : "Provided power")
+                                    .arg(std::abs(lastStatus.power_W), 0, 'f', 1)
+                                    .arg(std::abs(lastStatus.current_A), 0, 'f', 1)
+                                    .arg(lastStatus.voltage_V, 0, 'f', 1);
+
+                bool showPrognosis =
+                    state == dto::BatteryState::charging or state == dto::BatteryState::discharging;
+                QString prognosis = "";
+                if (showPrognosis)
+                {
+                    QString fullOrEmpty = state == dto::BatteryState::charging ? "Full" : "Empty";
+                    prognosis = QString("&nbsp;- %1 in: &asymp; %2 h <br>")
+                                    .arg(fullOrEmpty)
+                                    .arg(lastStatus.remainingTime_h, 0, 'f', 1);
+                }
+
+                QString temperature = QString("&nbsp;- Temperature: %6 °C<br>")
+                                          .arg(lastStatus.temperature_degC, 0, 'f', 1);
+
+                QString health = QString("&nbsp;- Health: %7%")
+                                     .arg(lastStatus.fullEnergyFromDesignEnergy_pct, 0, 'f', 1);
+
+                detailedReport = QString("%1%2%3%4%5%6")
+                                     .arg(charge, energy, power, prognosis, temperature, health);
+            }
+
+            QString errorsText =
+                lastStatus.hasError
+                    ? "<br><b><font color='red'>Battery error occured! Check the logs.</font></b>"
+                    : "";
+
+            text = QString("Battery %1.<br>%2%3").arg(status).arg(detailedReport).arg(errorsText);
+        }
+
+        getWidget()->setToolTip(text);
+
+        if (not QToolTip::isVisible())
+        {
+            return;
+        }
+
+        QPoint p = getWidget()->mapFromGlobal(QCursor::pos());
+
+        if (p.x() >= 0 and p.y() >= 0 and p.x() < getWidget()->width() and
+            p.y() < getWidget()->height())
+        {
+            QToolTip::showText(QCursor::pos(), text);
+        }
+    }
+
+    void
+    BatteryWidget::onInitComponent()
+    {
+        usingProxy(std::string{battery_master_default_name});
+    }
+
+    void
+    BatteryWidget::onConnectComponent()
+    {
+        QMetaObject::invokeMethod(icon, "setVisible", Qt::QueuedConnection, Q_ARG(bool, true));
+
+        ARMARX_INFO << "Battery widget connected.";
+        batteryManagement = getProxy<armarx::BatteryManagementInterfacePrx>(
+            std::string{battery_master_default_name});
+
+        emit startPeriodicStateUpdate();
+    }
+
+    void
+    BatteryWidget::onDisconnectComponent()
+    {
+        ARMARX_IMPORTANT
+            << "Battery widget disconnected.  This is expected if the earlier connected "
+               "robot unit shut down.";
+
+        QMetaObject::invokeMethod(this,
+                                  "setBatteryStatus",
+                                  Qt::QueuedConnection,
+                                  Q_ARG(dto::BatteryStatus, invalidStatus));
+
+        emit stopPeriodicStateUpdate();
+    }
+
+    void
+    BatteryWidget::loadSettings(QSettings* settings)
+    {
+        ;
+    }
+
+    void
+    BatteryWidget::saveSettings(QSettings* settings)
+    {
+        ;
+    }
+
+    void
+    BatteryWidget::updateBatteryStatus()
+    {
+        dto::BatteryStatus newStatus;
+
+        try
+        {
+            newStatus = batteryManagement->getBatteryStatus();
+        }
+        catch (...)
+        {
+            ARMARX_DEBUG << deactivateSpam(60) << "Failed to get current battery percentage";
+            newStatus.state = dto::BatteryState::unavailable;
+        }
+
+        QMetaObject::invokeMethod(
+            this, "setBatteryStatus", Qt::QueuedConnection, Q_ARG(dto::BatteryStatus, newStatus));
+    }
+
+    void
+    BatteryWidget::setBatteryStatus(dto::BatteryStatus batteryStatus)
+    {
+        lastStatus = batteryStatus;
+
+        icon->setPercentage(lastStatus.energyFromFullCharge_pct);
+        txtPercentage = QString("%1%").arg(lastStatus.energyFromFullCharge_pct, 0, 'f', 1);
+        lbl->setText(txtPercentage);
+
+        dto::BatteryState state = lastStatus.state;
+
+        icon->setState(state);
+        if (state == dto::BatteryState::unavailable)
+        {
+            lbl->setVisible(false);
+        }
+        else
+        {
+            lbl->setVisible(true);
+        }
+
+        updateTooltip();
+        icon->update();
+    }
+
+    std::string
+    BatteryWidget::getDefaultName() const
+    {
+        return "BatteryWidget" + iceNameUUID;
+    }
+
+} // namespace armarx
diff --git a/source/ArmarXGui/applications/ArmarXGui/Widgets/BatteryWidget.h b/source/ArmarXGui/applications/ArmarXGui/Widgets/BatteryWidget.h
new file mode 100644
index 0000000000000000000000000000000000000000..a05f3d5552de88bb678a6fca9f1a371f4f0c9f7f
--- /dev/null
+++ b/source/ArmarXGui/applications/ArmarXGui/Widgets/BatteryWidget.h
@@ -0,0 +1,111 @@
+#pragma once
+
+#include <QGridLayout>
+#include <QLabel>
+#include <QPaintEvent>
+#include <QPainter>
+#include <QPainterPath>
+#include <QTimer>
+#include <QWidget>
+
+#include <IceUtil/UUID.h>
+
+#include <ArmarXCore/core/IceGridAdmin.h>
+#include <ArmarXCore/interface/components/BatteryManagementInterface.h>
+
+#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXComponentWidgetController.h>
+
+Q_DECLARE_METATYPE(armarx::dto::BatteryStatus)
+
+namespace armarx
+{
+    class ArmarXMainWindow;
+
+    class BatteryIcon : public QWidget
+    {
+        Q_OBJECT
+    public:
+        explicit BatteryIcon(QWidget* parent = 0);
+
+        void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE;
+
+        void setPercentage(int percentage);
+
+        void setState(dto::BatteryState state);
+
+        QSize sizeHint() const Q_DECL_OVERRIDE;
+
+    private:
+        int percentage = 0;
+        dto::BatteryState state = dto::BatteryState::unavailable;
+    };
+
+    class BatteryWidget : public ArmarXComponentWidgetControllerTemplate<BatteryWidget>
+    {
+        Q_OBJECT
+    public:
+        explicit BatteryWidget(QWidget* parent = 0, ArmarXMainWindow* mainWindow = 0);
+
+        QWidget* getBatteryWidget();
+
+    signals:
+        void startPeriodicStateUpdate();
+        void stopPeriodicStateUpdate();
+
+    public slots:
+        void updateBatteryStatus();
+
+        void updateTooltip();
+
+        void setBatteryStatus(dto::BatteryStatus batteryStatus);
+
+        // ManagedIceObject interface
+    protected:
+        void onInitComponent() override;
+        void onConnectComponent() override;
+        void onDisconnectComponent() override;
+        std::string getDefaultName() const override;
+
+    private:
+        ArmarXMainWindow* mainWindow;
+        QGridLayout* layout;
+        BatteryIcon* icon;
+        QLabel* lbl;
+        QString txtPercentage;
+        QTimer* timer;
+
+        armarx::BatteryManagementInterfacePrx batteryManagement;
+
+        dto::BatteryStatus const invalidStatus{.name = "invalid",
+                                               .state = dto::BatteryState::unavailable,
+                                               .designEnergy_Wh = -1,
+                                               .fullChargeEnergy_Wh = -1,
+                                               .energy_Wh = -1,
+                                               .energyFromFullCharge_pct = 0,
+                                               .fullEnergyFromDesignEnergy_pct = 0,
+                                               .temperature_degC = -1,
+                                               .ratedVoltage_V = -1,
+                                               .voltage_V = -1,
+                                               .current_A = -1,
+                                               .power_W = -1,
+                                               .remainingTime_h = -1,
+                                               .hasError = false,
+                                               .error = ""};
+
+        dto::BatteryStatus lastStatus = invalidStatus;
+
+        // ArmarXWidgetController interface
+    public:
+        static QString
+        GetWidgetName()
+        {
+            return "BatteryWidget";
+        }
+
+        void loadSettings(QSettings* settings) override;
+        void saveSettings(QSettings* settings) override;
+        std::string iceNameUUID = IceUtil::generateUUID();
+    };
+
+    using BatteryWidgetPtr = IceInternal::Handle<BatteryWidget>;
+} // namespace armarx