zscilib C Library

repository·master·Indexed 41 days ago

https://github.com/zephyrproject-rtos/zscilib

A C library for scientific computing, data analysis, and data manipulation on resource-constrained embedded hardware. It provides vector and matrix operations (including SVD and pseudoinverse), motion and orientation APIs (Quaternions, AHRS, and sensor fusion), and colorimetry conversions. Designed for use with Zephyr RTOS or as a standalone library, it includes ARM Thumb/Thumb-2 assembly optimizations for Cortex-M devices.

Tokens
13.2K
Snippets
45
Records
77
Agent score
49%

What's inside zscilib

  1. Overview of the Orientation API Test sample

    master

    The Orientation API Test sample is a demonstration of the zscilib orientation capabilities. It shows how to process raw sensor data through the following pipeline:

    1. Input: Raw accelerometer, magnetometer, and gyroscope data.
    2. Calibration: Applying calibration to the raw sensor inputs.
    3. Sensor Fusion: Feeding the calibrated data into a sensor fusion algorithm to determine orientation.
  2. SVD and Pseudoinverse functionality in zscilib

    master

    The standalone example demonstrates two core mathematical capabilities of the library:

    1. Singular Value Decomposition (SVD): Uses the zsl_mtx_svd function to calculate the SVD of an input matrix. The results consist of $U$, $\Sigma$, and $V^T$ matrices, such that $\text{input} = U \cdot \Sigma \cdot V^T$.
    2. Moore-Penrose Pseudoinverse: Uses the zsl_mtx_pinv function to calculate the pseudoinverse of a matrix (e.g., converting an $18 \times 3$ matrix into a $3 \times 18$ matrix).
  3. Planned Features in zscilib

    master

    The following features are planned for future releases of zscilib:

    Scalar Operations

    • Fast trigonometry approximations

    Digital Signal Processing (v0.3.0)

    • Simple moving average filter
    • Windowed moving average filter
    • Weighted moving average filter
    • Basic IIR and FIR-type filters and helper functions

    Spectrometry

    • Conversion between radiometric and photometric units
    • Radiometric data to lux
    • Radiometric data to CCT/Duv
    • Spectral analysis

    Calibration

    • Offset management
    • Correlation matrix generation
    • Non-linear compensation
  4. Formulate ARM Mnemonics with Modifiers

    master

    An ARM mnemonic is composed of three potential parts:

    1. Base Instruction: The core operation (e.g., add).
    2. s Modifier: Appending s (e.g., adds) tells the core to update the CPSR condition flags based on the result of the operation. By default, instructions do not modify flags.
    3. Condition Modifier: A two-letter code appended to the mnemonic to make the instruction conditional (e.g., addeq). These can be combined with the s modifier (e.g., addseq).

    Common Condition Modifiers

    Cond CodeCondition FlagsMeaning
    EQZ = 1Equal
    NEZ = 0Not equal
    CS/HSC = 1Carry condition flag set
    CC/LOC = 0Carry condition flag clear
    MIN = 1Negative
    PLN = 0Positive or zero
    VSV = 1Overflow set
    VCV = 0Overflow not set
    HIC = 1 and Z = 0Unsigned higher
    LSC = 0 or Z = 1Unsigned lower or same
    GEN = VSigned greater than or equal
    LTN != VSigned less than
    GTZ = 0 and N = VSigned greater than
    LEZ = 1 and N != VSigned less than or equal
    ALDefaultAlways (usually omitted)
  5. How orientation fusion algorithms work

    master

    Most orientation fusion algorithms in zscilib follow a similar principle: they take an initial orientation and integrate angular velocity from a gyroscope over time to estimate new orientations.

    To prevent gyroscope drift (common in MEMS sensors), accelerometer and/or magnetometer vectors are used to provide absolute references relative to gravity and/or magnetic north.

    Algorithm Specifics

    • AQUA (Algebraic Quaternion Algorithm): A robust algorithm that starts with gyroscope integration. It refines the estimate using an accelerometer, and further refines it using a magnetometer if both an accelerometer and magnetometer are present. Note: If you have a gyroscope and magnetometer but no accelerometer, the magnetometer data will be ignored.
    • Complementary: Merges two estimates using linear interpolation with a weight (alpha). One estimate comes from the gyroscope (zsl_quat_from_ang_vel), and the second comes from the accelerometer and magnetometer (zsl_att_from_accelmag).
      • alpha near 0.0: Gyroscope is prioritized.
      • alpha near 1.0: Accel/Mag are prioritized.
    • Extended Kalman: A robust, stable, and reliable choice for stable results, but it is computationally expensive.
    • Madgwick: A computationally efficient alternative to Extended Kalman. It requires careful tuning of the beta parameter based on your specific sensors to ensure stability and accuracy.
    • SAAM (Super-fast Attitude from Accelerometer and Magnetometer): A highly efficient algorithm based on least-squares optimization. It does not require a gyroscope, making it ideal for low-power or low-cost applications.
  6. Understand ARM Cortex-M Instruction Sets

    master

    ARM Cortex-M devices use different instruction sets depending on the specific architecture. When writing assembly for these devices, ensure you are targeting the correct set:

    • ARMv6-M (Thumb): Used by ARM Cortex M0, ARM Cortex-M0+
    • ARMv7-M (Thumb-2): Used by ARM Cortex-M3
    • ARMv7E-M (Thumb-2): Used by ARM Cortex M4(F), ARM Cortex M7
    • ARMv8-M (Thumb-2): Used by ARM Cortex M23, ARM Cortex M33
  7. Architecture-Specific Optimisations

    master

    The library includes tooling to allow for optimized, architecture-specific implementations of key functions using assembly.

    Initial optimization efforts target the Arm Cortex-M family of devices using the Thumb and Thumb-2 instruction sets. This design allows the library to achieve high performance on resource-constrained hardware by replacing generic C implementations with hand-optimized assembly where beneficial.

  8. Identify ARM User Registers

    master

    ARM processors use 32-bit registers to store values before operations. Registers are divided into general-purpose and special-purpose categories.

    General Purpose Registers

    • R0 through R10: General-purpose.
    • R11 (fp): Frame pointer (used by compilers to track stack frames).
    • R12 (ip): Inter-procedure scratch register (used by C libraries for DLL calls).

    Special Purpose Registers

    • R13 (sp): Stack Pointer. Holds the address where the stack currently ends. The stack grows downward (the value decreases as usage increases).
    • R14 (lr): Link Register. Contains the return address for subroutines (usually the pc value from the caller).
    • R15 (pc): Program Counter. Contains the address of the next instruction to be executed.
  9. Perform component-wise matrix operations

    master

    You can apply unary or binary operations to matrices using the zsl_mtx_unary_op and zsl_mtx_binary_op functions. For operations not covered by the built-in list, you can provide user-defined functions via zsl_mtx_unary_func or zsl_mtx_binary_func.

    // Example concept: applying a unary operation
    // zsl_mtx_unary_op(matrix, operation_type)
    
    // Example concept: applying a binary operation
    // zsl_mtx_binary_op(matrix_a, matrix_b, operation_type)
  10. Use Immediate Values in ARM Assembly

    master

    Immediate values are constants used as operands. They can be specified in decimal, octal (03), hexadecimal (0x2F), or binary (0b11010010).

    There are two distinct syntaxes in GNU assembly depending on the instruction type:

    1. For Load/Store instructions: Use =<immediate|symbol>. This specifies a 32-bit immediate value or the value of a symbol (label or .equ).
    2. For Data-processing instructions: Use #<immediate|symbol>.

    Important Restrictions:

    • The = syntax is only for load/store instructions.
    • The # syntax is restricted: the assembler must be able to construct the value using only eight bits of data, a shift/rotate operation, and/or a complement. If a value cannot meet these constraints, you must use a ldr instruction with the = syntax to load it from a literal pool.
    ; Example of using the = syntax for load/store
    LDR R0, =0x12345678
    
    ; Example of using the # syntax for data processing
    ADD R1, R2, #5
  11. Understand ARM Instruction Types

    master

    ARM instructions are rigidly separated into two main types:

    1. Load/Store Instructions: Move data between the CPU and memory (or vice versa). They can work with 8, 16, or 32-bit chunks.
    2. Data-processing Instructions: Perform computations. These operate on values already present in core registers (e.g., R5, R8). They typically use two source operands and one core register.
  12. Understand benchmarking accuracy and hardware requirements

    master

    The accuracy of the benchmark results depends on the hardware platform:

    • High Accuracy: Use an actual ARM Cortex-M3 or M4 core with the DWT (Data Watchpoint and Trace) peripheral block present.
    • Approximate Accuracy: When using qemu_cortex_m3 or non-M3/M4 hardware, the sample uses the high-precision kernel clock. Data from these platforms is approximate and should not be compared directly against data from M3/M4 hardware.