Skip to content

Commit 5856075

Browse files
authored
Merge branch 'main' into alex/clang-format
2 parents d747833 + aef5513 commit 5856075

8 files changed

Lines changed: 193 additions & 17 deletions

File tree

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
**/build/
22
.DS_Store
33
twister-out*
4-
.cache
4+
.cache
5+
6+
data/
7+
*.jar
8+
*.ork

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,29 @@ TODO
3434
- Zephyr Documentation: https://docs.zephyrproject.org/latest/index.html
3535
- Highly recommend watching this tutorial series (Videos 9, 10, and 11 shouldnt be necessary for this project): https://www.youtube.com/playlist?list=PLEBQazB0HUyTmK2zdwhaf8bLwuEaDH-52
3636

37+
## Integration Testing
38+
### Zephyr's Native Sim
39+
#### Getting the data
40+
1. Follow the installation instruction for OpenRocket: https://openrocket.readthedocs.io/en/latest/setup/installation.html
41+
2. Boot up OpenRocket and load the .ork file
42+
3. Under Flight Simulations, open a previous simulation by double clicking on the row
43+
4. Under Export Data, click "select all" and ensure that only the "Include field descriptions" option is checked.
44+
5. Click Export and save your csv file
45+
46+
#### Running the integration test
47+
1. Ensure you're in the virtual environment using inside `FALCON/`:
48+
- `source .venv/bin/activate` (MacOS/Linux) or `.venv\Scripts\activate.bat` (Windows)
49+
2. Build FALCON using Zephyr's built in native_sim board:
50+
- `west build -b native_sim/native/64 app/apps/rockets/cloudburst -- -DDTC_OVERLAY_FILE="$(pwd)/boards/native_sim.overlay" -DDATA_FILE="$(pwd)/<PATH>/<DATA_FILE>.csv"`
51+
- Replace `PATH` and `DATA_FILE` with the location and name of your OpenRocket csv file
52+
3. Run the integration test:
53+
- For a realtime test, use `west build -t run`
54+
- To run at the maximum speed, use `./app/build/zephyr/zephyr.exe --no-rt`
55+
- To run at a custom speed, use `./app/build/zephyr/zephyr.exe --rt-ratio=2`
56+
57+
### QEMU (WIP)
58+
59+
3760
## Debugging
3861
### Terminal debugging:
3962
*Should work out of the box provided your zephyr environment is set up correctly*

boards/native_sim.overlay

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,27 @@
3535
sector-count = <2048>; /* 1 MB */
3636
};
3737

38+
spi_pyro: spi@40000000 {
39+
compatible = "vnd,spi";
40+
reg = <0x40000000 0x100>;
41+
#address-cells = <1>;
42+
#size-cells = <0>;
43+
status = "okay";
44+
45+
sim_pyro0: sim_pyro_0@0 {
46+
compatible = "zephyr,sim-pyro";
47+
reg = <0>;
48+
spi-max-frequency = <1000000>;
49+
status = "okay";
50+
};
51+
};
52+
3853
aliases {
3954
baro0 = &sim_baro0;
4055
baro1 = &sim_baro1;
4156
accel0 = &sim_accel0;
4257
gyro0 = &sim_gyro0;
58+
pyro0 = &sim_pyro0;
4359
sdmmc1 = &sim_sdmmc1;
4460
ramdisk0 = &sim_ramdisk0;
4561
};

drivers/sensor/sim_baro/sim_baro.c

Lines changed: 123 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,62 @@ LOG_MODULE_REGISTER(sim_baro, LOG_LEVEL_INF);
1818
#define MAX_LINE_LENGTH 512
1919
#define MAX_CSV_ROWS 10000
2020

