From 2d7e3f18ad6d57b615023eb0c79b5b71725b523c Mon Sep 17 00:00:00 2001 From: David Wehr <dawehr@iastate.edu> Date: Fri, 24 Mar 2017 21:37:06 -0500 Subject: [PATCH] Added type_id to node types. Linked graph_blocks to virtual quad. Fixed issues with commands array --- .../uart_stress_tests.cpython-36.pyc | Bin 0 -> 4778 bytes quad/src/commands/commands.c | 15 +++--------- .../src/computation_graph/computation_graph.h | 1 + quad/src/graph_blocks/graph_blocks.h | 6 ++++- quad/src/graph_blocks/node_accumulator.c | 3 ++- quad/src/graph_blocks/node_accumulator.h | 1 + quad/src/graph_blocks/node_add.c | 3 ++- quad/src/graph_blocks/node_add.h | 1 + quad/src/graph_blocks/node_bounds.c | 3 ++- quad/src/graph_blocks/node_bounds.h | 1 + quad/src/graph_blocks/node_constant.c | 3 ++- quad/src/graph_blocks/node_constant.h | 1 + quad/src/graph_blocks/node_gain.c | 3 ++- quad/src/graph_blocks/node_gain.h | 1 + quad/src/graph_blocks/node_mixer.c | 3 ++- quad/src/graph_blocks/node_mixer.h | 1 + quad/src/graph_blocks/node_mult.c | 3 ++- quad/src/graph_blocks/node_mult.h | 1 + quad/src/graph_blocks/node_pid.c | 3 ++- quad/src/graph_blocks/node_pid.h | 1 + quad/src/graph_blocks/node_pow.c | 2 +- quad/src/virt_quad/Makefile | 2 +- quad/test_logging/Makefile | 3 +++ quad/test_logging/log.txt | 7 ++++++ quad/test_logging/test.c | 22 ++++++++++++++++++ quad/test_logging/test_log | Bin 0 -> 56535 bytes 26 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 quad/scripts/__pycache__/uart_stress_tests.cpython-36.pyc create mode 100644 quad/test_logging/Makefile create mode 100644 quad/test_logging/log.txt create mode 100644 quad/test_logging/test.c create mode 100644 quad/test_logging/test_log 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 GIT binary patch literal 4778 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 Xp9!XdB3f?-CcKr*9Fpu={7d|QTUQ}I literal 0 HcmV?d00001 diff --git a/quad/src/commands/commands.c b/quad/src/commands/commands.c index 9111f1050..14ae7c58c 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/computation_graph.h b/quad/src/computation_graph/computation_graph.h index 8449a903d..e997aa7ab 100644 --- a/quad/src/computation_graph/computation_graph.h +++ b/quad/src/computation_graph/computation_graph.h @@ -34,6 +34,7 @@ struct graph_node_type { 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/graph_blocks/graph_blocks.h b/quad/src/graph_blocks/graph_blocks.h index 7db4f7f21..cc822b242 100644 --- a/quad/src/graph_blocks/graph_blocks.h +++ b/quad/src/graph_blocks/graph_blocks.h @@ -1,3 +1,6 @@ +#ifndef __GRAPH_BLOCKS_H__ +#define __GRAPH_BLOCKS_H__ + #include "computation_graph.h" #include "node_constant.h" #include "node_add.h" @@ -48,4 +51,5 @@ 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); \ No newline at end of file +int graph_add_defined_block(struct computation_graph* graph, int type_id, const char* name); +#endif // __GRAPH_BLOCKS_H__ diff --git a/quad/src/graph_blocks/node_accumulator.c b/quad/src/graph_blocks/node_accumulator.c index 4d02ab374..10b968737 100644 --- a/quad/src/graph_blocks/node_accumulator.c +++ b/quad/src/graph_blocks/node_accumulator.c @@ -28,7 +28,8 @@ const struct graph_node_type node_accum_type = { .n_params = 0, .execute = accum_nodes, .reset = reset, - .state_size = sizeof(struct accum_state) + .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/graph_blocks/node_accumulator.h b/quad/src/graph_blocks/node_accumulator.h index a392a9db2..43301d667 100644 --- a/quad/src/graph_blocks/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/graph_blocks/node_add.c b/quad/src/graph_blocks/node_add.c index db6692856..25a780a32 100644 --- a/quad/src/graph_blocks/node_add.c +++ b/quad/src/graph_blocks/node_add.c @@ -18,7 +18,8 @@ const struct graph_node_type node_add_type = { .n_params = 0, .execute = add_nodes, .reset = reset, - .state_size = 0 + .state_size = 0, + .type_id = BLOCK_ADD }; int graph_add_node_add(struct computation_graph *graph, const char* name) { diff --git a/quad/src/graph_blocks/node_add.h b/quad/src/graph_blocks/node_add.h index 390e3d229..34b812363 100644 --- a/quad/src/graph_blocks/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/graph_blocks/node_bounds.c b/quad/src/graph_blocks/node_bounds.c index cbcad4a13..d1fe26431 100644 --- a/quad/src/graph_blocks/node_bounds.c +++ b/quad/src/graph_blocks/node_bounds.c @@ -26,7 +26,8 @@ const struct graph_node_type node_bounds_type = { .n_params = 2, .execute = bounds_computation, .reset = reset_bounds, - .state_size = 0 + .state_size = 0, + .type_id = BLOCK_BOUNDS }; int graph_add_node_bounds(struct computation_graph *graph, const char* name) { diff --git a/quad/src/graph_blocks/node_bounds.h b/quad/src/graph_blocks/node_bounds.h index 4c3b93256..7eea073fa 100644 --- a/quad/src/graph_blocks/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/graph_blocks/node_constant.c b/quad/src/graph_blocks/node_constant.c index e3ca2188c..8bd406ad9 100644 --- a/quad/src/graph_blocks/node_constant.c +++ b/quad/src/graph_blocks/node_constant.c @@ -18,7 +18,8 @@ const struct graph_node_type node_const_type = { .n_params = 1, .execute = output_const, .reset = reset, - .state_size = 0 + .state_size = 0, + .type_id = BLOCK_CONSTANT }; int graph_add_node_const(struct computation_graph *graph, const char* name) { diff --git a/quad/src/graph_blocks/node_constant.h b/quad/src/graph_blocks/node_constant.h index c67ac6e05..417e92da1 100644 --- a/quad/src/graph_blocks/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/graph_blocks/node_gain.c b/quad/src/graph_blocks/node_gain.c index f16eb2b2a..3c0ac77ae 100644 --- a/quad/src/graph_blocks/node_gain.c +++ b/quad/src/graph_blocks/node_gain.c @@ -18,7 +18,8 @@ const struct graph_node_type node_gain_type = { .n_params = 1, .execute = scale_nodes, .reset = reset, - .state_size = 0 + .state_size = 0, + .type_id = BLOCK_GAIN }; int graph_add_node_gain(struct computation_graph *graph, const char* name) { diff --git a/quad/src/graph_blocks/node_gain.h b/quad/src/graph_blocks/node_gain.h index 408924498..4a1a3322f 100644 --- a/quad/src/graph_blocks/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/graph_blocks/node_mixer.c b/quad/src/graph_blocks/node_mixer.c index d7df8cd3a..fe7d57f27 100644 --- a/quad/src/graph_blocks/node_mixer.c +++ b/quad/src/graph_blocks/node_mixer.c @@ -35,7 +35,8 @@ const struct graph_node_type node_mixer_type = { .n_params = 0, .execute = mixer_computation, .reset = reset_mixer, - .state_size = 0 + .state_size = 0, + .type_id = BLOCK_MIXER }; int graph_add_node_mixer(struct computation_graph *graph, const char* name) { diff --git a/quad/src/graph_blocks/node_mixer.h b/quad/src/graph_blocks/node_mixer.h index ba1ec1c49..584538f02 100644 --- a/quad/src/graph_blocks/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/graph_blocks/node_mult.c b/quad/src/graph_blocks/node_mult.c index ba797a5c3..427b9e74d 100644 --- a/quad/src/graph_blocks/node_mult.c +++ b/quad/src/graph_blocks/node_mult.c @@ -18,7 +18,8 @@ const struct graph_node_type node_mult_type = { .n_params = 0, .execute = mult_nodes, .reset = reset, - .state_size = 0 + .state_size = 0, + .type_id = BLOCK_MULT }; int graph_add_node_mult(struct computation_graph *graph, const char* name) { diff --git a/quad/src/graph_blocks/node_mult.h b/quad/src/graph_blocks/node_mult.h index 9ea2bbb9f..f86f7ee0a 100644 --- a/quad/src/graph_blocks/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/graph_blocks/node_pid.c b/quad/src/graph_blocks/node_pid.c index 0dc6eed41..df6b61110 100644 --- a/quad/src/graph_blocks/node_pid.c +++ b/quad/src/graph_blocks/node_pid.c @@ -91,7 +91,8 @@ const struct graph_node_type node_pid_type = { .n_params = 4, .execute = pid_computation, .reset = reset_pid, - .state_size = sizeof(struct pid_node_state) + .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/graph_blocks/node_pid.h b/quad/src/graph_blocks/node_pid.h index 7b384bb1a..694f7a143 100644 --- a/quad/src/graph_blocks/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/graph_blocks/node_pow.c b/quad/src/graph_blocks/node_pow.c index 65af8e45d..e4fe0f25c 100644 --- a/quad/src/graph_blocks/node_pow.c +++ b/quad/src/graph_blocks/node_pow.c @@ -19,7 +19,7 @@ const struct graph_node_type node_pow_type = { .n_params = 1, .execute = pow_nodes, .reset = reset, - .state_size = 0 + .state_size = 0, }; int graph_add_node_pow(struct computation_graph *graph, const char* name) { diff --git a/quad/src/virt_quad/Makefile b/quad/src/virt_quad/Makefile index 47cebc494..3626790b0 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/test_logging/Makefile b/quad/test_logging/Makefile new file mode 100644 index 000000000..d30eb0102 --- /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 000000000..c66e5152c --- /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 000000000..7fd26a97d --- /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 GIT binary patch literal 56535 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 F{~xc`NyPvF literal 0 HcmV?d00001 -- GitLab