diff --git a/groundStation/gui/MicroCART/MicroCART.pro.user b/groundStation/gui/MicroCART/MicroCART.pro.user index 1dbd232a082163317c643a0b53fd6b2f093385cd..b845d25d848e878796105144c4340687885425fb 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 3201d0ef341e73bde79b7e7ccc490e1ef7a5b4ce..6e7d92564b9bfe649352abba0939ea7c062b2b9d 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 58939cd8d2067a625e0fd4a934f05cacb866b4d8..9a2c6de5101100953c3cd65eb8fa5abc5998ba08 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 8eed5261fc0bee1fec1a916e4bbfac41eef739a1..7846be25d4b7b4cf9f58bf2b917c0fc28c107ee9 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 95dc0261e7241780af96e026696240382d52fb6d..95d901e51acbd7bc63ae6b306c03da33008243d4 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 2931a125f4b689f91261e140f168b56c8d20355a..16d9d4abf2df3a24cd26a0a78f98d6b123fd32c4 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 ac6da68956e933717a51ee9783bd1a821548a5a0..9488869efdef60d46e7ab06b33e52d42ef1928c8 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 adddf5119ff742f9f2a603936c8d3b59ae4c6deb..10a46e6d8fbed2cb157b1f7495ccd5100e93177c 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__