Project - Native Objects Proxy

Native Objects Proxy

This framework provides a base class to handle native objects in managed code. Those managed proxy objects automatically allocate native memory on creation and free it when they are destroyed by the garbage collection. The proxies only store a pointer to the native memory address of their data,
By this you can keep the objects’ data in the RLPLite memory while having a reference to it in managed code, so that you can call native functions without the need of transfering the data back and forth.

The code is still very rudimental and is not really documented, yet, but I wanted to share it with you already. I will improve it as soon as I got some more free time.
I added a proxy, and a local class for a four-dimensional vector, both implementing a method to execute a quaternion multiplication. This class (NativeVector4) also contains quite some comments about design considerations I have done, while writing the code.

Multiplying the same two quaternions with each other 500 times on a Fez Cerberus (floating-point unit + DSP functions) results in the following execution times:
500x Vector4 = 0.95s
500x NativeVector4 = 0.17s

It uses the SimpleHeap implementation by taylorza. Big thanks for that!

2 Likes

Sounds like IMU time :slight_smile:
Looks very interesting - Thanks.

Actually, the kalman-filter is running, but not yet very good. I might publish it when it’s a bit more stable :wink:
Also I’m running out of RLPLite memory on cerberus with the kalman-filter, I have only 1-3kb left (depending whether I compile with ‘optimize for time’) and I still need to implement the RLPLite I2C connection to the IMU. Kalman filter requires about 1.6kb for data storage alone. I could reduce it by about 640 bytes, as I have 10 4x4 matrices for debugging purposes only. I can pass a byte parameter to the filter, which tells it which part I’d like to debug (however only part at a time). Those matrices are then filled with all intermediate results of that part.

Using managed code I don’t seem to be able to trigger the I2C communication at 150Hz. I might have to go for Hydra, but I don’t think it will fit into my airplane. At least not without major changes (to the airplane, not Hydra).

EDIT: Right now, 500 kalman-filter steps, each triggered separately from managed code, takes about 0.2s to execute.

@ MarkusFriedel - Have you tried a DCM at all? I am in the process of doing a G120 based autopilot and using a similar design to this http://store.diydrones.com/ArduIMU_V3_p/kt-arduimu-30.htm for the IMU. I would be very interested in your design.

Cheers
Justin

No, I haven’t tried it, nor took a look at it, yet. But now as you mentioned it, I’m gonna give it a look, however I will test my kalman filter first in flight before spending time on a different method.

What keeps me away from the G120 for the airplane (even though I have a G120 here) is the lack of a floating point unit.
You’re not using a Spektrum Transmitter for the autopilot, are you? Cause I’m also gonna create a daisylink module, capable of reading the TX output of a Spektrum satellite receiver. By this I only require 3 pins for the RC connection. This module should also create the pwm outputs for the servos. I want to have that on a separate module, as NetMF together with native coding tends to be quite unstable. An error could halt the whole system. Therefore I want to have a module with the minumum functionality to read from RC receiver and control the servos, so that it could send the RC data right through to the outputs in case the communication to the main cpu breaks.

So you’re using a mpu60xx together with a HMC5883?

@ MarkusFriedel

Yes i am using a DX6i

18 months ago i was using a Netduino Mini reading 4 channels and an Arduimu V2 and stabalising a Skywalker - worked a treat.

I am creating a custom board with G120 doing all the high level GPS navigation stuff and reading the serial IMU etc and separate expansion boards for servos etc.

I am basing my design and expansion boards on a PixHawk - https://pixhawk.ethz.ch/px4/modules/px4fmu

Here’s my code I’ve written to communicate with Spektrum satellite receiver (receiver’s gray cable) with the uart’s RX pin of the specified port.

It’s very simple and not failsafe at all! So I don’t parse the received frames for the channel id’s, yet. If it would ever miss a single byte, it would mix up the channels. In addition, you can’t use it for binding, so you would have to bind te satellite receiver using a normal receiver first. After that it can be used standalone. However, so far it works, I’ve never lost sync with the frames and it’s quite nice for testing. I simply connected both, my IMU using I2C and the receiver using UART to a U/I port using a gadgeteer breakout adapter.

The IMU I’m using is the 9 DOF from flyduino.net, however I will go for the 10 DOF, as this one not only has an additional pressure sensor, but as far as I know, also routes the MPU’s IRQ pin to the connector.


using System;
using Microsoft.SPOT;

using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using GTI = Gadgeteer.Interfaces;

namespace Gadgeteer.Modules.SpektrumReceiver
{
    public class SpektrumReceiver : GTM.Module
    {
        public SpektrumReceiver(int socketNumber)
        {
            for (int i = 0; i < 8; i++)
            {
                inputs[i] = 0;
            }
            Socket socket = Socket.GetSocket(socketNumber, true, this, null);

            serialPort = new GTI.Serial(socket, 115200, GTI.Serial.SerialParity.None, GTI.Serial.SerialStopBits.One, 8, GTI.Serial.HardwareFlowControl.NotRequired, this);

            serialPort.DataReceived += new GTI.Serial.DataReceivedEventHandler(serialPort_DataReceived);

            serialPort.Open();
        }

        public short getValue(int channel)
        {
            return inputs[channel];
        }

        short[] inputs = new short[8];
        object inputlock = new object();

        int byteNr = 0;

        byte[] inputBuffer = new byte[16];

        public int FramesReceived { get; private set; }
        public int FramesProcessed { get; private set; }

        void serialPort_DataReceived(GTI.Serial sender, System.IO.Ports.SerialData data)
        {
            

            int bytesToRead = serialPort.BytesToRead;

            int frameCount = bytesToRead / 16;

            FramesReceived += frameCount;
            FramesProcessed++;

            int offset = (frameCount - 1) * 16;
            if (offset < 0)
                offset = 0;
                
            byte[] buffer = new byte[bytesToRead];

            serialPort.Read(buffer, 0, bytesToRead);

            for (int bufIdx = offset; bufIdx < bytesToRead; bufIdx++)
            {

                inputBuffer[byteNr++] = buffer[bufIdx];

                if (byteNr >= 16)
                {
                    byteNr = 0;

                    for (int i = 0; i < 8; i++)
                    {
                        inputs[i] = (short)((inputBuffer[i * 2] & 3) * 256 + inputBuffer[(i * 2) + 1] - 170);
                    }

                }
            }
        }

        GTI.Serial serialPort;
    }
}

Good stuff - looks like we can collaborate on this - what airframe are you using?
Also with your imu are you using airspeed measurements for centripetal forces?

@ MarkusFriedel - Very nice, I like this idea very much!

Indeed new topic or offline via email if fine by me - justin at ingenuitymicro dot com