From c89f24237cee7ada07718689cd35991b4fd1396e Mon Sep 17 00:00:00 2001
From: Jake <j@kedrahos.com>
Date: Fri, 14 Apr 2017 18:45:38 -0500
Subject: [PATCH] Graph almost working in GUI

Had to make small changes to headers in quad inc
---
 .../gui/MicroCART/MicroCART.pro.user          |  2 +-
 groundStation/gui/MicroCART/controlworker.cpp | 59 ++++++++++++++++++-
 groundStation/gui/MicroCART/controlworker.h   |  1 +
 groundStation/gui/MicroCART/mainwindow.cpp    |  7 +++
 groundStation/gui/MicroCART/mainwindow.h      |  1 +
 groundStation/gui/MicroCART/mainwindow.ui     | 24 ++++----
 groundStation/src/frontend/frontend_source.h  | 10 +++-
 .../src/computation_graph/computation_graph.h |  8 +++
 8 files changed, 94 insertions(+), 18 deletions(-)

diff --git a/groundStation/gui/MicroCART/MicroCART.pro.user b/groundStation/gui/MicroCART/MicroCART.pro.user
index 1dbd232a0..b845d25d8 100644
--- a/groundStation/gui/MicroCART/MicroCART.pro.user
+++ b/groundStation/gui/MicroCART/MicroCART.pro.user
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 4.0.1, 2017-04-11T14:10:46. -->
+<!-- Written by QtCreator 4.0.1, 2017-04-11T17:47:13. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>
diff --git a/groundStation/gui/MicroCART/controlworker.cpp b/groundStation/gui/MicroCART/controlworker.cpp
index 3201d0ef3..6e7d92564 100644
--- a/groundStation/gui/MicroCART/controlworker.cpp
+++ b/groundStation/gui/MicroCART/controlworker.cpp
@@ -1,7 +1,10 @@
 #include "controlworker.h"
 #include "frontend_nodes.h"
 #include "frontend_param.h"
+#include "frontend_source.h"
 #include "graph_blocks.h"
+#include <QProcess>
+#include <err.h>
 
 ControlWorker::ControlWorker(QObject *parent) :
     QObject(parent), conn(NULL)
@@ -41,9 +44,63 @@ void ControlWorker::getNodes()
                 const_block_nodes.append(nd[i].name);
             }
         }
-        frontend_free_node_data(nd, num_nodes);
         emit(gotNodes(nodes));
         emit(gotConstantBlocks(const_block_nodes));
+
+        /* Create a graph for rendering.
+         *
+         * This leaks memory (NOT MY FAULT!) because there isn't a function to free
+         * a graph created with create_graph().
+         */
+        computation_graph * cgraph = create_graph();
+
+        /* Add nodes */
+        for (size_t i = 0; i < num_nodes; i++) {
+            graph_add_node_id(cgraph, nd[i].block, nd[i].name, blockDefs[nd[i].type], NULL);
+        }
+
+        /* Set sources */
+        for (size_t i = 0; i < num_nodes; i++) {
+            for (ssize_t j = 0; j < blockDefs[nd[i].type]->n_inputs; j++) {
+                frontend_source_data sd;
+                sd.dst_block = nd[i].block;
+                sd.dst_input = j;
+                sd.src_block = 0;
+                sd.src_output = 0;
+                frontend_getsource(conn, &sd);
+                graph_set_source(cgraph, sd.dst_block, sd.dst_input, sd.src_block, sd.src_output);
+            }
+        }
+
+        /* Set params */
+        for (size_t i = 0; i < num_nodes; i++) {
+            for (ssize_t j = 0; j < blockDefs[nd[i].type]->n_params; j++) {
+                frontend_param_data pd;
+                pd.block = nd[i].block;
+                pd.param = j;
+                pd.value = 0;
+                frontend_getparam(conn, &pd);
+                graph_set_param_val(cgraph, pd.block, pd.param, pd.value);
+            }
+        }
+
+        /* This is a massive hack... */
+        /* Could be done with popen, but fuck it */
+        FILE * dotfile = fopen("/tmp/ucart-tmp-graph.dot", "rw");
+        if (dotfile) {
+            export_dot(cgraph, dotfile, 0);
+            fclose(dotfile);
+            if (int dot_exit = QProcess::execute("dot /tmp/ucart-tmp/graph.dot -Tpng -o /tmp/ucart-tmp-graph.png")) {
+                warnx("dot returned nonzero value (%d)", dot_exit);
+            } else {
+                emit(graphRendered(QString("/tmp/ucart-tmp-graph.png")));
+            }
+        } else {
+            warn("fopen (/tmp/ucart-tmp-graph.dot)");
+        }
+
+        /* And here's where I'd put a call to free_graph(), IF I HAD ONE! */
+        frontend_free_node_data(nd, num_nodes);
     }
 }
 
