diff --git a/.gitmodules b/.gitmodules
index 1d7f28ad9b1e45d495b9440664eac40bad1ac6cf..6821767e986fef35ecf107d7b79b6ae27c0834bb 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,4 @@
 [submodule "groundStation/src/vrpn"]
 	path = groundStation/src/vrpn
 	url = https://github.com/vrpn/vrpn
+	ignore = dirty
diff --git a/controls/model/.gitignore b/controls/model/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..fdd0385d7c2df2b890075dc24d1f80bb1e671391
--- /dev/null
+++ b/controls/model/.gitignore
@@ -0,0 +1,3 @@
+slprj/
+test_model_grt_rtw/
+test_model_sfun.mexw64
\ No newline at end of file
diff --git a/groundStation/src/backend/backend.c b/groundStation/src/backend/backend.c
index 300e9546868bb57116edbfb478b6c129d65e50ff..f4fcee7b039c73670146b11e78e427049010257b 100644
--- a/groundStation/src/backend/backend.c
+++ b/groundStation/src/backend/backend.c
@@ -341,28 +341,48 @@ void printVrpnData(struct ucart_vrpn_TrackerData * td) {
 
 int connectToZybo() {
 	int sock;
-	int status = 0;
+	int status = -1;
 
 	if (getenv(NOQUAD_ENV)) {
 		return 0;
 	}
 
-	/* Use bluetooth by default */
-	if (!getenv(QUAD_WIFI_ENV)) {
-		printf("Using BT Settings\n");
-		struct sockaddr_rc addr;
+	/* Use wifi by default */
+	if (getenv(QUAD_COMM_ENV)) {
+		/* Determine if we are using bluetooth or local */
+		if(strcmp(getenv(QUAD_COMM_ENV), "local") == 0) {
+			printf("Using Local Socket Settings\n");
+			
+			struct sockaddr_un remote;
+			char str[100];
+
+			if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+				perror("socket");
+				exit(1);
+			}
 
-		// allocate a socket	
-		sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+			remote.sun_family = AF_UNIX;
+			char * sock_env = getenv(QUAD_LOCAL_SOCKET);
+			strcpy(remote.sun_path, sock_env ? sock_env : QUAD_DEFAULT_LOCAL_SOCKET);
+			printf("Attempting to connect to local socket at '%s'. please be patiend.\n", remote.sun_path);
 
-		//set the connection params ie. who to connect to	
-		addr.rc_family = AF_BLUETOOTH;
-		addr.rc_channel = (uint8_t) QUAD_BT_CHANNEL;
-		str2ba( QUAD_BT_ADDR, &addr.rc_bdaddr );
-		
-		printf("Attempting to connect to zybo. Please be patient...\n");
-		// blocking call to connect to socket sock ie. zybo board
-		status = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
+			status = connect(sock, (struct sockaddr *)&remote, sizeof(remote));
+		} else if (strcmp(getenv(QUAD_COMM_ENV), "bluetooth") == 0) {
+			printf("Using BT Settings\n");
+			struct sockaddr_rc addr;
+
+			// allocate a socket	
+			sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+
+			//set the connection params ie. who to connect to	
+			addr.rc_family = AF_BLUETOOTH;
+			addr.rc_channel = (uint8_t) QUAD_BT_CHANNEL;
+			str2ba( QUAD_BT_ADDR, &addr.rc_bdaddr );
+			
+			printf("Attempting to connect to zybo. Please be patient...\n");
+			// blocking call to connect to socket sock ie. zybo board
+			status = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
+		}
 	} else {
 		printf("Using WIFI settings\n");
 		struct sockaddr_in addr;
diff --git a/groundStation/src/backend/config.h b/groundStation/src/backend/config.h
index 38bf5611a009380597fd44732d995bb65535e75a..9306bd65ecf4ca80e60fb118a942e8fff00131d1 100644
--- a/groundStation/src/backend/config.h
+++ b/groundStation/src/backend/config.h
@@ -11,7 +11,10 @@
 // If you are planning on using any of these env vars and you have
 // 	exported them with normal user rights. You will need to run the 
 // 	backend with sudo elevation and with the --preserve-env flag or -E
-#define QUAD_WIFI_ENV "UCART_USE_WIFI"
+#define QUAD_COMM_ENV "UCART_COMM_CHANNEL"
+
+#define QUAD_DEFAULT_LOCAL_SOCKET "./virtquad.socket"
+#define QUAD_LOCAL_SOCKET "UCART_LOCAL_SOCKET"
 #define QUAD_IP_ENV "UCART_QUAD_IP"
 #define QUAD_IP_DEFAULT "192.168.1.1"
 #define QUAD_PORT_ENV "UCART_QUAD_PORT"
diff --git a/quad/Makefile b/quad/Makefile
index 18875c630eee61348a964b38c0cdac57fc0d2eb5..d04ffe0e3d8af5a9842809be690f7ab85d30e134 100644
--- a/quad/Makefile
+++ b/quad/Makefile
@@ -14,6 +14,7 @@ libs:
 	$(MAKE) -C src/test
 	$(MAKE) -C src/queue
 	$(MAKE) -C src/computation_graph
+	$(MAKE) -C src/graph_blocks
 	$(MAKE) -C src/commands
 	$(MAKE) -C src/quad_app
 
@@ -38,6 +39,7 @@ deep-clean:
 	$(MAKE) -C src/test clean
 	$(MAKE) -C src/queue clean
 	$(MAKE) -C src/computation_graph clean
+	$(MAKE) -C src/graph_blocks clean
 	$(MAKE) -C src/commands clean
 	$(MAKE) -C src/quad_app clean
 	bash scripts/clean_xsdk_workspace.sh
diff --git a/quad/scripts/__pycache__/uart_stress_tests.cpython-36.pyc b/quad/scripts/__pycache__/uart_stress_tests.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4b92a40fddc351f17e205b35da850c41744a373c
Binary files /dev/null and b/quad/scripts/__pycache__/uart_stress_tests.cpython-36.pyc differ
diff --git a/quad/src/commands/commands.c b/quad/src/commands/commands.c
index 9111f1050af02e5e26800623266e7e83aaefa9dd..14ae7c58c9e3bac69bfc1d4a04c8239cabc0d908 100644
--- a/quad/src/commands/commands.c
+++ b/quad/src/commands/commands.c
@@ -143,14 +143,14 @@ struct MessageType MessageTypes[MAX_TYPE_ID] =
 		// Function pointer
 		&cb_log
 	},
-	// RESPONSE
+	// LOG_END
 	{
 		// Command text
-		"response",
+		"logend",
 		// Type of the command data
 		stringType,
 		// Function pointer
-		&cb_response
+		&cb_logend
 	},
 	// SETPARAM
 	{
@@ -259,15 +259,6 @@ struct MessageType MessageTypes[MAX_TYPE_ID] =
 		floatType,
 		// Function pointer
 		&cb_respaddnode
-	},
-	// LOG_END
-	{
-		// Command text
-		"logend",
-		// Type of the command data
-		stringType,
-		// Function pointer
-		&cb_logend
 	}
 };
 
diff --git a/quad/src/computation_graph/Makefile b/quad/src/computation_graph/Makefile
index 5142ac39b839e02ca6ed2eb2c28fcec186b88ef7..ddd1f5c2e82619162c544e52c82cd774958782dd 100644
--- a/quad/src/computation_graph/Makefile
+++ b/quad/src/computation_graph/Makefile
@@ -1,6 +1,6 @@
 TOP=../..
 
 NAME = computation_graph
-REQLIBS = -ltest -lm
+REQLIBS = -ltest -lm -lgraph_blocks
 
 include $(TOP)/library.mk
diff --git a/quad/src/computation_graph/computation_graph.h b/quad/src/computation_graph/computation_graph.h
index 2cd90dc15ff6e278b379c24504443def566fb419..e997aa7ab06a79d61aac152699d9a49379403ffc 100644
--- a/quad/src/computation_graph/computation_graph.h
+++ b/quad/src/computation_graph/computation_graph.h
@@ -25,14 +25,16 @@ struct computation_graph {
 
 // Declares a node type
 struct graph_node_type {
-    const char* const* input_names;
-    const char* const* output_names;
-    const char* const* param_names;
-    int n_inputs;
-    int n_outputs;
-    int n_params;
-    execute_node_t execute;
-    reset_node_t reset;
+    const char* const* input_names; // Array of strings corresponding to the inputs
+    const char* const* output_names; // Array of strings corresponding to the outputs
+    const char* const* param_names; // Array of strings corresponding to the parameters
+    int n_inputs; // Number of inputs
+    int n_outputs; // Number of outputs
+    int n_params; // Number of parameters
+    execute_node_t execute; // Function describing how to produce outputs
+    reset_node_t reset; // Reset this node. Called upon (re)connection
+    size_t state_size; // Size of the state struct for this type
+    int type_id; // A unique ID for this node type
 };
 
 // Holds a tuple for defining the source of a node. Includes the node ID and its output ID
diff --git a/quad/src/computation_graph/test/test_computation_graph.c b/quad/src/computation_graph/test/test_computation_graph.c
index 42e913dca182bb8406f8e4eb925001d46cacbaca..929fe9ca44404efbaa9e46287cc78a6a2fe057f9 100644
--- a/quad/src/computation_graph/test/test_computation_graph.c
+++ b/quad/src/computation_graph/test/test_computation_graph.c
@@ -2,11 +2,7 @@
 
 
 #include "computation_graph.h"
-#include "node_add.h"
-#include "node_mult.h"
-#include "node_constant.h"
-#include "node_gain.h"
-#include "node_accumulator.h"
+#include "graph_blocks.h"
 
 #define GRAPH_TEST_EPS 0.00001
 
@@ -19,10 +15,10 @@ static int nequal(double val1, double val2) {
 
 int graph_test_one_add() {
     struct computation_graph *graph = create_graph();
-    int block = graph_add_node_add(graph, "Add");
-    int cblock3 = graph_add_node_const(graph, "3");
+    int block = graph_add_defined_block(graph, BLOCK_ADD, "Add");
+    int cblock3 = graph_add_defined_block(graph, BLOCK_CONSTANT, "3");
     graph_set_param_val(graph, cblock3, CONST_SET, 3);
-    int cblock4 = graph_add_node_const(graph, "4");
+    int cblock4 = graph_add_defined_block(graph, BLOCK_CONSTANT, "4");
     graph_set_param_val(graph, cblock4, CONST_SET, 4);
     graph_set_source(graph, block, ADD_SUMMAND1, cblock3, CONST_VAL);
     graph_set_source(graph, block, ADD_SUMMAND2, cblock4, CONST_VAL);
@@ -35,8 +31,8 @@ int graph_test_one_add() {
 
 int graph_test_circular_runs() {
     struct computation_graph *graph = create_graph();
-    int gain1 = graph_add_node_gain(graph, "gain1");
-    int gain2 = graph_add_node_gain(graph, "gain2");
+    int gain1 = graph_add_defined_block(graph, BLOCK_GAIN, "gain1");
+    int gain2 = graph_add_defined_block(graph, BLOCK_GAIN, "gain2");
     graph_set_source(graph, gain2, GAIN_INPUT, gain1, GAIN_RESULT);
     graph_set_source(graph, gain1, GAIN_INPUT, gain2, GAIN_RESULT);
     int to_compute_for[1] = {gain2};
@@ -47,8 +43,8 @@ int graph_test_circular_runs() {
 
 int graph_test_circular_resets() {
     struct computation_graph *graph = create_graph();
-    int acum1 = graph_add_node_accum(graph, "accumulator1");
-    int acum2 = graph_add_node_accum(graph, "accumulator2");
+    int acum1 = graph_add_defined_block(graph, BLOCK_ACCUMULATE, "accumulator1");
+    int acum2 = graph_add_defined_block(graph, BLOCK_ACCUMULATE, "accumulator2");
     graph_set_source(graph, acum2, ACCUM_IN, acum1, ACCUMULATED);
     graph_set_source(graph, acum1, ACCUM_IN, acum2, ACCUMULATED);
     return 0; // Passes if no infinite loop
@@ -57,8 +53,8 @@ int graph_test_circular_resets() {
 // Tests the accumulator block, thereby testing reset and state changes
 int graph_test_accumulator() {
     struct computation_graph *graph = create_graph();
-    int cblock = graph_add_node_const(graph, "const");
-    int acum_b = graph_add_node_accum(graph, "accumulator");
+    int cblock = graph_add_defined_block(graph, BLOCK_CONSTANT, "const");
+    int acum_b = graph_add_defined_block(graph, BLOCK_ACCUMULATE, "accumulator");
     graph_set_source(graph, acum_b, ACCUM_IN, cblock, CONST_VAL);
 
     int to_compute_for[1] = {acum_b};
@@ -76,7 +72,7 @@ int graph_test_accumulator() {
     }
 
     // Test reset on source set
-    int gain_b = graph_add_node_gain(graph, "Gain");
+    int gain_b = graph_add_defined_block(graph, BLOCK_GAIN, "Gain");
     graph_set_param_val(graph, gain_b, GAIN_GAIN, 1);
     graph_set_source(graph, gain_b, GAIN_INPUT, acum_b, ACCUMULATED);
     to_compute_for[0] = gain_b;
@@ -93,9 +89,9 @@ int graph_test_accumulator() {
 // even if its output is connected to multiple inputs
 int graph_test_single_run() {
     struct computation_graph *graph = create_graph();
-    int acum_b = graph_add_node_accum(graph, "accumulator");
-    int add_block = graph_add_node_add(graph, "Add");
-    int cblock = graph_add_node_const(graph, "const");
+    int acum_b = graph_add_defined_block(graph, BLOCK_ACCUMULATE, "accumulator");
+    int add_block = graph_add_defined_block(graph, BLOCK_ADD, "Add");
+    int cblock = graph_add_defined_block(graph, BLOCK_CONSTANT, "const");
     graph_set_param_val(graph, cblock, CONST_SET, 2);
 
 
@@ -112,10 +108,10 @@ int graph_test_single_run() {
 // Tests that upon connection of a second child, a block will not reset
 int graph_test_reset_rules() {
     struct computation_graph *graph = create_graph();
-    int cblock = graph_add_node_const(graph, "5");
+    int cblock = graph_add_defined_block(graph, BLOCK_CONSTANT, "5");
     graph_set_param_val(graph, cblock, CONST_SET, 5);
-    int acum_b = graph_add_node_accum(graph, "accumulator");
-    int gain1 = graph_add_node_gain(graph, "gain1");
+    int acum_b = graph_add_defined_block(graph, BLOCK_ACCUMULATE, "accumulator");
+    int gain1 = graph_add_defined_block(graph, BLOCK_GAIN, "gain1");
     graph_set_param_val(graph, gain1, GAIN_GAIN, 1);
 
     graph_set_source(graph, gain1, GAIN_INPUT, acum_b, ACCUMULATED);
@@ -124,7 +120,7 @@ int graph_test_reset_rules() {
     graph_compute_nodes(graph, to_compute_for, 1);
     // state of acum_b is now 5
 
-    int gain2 = graph_add_node_gain(graph, "gain2");
+    int gain2 = graph_add_defined_block(graph, BLOCK_GAIN, "gain2");
     graph_set_param_val(graph, gain2, GAIN_GAIN, 1);
     // Connect gain 2, and accumulator should not get reset
     graph_set_source(graph, gain2, GAIN_INPUT, acum_b, ACCUMULATED);
@@ -138,7 +134,7 @@ int graph_test_reset_rules() {
 
 int graph_test_self_loop() {
     struct computation_graph *graph = create_graph();
-    int gain1 = graph_add_node_gain(graph, "gain1");
+    int gain1 = graph_add_defined_block(graph, BLOCK_GAIN, "gain1");
     graph_set_source(graph, gain1, GAIN_INPUT, gain1, GAIN_RESULT);
     int to_compute_for[1] = {gain1};
     graph_compute_nodes(graph, to_compute_for, 1);
@@ -147,8 +143,8 @@ int graph_test_self_loop() {
 
 int graph_test_update_rules() {
     struct computation_graph *graph = create_graph();
-    int cblock = graph_add_node_const(graph, "const");
-    int acum_b = graph_add_node_accum(graph, "accumulator");
+    int cblock = graph_add_defined_block(graph, BLOCK_CONSTANT, "const");
+    int acum_b = graph_add_defined_block(graph, BLOCK_ACCUMULATE, "accumulator");
     graph_set_source(graph, acum_b, ACCUM_IN, cblock, CONST_VAL);
 
     graph_set_param_val(graph, cblock, CONST_SET, 3);
@@ -167,11 +163,11 @@ C2 --->| accum_b2 --->|
 */
 int graph_test_update_propagation() {
     struct computation_graph *graph = create_graph();
-    int cblock1 = graph_add_node_const(graph, "const1");
-    int cblock2 = graph_add_node_const(graph, "const2");
-    int accum_b1 = graph_add_node_accum(graph, "accumulator1");
-    int accum_b2 = graph_add_node_accum(graph, "accumulator2");
-    int add_b = graph_add_node_add(graph, "add");
+    int cblock1 = graph_add_defined_block(graph, BLOCK_CONSTANT, "const1");
+    int cblock2 = graph_add_defined_block(graph, BLOCK_CONSTANT, "const2");
+    int accum_b1 = graph_add_defined_block(graph, BLOCK_ACCUMULATE, "accumulator1");
+    int accum_b2 = graph_add_defined_block(graph, BLOCK_ACCUMULATE, "accumulator2");
+    int add_b = graph_add_defined_block(graph, BLOCK_ADD, "add");
     graph_set_source(graph, accum_b1, ACCUM_IN, cblock1, CONST_VAL);
     graph_set_source(graph, accum_b2, ACCUM_IN, cblock2, CONST_VAL);
     graph_set_source(graph, add_b, ADD_SUMMAND1, accum_b1, ACCUMULATED);
@@ -199,10 +195,10 @@ the node would never get set.
 int graph_test_update_disconnected() {
     printf("\n\n---------\n");
     struct computation_graph *graph = create_graph();
-    int d_block = graph_add_node_const(graph, "const1");
-    int gain_block = graph_add_node_gain(graph, "gain");
-    int gain2_block = graph_add_node_gain(graph, "gain2");
-    int const_b = graph_add_node_const(graph, "const2");
+    int d_block = graph_add_defined_block(graph, BLOCK_CONSTANT, "const1");
+    int gain_block = graph_add_defined_block(graph, BLOCK_GAIN, "gain");
+    int gain2_block = graph_add_defined_block(graph, BLOCK_GAIN, "gain2");
+    int const_b = graph_add_defined_block(graph, BLOCK_CONSTANT, "const2");
     graph_set_source(graph, gain_block, GAIN_INPUT, const_b, CONST_VAL);
     graph_set_source(graph, gain2_block, GAIN_INPUT, d_block, CONST_VAL); // We need this so d_block doesn't get updated
     graph_set_param_val(graph, gain_block, GAIN_GAIN, 2);
@@ -219,8 +215,8 @@ int graph_test_update_disconnected() {
 
 int graph_test_get_source() {
     struct computation_graph *graph = create_graph();
-    int add_block = graph_add_node_add(graph, "Add");
-    int cblock3 = graph_add_node_const(graph, "3");
+    int add_block = graph_add_defined_block(graph, BLOCK_ADD, "Add");
+    int cblock3 = graph_add_defined_block(graph, BLOCK_CONSTANT, "3");
     graph_set_source(graph, add_block, ADD_SUMMAND1, cblock3, CONST_VAL);
 
     struct node_src source = graph_get_source(graph, add_block, ADD_SUMMAND1);
@@ -234,7 +230,7 @@ int graph_test_get_source() {
 
 int graph_test_get_source_null() {
     struct computation_graph *graph = create_graph();
-    int add_block = graph_add_node_add(graph, "Add");
+    int add_block = graph_add_defined_block(graph, BLOCK_ADD, "Add");
 
     struct node_src source = graph_get_source(graph, 123, ADD_SUMMAND1);
     if (source.controller_id != -1) {
diff --git a/quad/src/graph_blocks/.gitignore b/quad/src/graph_blocks/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..90edb74c26197159cf7438929580622073b7cd17
--- /dev/null
+++ b/quad/src/graph_blocks/.gitignore
@@ -0,0 +1 @@
+obj/
diff --git a/quad/src/graph_blocks/Makefile b/quad/src/graph_blocks/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..2769a61ebc43c61087f2cb47df50d11e94729e95
--- /dev/null
+++ b/quad/src/graph_blocks/Makefile
@@ -0,0 +1,6 @@
+TOP=../..
+
+NAME = graph_blocks
+REQLIBS = -lcomputation_graph
+
+include $(TOP)/library.mk
diff --git a/quad/src/graph_blocks/graph_blocks.c b/quad/src/graph_blocks/graph_blocks.c
new file mode 100644
index 0000000000000000000000000000000000000000..325218bf8d966c0eaca77675fb091ad34e4a28fd
--- /dev/null
+++ b/quad/src/graph_blocks/graph_blocks.c
@@ -0,0 +1,33 @@
+#include "graph_blocks.h"
+#include <stdlib.h>
+
+// See graph_blocks.h
+const struct graph_node_type* blockDefs[MAX_BLOCK_TYPES] = 
+{
+    &node_const_type,
+    &node_add_type,
+    &node_mult_type,
+    &node_gain_type,
+    &node_accum_type,
+    &node_bounds_type,
+    &node_mixer_type,
+    &node_pid_type
+};
+
+
+int graph_add_defined_block(struct computation_graph* graph, int type_id, const char* name) {
+    // Verify block type is valid
+    if (type_id >= MAX_BLOCK_TYPES) {
+        return -1;
+    }
+    const struct graph_node_type *block_type = blockDefs[type_id];
+    void* state = NULL;
+    // Allocate the state struct for this node, if necessary
+    if (block_type->state_size) {
+        state = malloc(block_type->state_size);
+        if (!state) {return -1;} // Check for malloc failure
+    }
+
+    // Use the computation graph implementation's add node function
+    return graph_add_node(graph, name, block_type, state);
+}
\ No newline at end of file
diff --git a/quad/src/graph_blocks/graph_blocks.h b/quad/src/graph_blocks/graph_blocks.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc822b242bbbc2a80a064ce2390a846cef7bc8d5
--- /dev/null
+++ b/quad/src/graph_blocks/graph_blocks.h
@@ -0,0 +1,55 @@
+#ifndef __GRAPH_BLOCKS_H__
+#define __GRAPH_BLOCKS_H__
+
+#include "computation_graph.h"
+#include "node_constant.h"
+#include "node_add.h"
+#include "node_mult.h"
+#include "node_gain.h"
+#include "node_accumulator.h"
+#include "node_bounds.h"
+#include "node_mixer.h"
+#include "node_pid.h"
+
+/*
+ * ---------- How-To ------------
+ * To add a new block type, put the implementation (.c and .h) files
+ * in the same directory as this file, and include the header file above
+ * Add a new entry to this enum right before MAX_BLOCK_TYPES
+ * 
+ * In graph_blocks.c, add a new entry at the end of the array with
+ * your graph_node_type struct.
+ */
+
+
+
+/*
+ * Enumerates all the types of different block types.
+ * Must match blockDefs
+ */
+enum BlockTypes {
+    BLOCK_CONSTANT,      // 00
+    BLOCK_ADD,           // 01
+    BLOCK_MULT,          // 02
+    BLOCK_GAIN,          // 03
+    BLOCK_ACCUMULATE,    // 04
+    BLOCK_BOUNDS,        // 05
+    BLOCK_MIXER,         // 07
+    BLOCK_PID,           // 08
+    //                        <-- Insert new block type here
+    MAX_BLOCK_TYPES
+};
+
+/*
+ * Array corresponding to the different block type structs
+ * Mustm match the nums in BlockTypes
+ */
+extern const struct graph_node_type* blockDefs[MAX_BLOCK_TYPES];
+
+
+/*
+ * Creates a new node and adds it to the graph with the given type ID and name
+ * Returns the id of the new node upon success, -1 upon failure
+ */
+int graph_add_defined_block(struct computation_graph* graph, int type_id, const char* name);
+#endif // __GRAPH_BLOCKS_H__
diff --git a/quad/src/computation_graph/node_accumulator.c b/quad/src/graph_blocks/node_accumulator.c
similarity index 91%
rename from quad/src/computation_graph/node_accumulator.c
rename to quad/src/graph_blocks/node_accumulator.c
index 17a36ee92dffc796e9ea592f28ecd1f4737085a1..10b96873750e862b9072d0f2738842aa3be69ec7 100644
--- a/quad/src/computation_graph/node_accumulator.c
+++ b/quad/src/graph_blocks/node_accumulator.c
@@ -27,7 +27,9 @@ const struct graph_node_type node_accum_type = {
         .n_outputs = 1,
         .n_params = 0,
         .execute = accum_nodes,
-        .reset = reset
+        .reset = reset,
+        .state_size = sizeof(struct accum_state),
+        .type_id = BLOCK_ACCUMULATE
 };
 
 int graph_add_node_accum(struct computation_graph *graph, const char* name) {
diff --git a/quad/src/computation_graph/node_accumulator.h b/quad/src/graph_blocks/node_accumulator.h
similarity index 93%
rename from quad/src/computation_graph/node_accumulator.h
rename to quad/src/graph_blocks/node_accumulator.h
index a392a9db295e5bc7f44d84292e4aa561ee3fba9d..43301d6676aa1289a6523da45546ffc88f7cbfe0 100644
--- a/quad/src/computation_graph/node_accumulator.h
+++ b/quad/src/graph_blocks/node_accumulator.h
@@ -1,6 +1,7 @@
 #ifndef __NODE_ACCUMULATOR_H__
 #define __NODE_ACCUMULATOR_H__
 #include "computation_graph.h"
+#include "graph_blocks.h"
 
 int graph_add_node_accum(struct computation_graph *graph, const char* name);
 
diff --git a/quad/src/computation_graph/node_add.c b/quad/src/graph_blocks/node_add.c
similarity index 91%
rename from quad/src/computation_graph/node_add.c
rename to quad/src/graph_blocks/node_add.c
index 048a49b3b6a9c054f74900e356e6377f17a6a4b7..25a780a32681df3d56aec758f9f0527115ee00b7 100644
--- a/quad/src/computation_graph/node_add.c
+++ b/quad/src/graph_blocks/node_add.c
@@ -17,7 +17,9 @@ const struct graph_node_type node_add_type = {
         .n_outputs = 1,
         .n_params = 0,
         .execute = add_nodes,
-        .reset = reset
+        .reset = reset,
+        .state_size = 0,
+        .type_id = BLOCK_ADD
 };
 
 int graph_add_node_add(struct computation_graph *graph, const char* name) {
diff --git a/quad/src/computation_graph/node_add.h b/quad/src/graph_blocks/node_add.h
similarity index 92%
rename from quad/src/computation_graph/node_add.h
rename to quad/src/graph_blocks/node_add.h
index 390e3d229c7a943fdd09c26e18be711672cf000e..34b8123638dc1d954ceb0dcd6ceadb959ae6c5c5 100644
--- a/quad/src/computation_graph/node_add.h
+++ b/quad/src/graph_blocks/node_add.h
@@ -1,6 +1,7 @@
 #ifndef __NODE_ADD_H__
 #define __NODE_ADD_H__
 #include "computation_graph.h"
+#include "graph_blocks.h"
 
 int graph_add_node_add(struct computation_graph *graph, const char* name);
 
diff --git a/quad/src/quad_app/node_bounds.c b/quad/src/graph_blocks/node_bounds.c
similarity index 92%
rename from quad/src/quad_app/node_bounds.c
rename to quad/src/graph_blocks/node_bounds.c
index aae4a67957a3d76c89d44480962e7b426b94f235..d1fe264311e1c5223df17f61e7e0330e9466c286 100644
--- a/quad/src/quad_app/node_bounds.c
+++ b/quad/src/graph_blocks/node_bounds.c
@@ -25,7 +25,9 @@ const struct graph_node_type node_bounds_type = {
         .n_outputs = 1,
         .n_params = 2,
         .execute = bounds_computation,
-        .reset = reset_bounds
+        .reset = reset_bounds,
+        .state_size = 0,
+        .type_id = BLOCK_BOUNDS
 };
 
 int graph_add_node_bounds(struct computation_graph *graph, const char* name) {
diff --git a/quad/src/quad_app/node_bounds.h b/quad/src/graph_blocks/node_bounds.h
similarity index 94%
rename from quad/src/quad_app/node_bounds.h
rename to quad/src/graph_blocks/node_bounds.h
index 4c3b93256106bce8560daf28c67f19844fb2ea8f..7eea073fa6000457c30588f251565fcdd3db1a5c 100644
--- a/quad/src/quad_app/node_bounds.h
+++ b/quad/src/graph_blocks/node_bounds.h
@@ -1,6 +1,7 @@
 #ifndef __NODE_BOUNDS_H__
 #define __NODE_BOUNDS_H__
 #include "computation_graph.h"
+#include "graph_blocks.h"
 
 int graph_add_node_bounds(struct computation_graph *graph, const char* name);
 
diff --git a/quad/src/computation_graph/node_constant.c b/quad/src/graph_blocks/node_constant.c
similarity index 90%
rename from quad/src/computation_graph/node_constant.c
rename to quad/src/graph_blocks/node_constant.c
index b2a46e757eef397b4c9805d4b76a159fccc6c9a0..8bd406ad924f3025631c4d251c5d751eddcce90e 100644
--- a/quad/src/computation_graph/node_constant.c
+++ b/quad/src/graph_blocks/node_constant.c
@@ -17,7 +17,9 @@ const struct graph_node_type node_const_type = {
         .n_outputs = 1,
         .n_params = 1,
         .execute = output_const,
-        .reset = reset
+        .reset = reset,
+        .state_size = 0,
+        .type_id = BLOCK_CONSTANT
 };
 
 int graph_add_node_const(struct computation_graph *graph, const char* name) {
diff --git a/quad/src/computation_graph/node_constant.h b/quad/src/graph_blocks/node_constant.h
similarity index 93%
rename from quad/src/computation_graph/node_constant.h
rename to quad/src/graph_blocks/node_constant.h
index c67ac6e0511e971e1f9ca57c853bd9de6fca6238..417e92da19bbe1170cbec09598e4129d3c4400a6 100644
--- a/quad/src/computation_graph/node_constant.h
+++ b/quad/src/graph_blocks/node_constant.h
@@ -1,6 +1,7 @@
 #ifndef __NODE_CONSTANT_H__
 #define __NODE_CONSTANT_H__
 #include "computation_graph.h"
+#include "graph_blocks.h"
 
 int graph_add_node_const(struct computation_graph *graph, const char* name);
 
diff --git a/quad/src/computation_graph/node_gain.c b/quad/src/graph_blocks/node_gain.c
similarity index 91%
rename from quad/src/computation_graph/node_gain.c
rename to quad/src/graph_blocks/node_gain.c
index 35bb3702cf2aa36d2f08f85ed580d12fadbe8fa8..3c0ac77ae8a54b0e99b6b767ec85083f3e047e91 100644
--- a/quad/src/computation_graph/node_gain.c
+++ b/quad/src/graph_blocks/node_gain.c
@@ -17,7 +17,9 @@ const struct graph_node_type node_gain_type = {
         .n_outputs = 1,
         .n_params = 1,
         .execute = scale_nodes,
-        .reset = reset
+        .reset = reset,
+        .state_size = 0,
+        .type_id = BLOCK_GAIN
 };
 
 int graph_add_node_gain(struct computation_graph *graph, const char* name) {
diff --git a/quad/src/computation_graph/node_gain.h b/quad/src/graph_blocks/node_gain.h
similarity index 93%
rename from quad/src/computation_graph/node_gain.h
rename to quad/src/graph_blocks/node_gain.h
index 4089244980ad7ee2fc50bc375f6cbb1500196b5e..4a1a3322f65789ffccd6282125181f8deade4200 100644
--- a/quad/src/computation_graph/node_gain.h
+++ b/quad/src/graph_blocks/node_gain.h
@@ -1,6 +1,7 @@
 #ifndef __NODE_GAIN_H__
 #define __NODE_GAIN_H__
 #include "computation_graph.h"
+#include "graph_blocks.h"
 
 int graph_add_node_gain(struct computation_graph *graph, const char* name);
 
diff --git a/quad/src/quad_app/node_mixer.c b/quad/src/graph_blocks/node_mixer.c
similarity index 95%
rename from quad/src/quad_app/node_mixer.c
rename to quad/src/graph_blocks/node_mixer.c
index 316c1ce8218b835ee002c8c4352c97af111b318d..fe7d57f276106e7847e5c0b0c0ba0fc92f2ed862 100644
--- a/quad/src/quad_app/node_mixer.c
+++ b/quad/src/graph_blocks/node_mixer.c
@@ -34,7 +34,9 @@ const struct graph_node_type node_mixer_type = {
         .n_outputs = 4,
         .n_params = 0,
         .execute = mixer_computation,
-        .reset = reset_mixer
+        .reset = reset_mixer,
+		.state_size = 0,
+		.type_id = BLOCK_MIXER
 };
 
 int graph_add_node_mixer(struct computation_graph *graph, const char* name) {
diff --git a/quad/src/quad_app/node_mixer.h b/quad/src/graph_blocks/node_mixer.h
similarity index 94%
rename from quad/src/quad_app/node_mixer.h
rename to quad/src/graph_blocks/node_mixer.h
index ba1ec1c4901db366610506f18e41f9883a41980b..584538f0242677428632b681b2f0fe064e789abc 100644
--- a/quad/src/quad_app/node_mixer.h
+++ b/quad/src/graph_blocks/node_mixer.h
@@ -1,6 +1,7 @@
 #ifndef __NODE_MIXER_H__
 #define __NODE_MIXER_H__
 #include "computation_graph.h"
+#include "graph_blocks.h"
 
 int graph_add_node_mixer(struct computation_graph *graph, const char* name);
 
diff --git a/quad/src/computation_graph/node_mult.c b/quad/src/graph_blocks/node_mult.c
similarity index 91%
rename from quad/src/computation_graph/node_mult.c
rename to quad/src/graph_blocks/node_mult.c
index 2696719fdc83a89ae346d4dc788df693d97b2ddb..427b9e74d071b45bbd5c7ef2437647f13aeb5b5c 100644
--- a/quad/src/computation_graph/node_mult.c
+++ b/quad/src/graph_blocks/node_mult.c
@@ -17,7 +17,9 @@ const struct graph_node_type node_mult_type = {
         .n_outputs = 1,
         .n_params = 0,
         .execute = mult_nodes,
-        .reset = reset
+        .reset = reset,
+        .state_size = 0,
+        .type_id = BLOCK_MULT
 };
 
 int graph_add_node_mult(struct computation_graph *graph, const char* name) {
diff --git a/quad/src/computation_graph/node_mult.h b/quad/src/graph_blocks/node_mult.h
similarity index 93%
rename from quad/src/computation_graph/node_mult.h
rename to quad/src/graph_blocks/node_mult.h
index 9ea2bbb9fabdbc522a02f292f5294b33ad7af44c..f86f7ee0ab88c64dc1f3241615ac06d66fc3d925 100644
--- a/quad/src/computation_graph/node_mult.h
+++ b/quad/src/graph_blocks/node_mult.h
@@ -1,6 +1,7 @@
 #ifndef __NODE_MULT_H__
 #define __NODE_MULT_H__
 #include "computation_graph.h"
+#include "graph_blocks.h"
 
 int graph_add_node_mult(struct computation_graph *graph, const char* name);
 
diff --git a/quad/src/quad_app/node_pid.c b/quad/src/graph_blocks/node_pid.c
similarity index 97%
rename from quad/src/quad_app/node_pid.c
rename to quad/src/graph_blocks/node_pid.c
index 7222094577d6c4ba1f41c93f65e5bdbe00c4dc75..df6b611100aec808a8728a3fbe435ecbe5078557 100644
--- a/quad/src/quad_app/node_pid.c
+++ b/quad/src/graph_blocks/node_pid.c
@@ -90,7 +90,9 @@ const struct graph_node_type node_pid_type = {
         .n_outputs = 1,
         .n_params = 4,
         .execute = pid_computation,
-        .reset = reset_pid
+        .reset = reset_pid,
+        .state_size = sizeof(struct pid_node_state),
+        .type_id = BLOCK_PID
 };
 
 int graph_add_node_pid(struct computation_graph *graph, const char* name) {
diff --git a/quad/src/quad_app/node_pid.h b/quad/src/graph_blocks/node_pid.h
similarity index 96%
rename from quad/src/quad_app/node_pid.h
rename to quad/src/graph_blocks/node_pid.h
index 7b384bb1a233785877fc2cc79d56a8e2dd88aa10..694f7a143d5141d7bbcaf951302fee187f56ab15 100644
--- a/quad/src/quad_app/node_pid.h
+++ b/quad/src/graph_blocks/node_pid.h
@@ -1,6 +1,7 @@
 #ifndef __NODE_PID_H__
 #define __NODE_PID_H__
 #include "computation_graph.h"
+#include "graph_blocks.h"
 
 int graph_add_node_pid(struct computation_graph *graph, const char* name);
 
diff --git a/quad/src/computation_graph/node_pow.c b/quad/src/graph_blocks/node_pow.c
similarity index 94%
rename from quad/src/computation_graph/node_pow.c
rename to quad/src/graph_blocks/node_pow.c
index dbbc1d707d7833254e5a96a4dc8ba2b9c954ae4d..e4fe0f25c2dd323085110869e3f1191217914d40 100644
--- a/quad/src/computation_graph/node_pow.c
+++ b/quad/src/graph_blocks/node_pow.c
@@ -18,7 +18,8 @@ const struct graph_node_type node_pow_type = {
         .n_outputs = 1,
         .n_params = 1,
         .execute = pow_nodes,
-        .reset = reset
+        .reset = reset,
+        .state_size = 0,
 };
 
 int graph_add_node_pow(struct computation_graph *graph, const char* name) {
diff --git a/quad/src/computation_graph/node_pow.h b/quad/src/graph_blocks/node_pow.h
similarity index 100%
rename from quad/src/computation_graph/node_pow.h
rename to quad/src/graph_blocks/node_pow.h
diff --git a/quad/src/quad_app/Makefile b/quad/src/quad_app/Makefile
index 4c9cdd92ffe4ca92eb20fc183589909c23bd9406..ffe41ddcba74e67aad0dacc4b28ff9788d1034d2 100644
--- a/quad/src/quad_app/Makefile
+++ b/quad/src/quad_app/Makefile
@@ -1,6 +1,7 @@
 TOP=../..
 
 NAME = quad_app
+REQLIBS = -ltest -lcomputation_graph -lm -lqueue -lgraph_blocks -lcommands
 REQLIBS = -ltest -lcomputation_graph -lm -lqueue -lcommands
 
 include $(TOP)/library.mk
diff --git a/quad/src/quad_app/callbacks.c b/quad/src/quad_app/callbacks.c
index f9886913b5b038ec417dc48692b269f323f0cfa9..c092e20d699eb2368399f5647f2b6d38c62021a3 100644
--- a/quad/src/quad_app/callbacks.c
+++ b/quad/src/quad_app/callbacks.c
@@ -303,10 +303,21 @@ int cb_getoutput(modular_structs_t* structs, metadata_t *meta,  u8 *data, u16 le
 	return 0;
 }
 
+/*
+ * Handles a request for the list of nodes in the graph
+ * For N total nodes, returns data in the following format:
+ * |---------------------------------------------------------------------------|
+ * |  data index ||     0 - 2*N    |     2 - 3     |    4 - 5    |     6 - 7     |
+ * |---------------------------------------------------------------------------|
+ * |   parameter || Array of node  | dest input ID | src node ID | src output ID |
+ * |---------------------------------------------------------------------------|
+ * |       bytes ||       2      |       2       |      2      |       2       |
+ * |---------------------------------------------------------------------------|
+ */
 int cb_getnodes(modular_structs_t* structs, metadata_t *meta,  u8 *data, u16 length) {
-
+	return 0;
 }
 
 int cb_addnode(modular_structs_t* structs, metadata_t *meta,  u8 *data, u16 length) {
-
+	return 0;
 }
\ No newline at end of file
diff --git a/quad/src/quad_app/control_algorithm.c b/quad/src/quad_app/control_algorithm.c
index 5e1ebfd7dd227de54ab2ec80b02896b02d26694b..178cfc8472d4e22b252176691160e18808389e15 100644
--- a/quad/src/quad_app/control_algorithm.c
+++ b/quad/src/quad_app/control_algorithm.c
@@ -8,11 +8,7 @@
 // This implemented modular quadrotor software implements a PID control algorithm
 
 #include "control_algorithm.h"
-#include "node_pid.h"
-#include "node_bounds.h"
-#include "node_constant.h"
-#include "node_mixer.h"
-#include "node_add.h"
+#include "graph_blocks.h"
 #include "PID.h"
 #include "util.h"
 #include "timer.h"
@@ -43,55 +39,55 @@ int control_algorithm_init(parameter_t * ps)
     ps->graph = graph;
 
     // Create all the PID blocks
-    ps->roll_pid = graph_add_node_pid(graph, "Roll PID");
-    ps->pitch_pid = graph_add_node_pid(graph, "Pitch PID");
-    ps->yaw_pid = graph_add_node_pid(graph, "Yaw PID");
-    ps->roll_r_pid = graph_add_node_pid(graph, "Roll Rate PID");
-    ps->pitch_r_pid = graph_add_node_pid(graph, "Pitch Rate PID");
-    ps->yaw_r_pid = graph_add_node_pid(graph, "Yaw Rate PID");
-    ps->x_pos_pid = graph_add_node_pid(graph, "X pos PID");
-    ps->y_pos_pid = graph_add_node_pid(graph, "Y pos PID");
-    ps->alt_pid = graph_add_node_pid(graph, "Altitude PID");
-    ps->x_set = graph_add_node_const(graph, "X Setpoint"); // ID 9
-    ps->y_set = graph_add_node_const(graph, "Y Setpoint");
-    ps->alt_set = graph_add_node_const(graph, "Alt Setpoint");
-    ps->yaw_set = graph_add_node_const(graph, "Yaw Setpoint");
-    ps->throttle_trim = graph_add_node_const(graph, "Throttle trim");
-    ps->throttle_trim_add = graph_add_node_add(graph, "T trim add");
+    ps->roll_pid = graph_add_defined_block(graph, BLOCK_PID, "Roll PID");
+    ps->pitch_pid = graph_add_defined_block(graph, BLOCK_PID, "Pitch PID");
+    ps->yaw_pid = graph_add_defined_block(graph, BLOCK_PID, "Yaw PID");
+    ps->roll_r_pid = graph_add_defined_block(graph, BLOCK_PID, "Roll Rate PID");
+    ps->pitch_r_pid = graph_add_defined_block(graph, BLOCK_PID, "Pitch Rate PID");
+    ps->yaw_r_pid = graph_add_defined_block(graph, BLOCK_PID, "Yaw Rate PID");
+    ps->x_pos_pid = graph_add_defined_block(graph, BLOCK_PID, "X pos PID");
+    ps->y_pos_pid = graph_add_defined_block(graph, BLOCK_PID, "Y pos PID");
+    ps->alt_pid = graph_add_defined_block(graph, BLOCK_PID, "Altitude PID");
+    ps->x_set = graph_add_defined_block(graph, BLOCK_CONSTANT, "X Setpoint"); // ID 9
+    ps->y_set = graph_add_defined_block(graph, BLOCK_CONSTANT, "Y Setpoint");
+    ps->alt_set = graph_add_defined_block(graph, BLOCK_CONSTANT, "Alt Setpoint");
+    ps->yaw_set = graph_add_defined_block(graph, BLOCK_CONSTANT, "Yaw Setpoint");
+    ps->throttle_trim = graph_add_defined_block(graph, BLOCK_CONSTANT, "Throttle trim");
+    ps->throttle_trim_add = graph_add_defined_block(graph, BLOCK_ADD, "T trim add");
 
     // Create blocks for sensor inputs
-    ps->cur_pitch = graph_add_node_const(graph, "Pitch"); // ID 20
-    ps->cur_roll = graph_add_node_const(graph, "Roll");
-    ps->cur_yaw = graph_add_node_const(graph, "Yaw");
+    ps->cur_pitch = graph_add_defined_block(graph, BLOCK_CONSTANT, "Pitch"); // ID 20
+    ps->cur_roll = graph_add_defined_block(graph, BLOCK_CONSTANT, "Roll");
+    ps->cur_yaw = graph_add_defined_block(graph, BLOCK_CONSTANT, "Yaw");
 	// Yaw angular velocity PID
     // theta_dot is the angular velocity about the y-axis
     // phi_dot is the angular velocity about the x-axis
 	// psi_dot is the angular velocity about the z-axis
 	// These are calculated from using the gimbal equations
-    ps->theta_dot = graph_add_node_const(graph, "dTheta");
-    ps->phi_dot = graph_add_node_const(graph, "dPhi");
-    ps->psi_dot = graph_add_node_const(graph, "dPsi");
-    ps->clamp_d_pwmP = graph_add_node_bounds(graph, "P PWM Clamp");
-    ps->clamp_d_pwmR = graph_add_node_bounds(graph, "R PWM Clamp");
-    ps->clamp_d_pwmY = graph_add_node_bounds(graph, "Y PWM Clamp");
+    ps->theta_dot = graph_add_defined_block(graph, BLOCK_CONSTANT, "dTheta");
+    ps->phi_dot = graph_add_defined_block(graph, BLOCK_CONSTANT, "dPhi");
+    ps->psi_dot = graph_add_defined_block(graph, BLOCK_CONSTANT, "dPsi");
+    ps->clamp_d_pwmP = graph_add_defined_block(graph, BLOCK_BOUNDS, "P PWM Clamp");
+    ps->clamp_d_pwmR = graph_add_defined_block(graph, BLOCK_BOUNDS, "R PWM Clamp");
+    ps->clamp_d_pwmY = graph_add_defined_block(graph, BLOCK_BOUNDS, "Y PWM Clamp");
 
     // Create blocks for VRPN data
-    ps->vrpn_x = graph_add_node_const(graph, "VRPN X");
-    ps->vrpn_y = graph_add_node_const(graph, "VRPN Y");
-    ps->vrpn_alt = graph_add_node_const(graph, "VRPN Alt");
-    ps->vrpn_pitch = graph_add_node_const(graph, "VRPN Pitch");
-    ps->vrpn_roll = graph_add_node_const(graph, "VRPN Roll");
+    ps->vrpn_x = graph_add_defined_block(graph, BLOCK_CONSTANT, "VRPN X");
+    ps->vrpn_y = graph_add_defined_block(graph, BLOCK_CONSTANT, "VRPN Y");
+    ps->vrpn_alt = graph_add_defined_block(graph, BLOCK_CONSTANT, "VRPN Alt");
+    ps->vrpn_pitch = graph_add_defined_block(graph, BLOCK_CONSTANT, "VRPN Pitch");
+    ps->vrpn_roll = graph_add_defined_block(graph, BLOCK_CONSTANT, "VRPN Roll");
 
     // Create blocks for RC controller
-    ps->rc_pitch = graph_add_node_const(graph, "RC Pitch");
-    ps->rc_roll = graph_add_node_const(graph, "RC Roll");
-    ps->rc_yaw = graph_add_node_const(graph, "RC Yaw");
-    ps->rc_throttle = graph_add_node_const(graph, "RC Throttle");
+    ps->rc_pitch = graph_add_defined_block(graph, BLOCK_CONSTANT, "RC Pitch");
+    ps->rc_roll = graph_add_defined_block(graph, BLOCK_CONSTANT, "RC Roll");
+    ps->rc_yaw = graph_add_defined_block(graph, BLOCK_CONSTANT, "RC Yaw");
+    ps->rc_throttle = graph_add_defined_block(graph, BLOCK_CONSTANT, "RC Throttle");
 
-    ps->mixer = graph_add_node_mixer(graph, "Signal Mixer");
+    ps->mixer = graph_add_defined_block(graph, BLOCK_MIXER, "Signal Mixer");
 
-    ps->angle_time = graph_add_node_const(graph, "Ts_IMU");
-    ps->pos_time = graph_add_node_const(graph, "Ts_VRPN");
+    ps->angle_time = graph_add_defined_block(graph, BLOCK_CONSTANT, "Ts_IMU");
+    ps->pos_time = graph_add_defined_block(graph, BLOCK_CONSTANT, "Ts_VRPN");
 
     // Connect pitch PID chain
     graph_set_source(graph, ps->pitch_r_pid, PID_SETPOINT, ps->pitch_pid, PID_CORRECTION);
diff --git a/quad/src/quad_app/log_data.c b/quad/src/quad_app/log_data.c
index d7a361dfe69963339efd502e89cf697446bfe5eb..61c9bdf997a348b64528bf91174a24fcc238f459 100644
--- a/quad/src/quad_app/log_data.c
+++ b/quad/src/quad_app/log_data.c
@@ -14,9 +14,7 @@
 #include "log_data.h"
 #include "communication.h"
 #include "computation_graph.h"
-#include "node_pid.h"
-#include "node_constant.h"
-#include "node_mixer.h"
+#include "graph_blocks.h"
 
 // Current index of the log array
 int arrayIndex = 0;
diff --git a/quad/src/virt_quad/Makefile b/quad/src/virt_quad/Makefile
index 47cebc494626a024de63f93c15480f5e4c3ff5a4..3626790b07efec7ea75a039491b6078a8c6918df 100644
--- a/quad/src/virt_quad/Makefile
+++ b/quad/src/virt_quad/Makefile
@@ -1,6 +1,6 @@
 TOP=../..
 
 NAME = virt_quad
-REQLIBS = -lquad_app -lcomputation_graph -lm -lcommands
+REQLIBS = -lquad_app -lcomputation_graph -lm -lcommands -lgraph_blocks
 
 include $(TOP)/executable.mk
diff --git a/quad/src/virt_quad/hw_impl_unix_uart.c b/quad/src/virt_quad/hw_impl_unix_uart.c
index f4787939832cd38d781643df1c9cd9d801f311b3..6328eb197729375022eb2d9f691a5d85fe31ce23 100644
--- a/quad/src/virt_quad/hw_impl_unix_uart.c
+++ b/quad/src/virt_quad/hw_impl_unix_uart.c
@@ -1,13 +1,63 @@
 #include "hw_impl_unix.h"
+#include <sys/types.h>       
+#include <sys/socket.h>
+#include <stdio.h>
+#include <sys/un.h>
+#include <err.h>
+#include <netinet/in.h>
+
+#define DEFAULT_SOCKET "../../groundStation/virtquad.socket"
+#define SOCKET_ENV "VIRT_QUAD_SOCKET"
+
+static int backendSocket;
+static int sendSocket;
 
 int unix_uart_reset(struct UARTDriver *self) {
+
+
+	char * backend_socket_path = DEFAULT_SOCKET;
+	if (getenv(SOCKET_ENV)) {
+	backend_socket_path = getenv(SOCKET_ENV);
+	}
+	/* Unlink if it exists */
+	unlink(backend_socket_path);
+	printf("using socket at '%s'\n", backend_socket_path);
+
+	/* Create socket */
+	backendSocket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
+
+
+	/* Create sockaddr and bind */
+	struct sockaddr_un sa;
+	sa.sun_family = AF_UNIX;
+	strncpy(sa.sun_path, backend_socket_path, 107);
+	sa.sun_path[107] = '\0';
+	if (bind(backendSocket, (struct sockaddr *) &sa, sizeof(sa))) {
+		err(-1, "bind");
+	}
+
+	/* Listen */
+	if (listen(backendSocket, 1)) {
+		err(-1, "listen");
+	}
+
+	while (1) {
+		sendSocket = accept(backendSocket, NULL, NULL);
+		if (sendSocket > 0)
+			break;
+	}
+
+	printf(" accpet() returned with %d\n", sendSocket);
   return 0;
 }
 
 int unix_uart_write(struct UARTDriver *self, unsigned char c) {
-  return 0;
+	printf("sending %c\n", c);
+	return send(sendSocket, &c, 1, 0);
 }
 
 int unix_uart_read(struct UARTDriver *self, unsigned char *c) {
-  return 0;
+	int bytes = read(sendSocket, c, 1);
+	printf("read in %d byte [%x], msg=%d\n", bytes, *c, self->msg);
+	return bytes;
 }
diff --git a/quad/test_logging/Makefile b/quad/test_logging/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d30eb0102cea878e910d440437f4c185e2562b30
--- /dev/null
+++ b/quad/test_logging/Makefile
@@ -0,0 +1,3 @@
+CC=gcc
+test: test.c
+	$(CC) -o test_log -I. -I../src/quad_app -I../src/computation_graph test.c ../src/quad_app/*.c ../src/computation_graph/*.c -lm
diff --git a/quad/test_logging/log.txt b/quad/test_logging/log.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c66e5152c66693e82bc287674ba3359ab6710dd4
--- /dev/null
+++ b/quad/test_logging/log.txt
@@ -0,0 +1,7 @@
+# MicroCART On-board Quad Log
+# Sample size: 3
+time	accel_x	accel_y	accel_z	gyro_x	gyro_y	gyro_z	Altitude PID_Correction	X pos PID_Correction	Y pos PID_Correction	Pitch PID_Correction	Roll PID_Correction	Yaw PID_Correction	Pitch Rate PID_Correction	Roll Rate PID_Correction	Yaw Rate PID_Correction	Pitch_Constant	Roll_Constant	Yaw_Constant	VRPN X_Constant	VRPN Y_Constant	VRPN Alt_Constant	VRPN Pitch_Constant	VRPN Roll_Constant	X Setpoint_Constant	Y Setpoint_Constant	Alt Setpoint_Constant	Yaw Setpoint_Constant	Signal Mixer_PWM 0	Signal Mixer_PWM 1	Signal Mixer_PWM 2	Signal Mixer_PWM 3
+s	G	G	G	rad/s	rad/s	rad/s	10ns_dutycycle	rad	rad	rad/s	rad/s	rad/s	10ns_dutycycle	10ns_dutycycle	10ns_dutycycle	rad	rad	rad	m	m	m	rad	rad	m	m	m	rad	10ns_dutycycle	10ns_dutycycle	10ns_dutycycle	10ns_dutycycle
+0.000000	0.000000	0.000000	0.000000	0.000000	4722366482869645213696.000000	-nan	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000
+0.000000	0.000000	0.000000	0.000000	0.000000	4722366482869645213696.000000	-nan	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000
+0.000000	0.000000	0.000000	0.000000	0.000000	4722366482869645213696.000000	-nan	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000	0.000000
diff --git a/quad/test_logging/test.c b/quad/test_logging/test.c
new file mode 100644
index 0000000000000000000000000000000000000000..7fd26a97d187f96630e209fa04f5364fdbdcef58
--- /dev/null
+++ b/quad/test_logging/test.c
@@ -0,0 +1,22 @@
+#include <stddef.h>
+#include "type_def.h"
+#include "log_data.h"
+#include "control_algorithm.h"
+
+int zybo_uart_write(struct UARTDriver *self, unsigned char c) {
+    printf("%c", c);
+    return 0;
+}
+
+
+int main() {
+    modular_structs_t structs;
+    structs.hardware_struct.uart.write = zybo_uart_write;
+    control_algorithm_init(&(structs.parameter_struct));
+	initialize_logging(&structs.log_struct, &structs.parameter_struct);
+    log_data(&(structs.log_struct), &(structs.parameter_struct));
+    log_data(&(structs.log_struct), &(structs.parameter_struct));
+    log_data(&(structs.log_struct), &(structs.parameter_struct));
+    printLogging(&structs.hardware_struct, &(structs.log_struct), &(structs.parameter_struct));
+    return 0;
+}
diff --git a/quad/test_logging/test_log b/quad/test_logging/test_log
new file mode 100644
index 0000000000000000000000000000000000000000..e9c0b45a27eb1eb96d051a7ec6738d3c8ff5adba
Binary files /dev/null and b/quad/test_logging/test_log differ