21+
// OpenRocket CSV Column definitions
22+
#define CSV_COL_TIMESTAMP 0
23+
#define CSV_COL_ALTITUDE 1
24+
#define CSV_COL_VERTICAL_VELO 2
25+
#define CSV_COL_VERTICAL_ACCEL 3
26+
#define CSV_COL_TOTAL_VELO 4
27+
#define CSV_COL_TOTAL_ACCEL 5
28+
#define CSV_COL_POS_EAST 6
29+
#define CSV_COL_POS_NORTH 7
30+
#define CSV_COL_GPS_LAT_DIST 8
31+
#define CSV_COL_GPS_LAT_DIR 9
32+
#define CSV_COL_GPS_LAT_VELO 10
33+
#define CSV_COL_GPS_LAT_ACCEL 11
34+
#define CSV_COL_LATITUDE 12
35+
#define CSV_COL_LONGITUDE 13
36+
#define CSV_COL_GRAVITY 14
37+
#define CSV_COL_ANGLE_ATTACK 15
38+
#define CSV_COL_ROLL_RATE 16
39+
#define CSV_COL_PITCH_RATE 17
40+
#define CSV_COL_YAW_RATE 18
41+
#define CSV_COL_MASS 19
42+
#define CSV_COL_MOTOR_MASS 20
43+
#define CSV_COL_LONG_MMOI 21
44+
#define CSV_COL_ROT_MMOI 22
45+
#define CSV_COL_CP_LOCATION 23
46+
#define CSV_COL_CG_LOCATION 24
47+
#define CSV_COL_STABILITY 25
48+
#define CSV_COL_MACH_NUMBER 26
49+
#define CSV_COL_REYNOLDS_NUMBER 27
50+
#define CSV_COL_THRUST 28
51+
#define CSV_COL_DRAG 29
52+
#define CSV_COL_DRAG_COEFF 30
53+
#define CSV_COL_AXIAL_DRAG_COEFF 31
54+
#define CSV_COL_FRIC_DRAG_COEFF 32
55+
#define CSV_COL_PRESSURE_DRAG_COEFF 33
56+
#define CSV_COL_BASE_DRAG_COEFF 34
57+
#define CSV_COL_NORM_FORCE_COEFF 35
58+
#define CSV_COL_PITCH_MOM_COEFF 36
59+
#define CSV_COL_YAW_MOM_COEFF 37
60+
#define CSV_COL_SIDE_FORCE_COEFF 38
61+
#define CSV_COL_ROLL_MOM_COEFF 39
62+
#define CSV_COL_ROLL_FORCING_COEFF 40
63+
#define CSV_COL_ROLL_DAMPING_COEFF 41
64+
#define CSV_COL_PITCH_DAMPING_COEFF 42
65+
#define CSV_COL_CORIOLIS_ACCEL 43
66+
#define CSV_COL_REF_LENGTH 44
67+
#define CSV_COL_REF_AREA 45
68+
#define CSV_COL_VERTICAL_ORIENT 46
69+
#define CSV_COL_LATERAL_ORIENT 47
70+
#define CSV_COL_WIND_SPEED 48
71+
#define CSV_COL_AIR_TEMP 49
72+
#define CSV_COL_AIR_PRESSURE 50
73+
#define CSV_COL_SPEED_OF_SOUND 51
74+
#define CSV_COL_SIM_TIMESTEP 52
75+
#define CSV_COL_COMPUTATION_TIME 53
76+
2177
struct csv_row {
2278
int64_t timestamp_ms;
2379
float pressure_mbar; // mbar = hPa
@@ -44,30 +100,81 @@ struct sim_baro_data {
44100
uint32_t sample_count;
45101
};
46102

47-
static int parse_csv_line(const char *line, struct csv_row *row)
48-
{
49-
int64_t timestamp;
50-
float altitude, baseline, pressure, temperature;
51-
int parsed;
52103

53-
// Read first 6 fields (we ignore the rest)
54-
// Format: Timestamp (ms),State,Altitude (m),Baseline altitude (m),Pressure (mbar),Barom. Temp
55-
// (0.01 C),...
56-
parsed = sscanf(line, "%lld,%*[^,],%f,%f,%f,%f", &timestamp, &altitude, &baseline, &pressure,
57-
&temperature);
58104

59-
if (parsed != 5) {
60-
return -1;
105+
// Helper to get Nth field from CSV line
106+
static const char* get_csv_field(const char *line, int field_index, char *buffer, size_t buf_size)
107+
{
108+
const char *start = line;
109+
const char *end;
110+
int current_field = 0;
111+
112+
// Skip to the desired field
113+
while (current_field < field_index && *start) {
114+
if (*start == ',') {
115+
current_field++;
116+
}
117+
start++;
118+
}
119+
120+
if (current_field != field_index) {
121+
return NULL; // Field not found
122+
}
123+
124+
// Find the end of this field
125+
end = start;
126+
while (*end && *end != ',' && *end != '\n' && *end != '\r') {
127+
end++;
128+
}
129+
130+
// Copy to buffer
131+
size_t len = end - start;
132+
if (len >= buf_size) {
133+
len = buf_size - 1;
61134
}
135+
136+
strncpy(buffer, start, len);
137+
buffer[len] = '\0';
138+
139+
return buffer;
140+
}
141+
142+
143+
144+
// Helper macro to extract and parse a field
145+
#define GET_CSV_INT64(line, col, dest) do { \
146+
char _buf[64]; \
147+
if (!get_csv_field(line, col, _buf, sizeof(_buf))) return -1; \
148+
dest = atoll(_buf); \
149+
} while(0)
62150

63-
row->timestamp_ms = timestamp;
64-
row->altitude_m = altitude;
65-
row->pressure_mbar = pressure / 100.0f; // Convert from cmbar to mbar (hPa)
66-
row->temperature_c = temperature / 100.0f; // Convert from centi-°C to °C
151+
// Helper macro to extract and parse a field
152+
#define GET_CSV_FLOAT(line, col, dest) do { \
153+
char _buf[64]; \
154+
if (!get_csv_field(line, col, _buf, sizeof(_buf))) return -1; \
155+
dest = atof(_buf); \
156+
} while(0)
67157

158+
static int parse_csv_line(const char *line, struct csv_row *row)
159+
{
160+
float pressure_raw, temp_raw, timestamp_raw, altitude_raw;
161+
162+
GET_CSV_FLOAT(line, CSV_COL_TIMESTAMP, timestamp_raw);
163+
GET_CSV_FLOAT(line, CSV_COL_ALTITUDE, altitude_raw);
164+
GET_CSV_FLOAT(line, CSV_COL_AIR_PRESSURE, pressure_raw);
165+
GET_CSV_FLOAT(line, CSV_COL_AIR_TEMP, temp_raw);
166+
167+
// Apply unit conversions
168+
row->timestamp_ms = timestamp_raw * 1000.0f; // Convert from seconds to milliseconds
169+
row->altitude_m = altitude_raw;
170+
row->pressure_mbar = pressure_raw; // mbar = hPa
171+
row->temperature_c = temp_raw;
172+
68173
return 0;
69174
}
70175

176+
177+
71178
static int load_csv_data(struct sim_baro_data *data)
72179
{
73180
LOG_INF("═══════════════════════════════════════════════");
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
zephyr_library()
2+
zephyr_library_sources_ifdef(CONFIG_SIM_PYRO sim_pyro.c)

drivers/sensor/sim_pyro/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
config SIM_PYRO
2+
bool "Simulated Pyro Board"
3+
depends on DT_HAS_ZEPHYR_SIM_PYRO_ENABLED

drivers/sensor/sim_pyro/sim_pyro.c

Whitespace-only changes.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
description: Simulated Pyro board for native_sim
2+
compatible: "zephyr,sim-pyro"
3+
include: [sensor-device.yaml, spi-device.yaml]
4+
5+
properties:
6+
spi-max-frequency:
7+
type: int
8+
required: true
9+
description: Maximum SPI frequency in Hz
10+
11+
duplex:
12+
type: int
13+
description: SPI duplex mode (full-duplex, half-duplex, etc.)
14+
15+
frame-format:
16+
type: int
17+
description: SPI frame format (Motorola, TI, etc.)
18+
19+
spi-interframe-delay-ns:
20+
type: int
21+
description: Inter-frame delay in nanoseconds

0 commit comments

Comments
 (0)