diff --git a/groundStation/gui/MicroCART/controlworker.h b/groundStation/gui/MicroCART/controlworker.h
index 58939cd8d..9a2c6de51 100644
--- a/groundStation/gui/MicroCART/controlworker.h
+++ b/groundStation/gui/MicroCART/controlworker.h
@@ -18,6 +18,7 @@ signals:
     void gotParamValue(QString node, QString param, float value);
     void gotConstantBlocks(QStringList blocks);
     void paramSet(QString node, QString param);
+    void graphRendered(QString graph);
 
 public slots:
     void connectBackend();
diff --git a/groundStation/gui/MicroCART/mainwindow.cpp b/groundStation/gui/MicroCART/mainwindow.cpp
index 8eed5261f..7846be25d 100644
--- a/groundStation/gui/MicroCART/mainwindow.cpp
+++ b/groundStation/gui/MicroCART/mainwindow.cpp
@@ -6,6 +6,7 @@
 #include <QTimer>
 #include <QRegExp>
 #include <QProcessEnvironment>
+#include <QPixmap>
 
 #include "wrappers.h"
 #include "trackerworker.h"
@@ -294,6 +295,12 @@ void MainWindow::on_pbDeleteSetpoint_clicked()
     }
 }
 
+void MainWindow::newControlGraph(QString graph)
+{
+    findChild<QLabel *>("graphImage")->setPixmap(QPixmap(graph));
+}
+
 void MainWindow::on_socketPath_returnPressed()
 {
+    QProcessEnvironment::systemEnvironment().insert("UCART_SOCKET", findChild<QLineEdit *>("socketPath")->text());
 }
diff --git a/groundStation/gui/MicroCART/mainwindow.h b/groundStation/gui/MicroCART/mainwindow.h
index 95dc0261e..95d901e51 100644
--- a/groundStation/gui/MicroCART/mainwindow.h
+++ b/groundStation/gui/MicroCART/mainwindow.h
@@ -40,6 +40,7 @@ private slots:
     void newParams(QStringList params);
     void newParamValue(QString node, QString param, float val);
     void newConstantBlocks(QStringList blocks);
+    void newControlGraph(QString graph);
 
     void on_paramSelect_currentIndexChanged(const QString &arg1);
 
diff --git a/groundStation/gui/MicroCART/mainwindow.ui b/groundStation/gui/MicroCART/mainwindow.ui
index 2931a125f..16d9d4abf 100644
--- a/groundStation/gui/MicroCART/mainwindow.ui
+++ b/groundStation/gui/MicroCART/mainwindow.ui
@@ -37,7 +37,7 @@
           <item row="0" column="1">
            <widget class="QLineEdit" name="socketPath">
             <property name="enabled">
-             <bool>false</bool>
+             <bool>true</bool>
             </property>
            </widget>
           </item>
@@ -143,23 +143,19 @@
        <layout class="QVBoxLayout" name="verticalLayout_2">
         <item>
          <widget class="QLabel" name="graphImage">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
           <property name="text">
            <string>Refresh to display controller graph</string>
           </property>
-         </widget>
-        </item>
-        <item>
-         <spacer name="verticalSpacer_2">
-          <property name="orientation">
-           <enum>Qt::Vertical</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>20</width>
-            <height>159</height>
-           </size>
+          <property name="alignment">
+           <set>Qt::AlignCenter</set>
           </property>
-         </spacer>
+         </widget>
         </item>
         <item>
          <widget class="Line" name="line_2">
diff --git a/groundStation/src/frontend/frontend_source.h b/groundStation/src/frontend/frontend_source.h
index ac6da6895..9488869ef 100644
--- a/groundStation/src/frontend/frontend_source.h
+++ b/groundStation/src/frontend/frontend_source.h
@@ -3,6 +3,10 @@
 
 #include "frontend_common.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Get the block.output that corresponds 
  *      to the block.input in question.
  *
@@ -21,5 +25,7 @@ int frontend_setsource(
 		struct backend_conn * conn,
 		struct frontend_source_data * source_data);
 
-
-#endif /* _FRONTEND_SOURCE_H */
\ No newline at end of file
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FRONTEND_SOURCE_H */
diff --git a/quad/src/computation_graph/computation_graph.h b/quad/src/computation_graph/computation_graph.h
index adddf5119..10a46e6d8 100644
--- a/quad/src/computation_graph/computation_graph.h
+++ b/quad/src/computation_graph/computation_graph.h
@@ -4,6 +4,10 @@
 #include <stdio.h>
 #include <math.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef void (*execute_node_t)(void *state,
                                const double* params,
                                const double *inputs,
@@ -138,4 +142,8 @@ int graph_node_exists(const struct computation_graph *graph, int node_id);
  */
 int export_dot(const struct computation_graph* graph, FILE* of, int print_outputs);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif // __COMPUTATION_GRAPH_H__
-- 
GitLab