ev3dev: C für EV3

NXC, C/C++, Lejos, pbLua, RobotC...

Moderator: Moderatoren

Benutzeravatar
Ziz
Schreibt ab und zu
Schreibt ab und zu
Beiträge: 36
Registriert: 16. Apr 2015 17:45
Kontaktdaten:

Re: ev3dev: C für EV3

Beitragvon Ziz » 8. Mai 2015 17:13

Ich habe gerade mal die Textausgabe und paar Zeichenfunktionen implementiert. Ich habe aber keine Funktion für unausgefüllt Ellipsen, Kreise oder Rectangle, habe diese also mit der gefüllten Variante ersetzt. Wie ist das eigentlich bei den Referenzimplementierungen, würde CircleOut(50, 40, 10); einen weiß gefüllten Kreis zeichnen (und anderes übermalen), oder die Mitte leer lassen?

Das ist das Gesamtergebnis mit dem gcc 4.9.2 und -O3:

Code: Alles auswählen

  0       2  int_Add
  1       1  int_Mult
  2      51  float_op
  3       2  randomize
  4       0  matrx_algb
  5      37  arr_sort
  6      39  displ_txt
  7      57  graphics
gesamt ms: 189
benchmark: 264550


Das ist der Code:

Code: Alles auswählen

// HaWe Brickbench
// benchmark test for NXT/EV3 and similar Micro Controllers
// PL: gpp CSLite C/C++, C-API and BCC by John Hansen
// Autor: (C) Helmut Wunder 2013,2014
// freie Verwendung für private Zwecke
// für kommerzielle Zwecke nur nach Genehmigung durch den Autor.
// protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/
// version 1.09.0

#include <stdio.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>

//Get ev3c here: https://github.com/theZiz/ev3c
#include "../ev3c/ev3c.h"

unsigned long runtime[8];

int a[500], b[500], c[500], t[500];

uint32_t timer()
{
   struct timeval now;
   uint32_t ticks;
   gettimeofday(&now, NULL);
   ticks=now.tv_sec*1000+now.tv_usec/1000;
   return(ticks);
}


//--------------------------------------------
// Mersenne Twister
//--------------------------------------------

unsigned long randM(void) {
   const int M = 7;
   const unsigned long A[2] = { 0, 0x8ebfd028 };

   static unsigned long y[25];
   static int index = 25+1;

   if (index >= 25) {
     int k;
     if (index > 25) {
        unsigned long r = 9, s = 3402;
        for (k=0 ; k<25 ; ++k) {
          r = 509845221 * r + 3;
          s *= s + 1;
          y[k] = s + (r >> 10);
        }
     }
     for (k=0 ; k<25-M ; ++k)
        y[k] = y[k+M] ^ (y[k] >> 1) ^ A[y[k] & 1];
     for (; k<25 ; ++k)
        y[k] = y[k+(M-25)] ^ (y[k] >> 1) ^ A[y[k] & 1];
     index = 0;
   }

   unsigned long e = y[index++];
   e ^= (e << 7) & 0x2b5b2500;
   e ^= (e << 15) & 0xdb8b0000;
   e ^= (e >> 16);
   return e;
}

//--------------------------------------------
// Matrix Algebra
//--------------------------------------------

// matrix * matrix multiplication (matrix product)

void MatrixMatrixMult(int N, int M, int K, double A[][M], double B[][K], double C[][K]){
  int i, j, s;                                       // matrix A: N x M // B: M x K // C: N x K
  for (i=0; i<N; ++i) {
    for (j=0; j<K; ++j) {
       C[i][j]=0;
       for (s=0; s<M; ++s) {
         C[i][j]=C[i][j] + A[i][s]*B[s][j];
      }
    }
  }
}


// matrix determinant

double MatrixDet(int N, double A[N][N])
{
    int i,j,i_count,j_count, count=0;
    double Asub[N-1][N-1], det=0;

    if(N==1) return A[0][0];
    if(N==2) return (A[0][0]*A[1][1] - A[0][1]*A[1][0]);

    for(count=0; count<N; count++)
    {
        i_count=0;
        for(i=1; i<N; i++)
        {
            j_count=0;
            for(j=0; j<N; j++)
            {
                if(j == count) continue;
                Asub[i_count][j_count] = A[i][j];
                j_count++;
            }
            i_count++;
        }
        det += pow(-1, count) * A[0][count] * MatrixDet(N-1,Asub);
    }
    return det;
}


//--------------------------------------------
// shell sort
//--------------------------------------------

void shellsort(int size, int* A)
{
  int i, j, increment;
  int temp;
  increment = size / 2;

  while (increment > 0) {
    for (i = increment; i < size; i++) {
      j = i;
      temp = A[i];
      while ((j >= increment) && (A[j-increment] > temp)) {
        A[j] = A[j - increment];
        j = j - increment;
      }
      A[j] = temp;
    }

    if (increment == 2)
       increment = 1;
    else
       increment = (unsigned int) (increment / 2.2);
  }
}

//--------------------------------------------
// gnu quick sort
// (0ptional)
//--------------------------------------------

int compare_int (const int *a, const int *b)
{
  int  temp = *a - *b;

  if (temp > 0)          return  1;
  else if (temp < 0)     return -1;
  else                   return  0;
}

// gnu qsort:
// void qsort (void *a , size_a count, size_a size, compare_function)
// gnu qsort call for a[500] array of int:
// qsort (a , 500, sizeof(a), compare_int)



//--------------------------------------------
// benchmark test procedures
//--------------------------------------------


int test_Int_Add() {
   int i=1, j=11, k=112, l=1111, m=11111, n=-1, o=-11, p=-111, q=-1112, r=-11111;
   int x;
   volatile long s=0;
   for(x=0;x<10000;++x) {
     s+=i; s+=j; s+=k; s+=l; s+=m; s+=n; s+=o; s+=p; s+=q; s+=r;
   }
   return s;
}



long test_Int_Mult() {
  int x,y;
  volatile long s;

  for(y=0;y<2000;++y) {
    s=1;
    for(x=1;x<=13;++x) { s*=x;}
    for(x=13;x>0;--x) { s/=x;}

  }
  return s;
}


#define PI  M_PI


double test_float_math() {

  volatile double s=PI;
  int y;

  for(y=0;y<1000;++y) {
     s*=sqrt(s);
     s=sin(s);
     s=exp(s);
     s*=s;
  }
  return s;
}


long test_rand_MT(){
  volatile unsigned long s;
  int y;

  for(y=0;y<5000;++y) {
     s=randM()%10001;
  }
  return s;
}


float test_matrix_math() {
  int x;

  double A[2][2], B[2][2], C[2][2];
  double O[3][3], T[3][3];
  unsigned long s;

  for(x=0;x<250;++x) {

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;

    B[0][0]=10;  B[0][1]=30;
    B[1][0]=20;  B[1][1]=40;

    MatrixMatrixMult(2,2,2, A,B,C);

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;

    MatrixDet(2, A);

    O[0][0]=1;   O[0][1]=4;  O[0][2]=7;
    O[1][0]=2;   O[1][1]=5;  O[1][2]=8;
    O[2][0]=3;   O[2][1]=6;  O[2][2]=9;

    MatrixDet(3, O);

  }

  s=(O[0][0]*O[1][1]*O[2][2]);
  return s;
}



// for array copy using void *memcpy(void *dest, const void *src, size_t n);

long test_Sort(){
  unsigned long s;
  int y, i;
  int t[500];

  for(y=0;y<30;++y) {
    memcpy(t, a, sizeof(a));
    shellsort(500, t);
   
    memcpy(t, a, sizeof(b));
    shellsort(500, t);
   
    memcpy(t, a, sizeof(c));
    shellsort(500, t);
  }

  return y;
}



long test_TextOut(){

  int  y;
  char buf[120];

  for(y=0;y<20;++y) {
    ev3_clear_lcd();
    sprintf (buf, "%3d %4d  int_Add",    0, 1000); ev3_text_lcd_normal( 0,10, buf);
    sprintf (buf, "%3d %4d  int_Mult",   1, 1010); ev3_text_lcd_normal( 0,20, buf);
    sprintf (buf, "%3d %4d  float_op",   2, 1020); ev3_text_lcd_normal( 0,30, buf);
    sprintf (buf, "%3d %4d  randomize",  3, 1030); ev3_text_lcd_normal( 0,40, buf);
    sprintf (buf, "%3d %4d  matrx_algb", 4, 1040); ev3_text_lcd_normal( 0,50, buf);
    sprintf (buf, "%3d %4d  arr_sort",   5, 1050); ev3_text_lcd_normal( 0,60, buf);
    sprintf (buf, "%3d %4d  displ_txt",  6, 1060); ev3_text_lcd_normal( 0,70, buf);
    sprintf (buf, "%3d %4d  testing...", 7, 1070); ev3_text_lcd_normal( 0,80, buf);

  }
  return 99;
}


long test_graphics(){
  int x=88, y;
  for(y=0;y<100;++y) {

    ev3_clear_lcd();

    ev3_circle_lcd(50, 40, 10, 1);
    ev3_circle_lcd(30, 24, 10, 1);
    ev3_line_lcd(10, 10, 60, 60, 1);
    ev3_line_lcd(50, 20, 90, 70, 1);
    ev3_rectangle_lcd(20, 20, 40, 40, 1);
    ev3_rectangle_lcd(65, 25, 20, 30, 1);
    ev3_ellipse_lcd(70, 30, 15, 20, 1);

  }
  return y;
}


inline void displayValues() {

  char buf[120];

    sprintf (buf, "%3d %7d  int_Add",    0, runtime[0]); ev3_text_lcd_normal( 0,10, buf);
    printf("%s\n",buf);
    sprintf (buf, "%3d %7d  int_Mult",   1, runtime[1]); ev3_text_lcd_normal( 0,20, buf);
    printf("%s\n",buf);
    sprintf (buf, "%3d %7d  float_op",   2, runtime[2]); ev3_text_lcd_normal( 0,30, buf);
    printf("%s\n",buf);
    sprintf (buf, "%3d %7d  randomize",  3, runtime[3]); ev3_text_lcd_normal( 0,40, buf);
    printf("%s\n",buf);
    sprintf (buf, "%3d %7d  matrx_algb", 4, runtime[4]); ev3_text_lcd_normal( 0,50, buf);
    printf("%s\n",buf);
    sprintf (buf, "%3d %7d  arr_sort",   5, runtime[5]); ev3_text_lcd_normal( 0,60, buf);
    printf("%s\n",buf);
    sprintf (buf, "%3d %7d  displ_txt",  6, runtime[6]); ev3_text_lcd_normal( 0,70, buf);
    printf("%s\n",buf);
    sprintf (buf, "%3d %7d  graphics",   7, runtime[7]); ev3_text_lcd_normal( 0,80, buf);
    printf("%s\n",buf);
}


int main(){

  unsigned long time0, x, y;
  float s;
  char  buf[120];
  int   i;

  ev3_init_lcd();
  ev3_clear_lcd();

  ev3_text_lcd_normal( 0,10, "hw brickbench");
  ev3_text_lcd_normal( 0,20, "(C)H.Wunder 2013");
  ev3_text_lcd_normal( 0,50, "initializing...");

  for(y=0;y<500;++y) {
    a[y]=randM()%30000; b[y]=randM()%30000; c[y]=randM()%30000;
  }


  ev3_clear_lcd();

  time0= timer();
  s=test_Int_Add();
  runtime[0]=timer()-time0;
  sprintf (buf, "%3d %7d  int_Add",    0, runtime[0]); ev3_text_lcd_normal( 0,10, buf);

  time0=timer();
  s=test_Int_Mult();
  runtime[1]=timer()-time0;
  sprintf (buf, "%3d %7d  int_Mult",   0, runtime[1]); ev3_text_lcd_normal( 0,20, buf);

  time0=timer();
  s=test_float_math();
  runtime[2]=timer()-time0;
  sprintf (buf, "%3d %7d  float_op",   0, runtime[2]); ev3_text_lcd_normal( 0,30, buf);

  time0=timer();
  s=test_rand_MT();
  runtime[3]=timer()-time0;
  sprintf (buf, "%3d %7d  randomize",  0, runtime[3]); ev3_text_lcd_normal( 0,40, buf);

  time0=timer();
  s=test_matrix_math();
  runtime[4]=timer()-time0;
  sprintf (buf, "%3d %7d  matrx_algb", 0, runtime[4]); ev3_text_lcd_normal( 0,50, buf);


  time0=timer();
  s=test_Sort();
  runtime[5]=timer()-time0;
  sprintf (buf, "%3d %7d  arr_sort",   0, runtime[5]); ev3_text_lcd_normal( 0,60, buf);

  time0=timer();
  s=test_TextOut();
  runtime[6]=timer()-time0;
  ev3_clear_lcd();
  displayValues();
  printf("---\n");

  time0=timer();
  s=test_graphics();
  runtime[7]=timer()-time0;
  ev3_clear_lcd();
  displayValues();
 
  ev3_clear_lcd();
  y=0;
  for(x=0;x<8;++x) {y+= runtime[x];}

  sprintf (buf, "gesamt ms: %d ", y);           ev3_text_lcd_normal( 0,10, buf);
  printf("%s\n",buf);
  sprintf (buf, "benchmark: %d ", 50000000/y ); ev3_text_lcd_normal( 0,20, buf);
  printf("%s\n",buf);

  ev3_text_lcd_normal( 0,40, "quit: press btn < LEFT...");   // to be fixed  ! <<<<<<<<< no reaction, just for left + ESC !

  ev3_quit_lcd();

  return 0;
}


Ich habe die Buttons noch nicht implementiert, deshalb fehlen die einfach. Das Programm geht einfach nach ~200ms zu Ende und ich schau mir die Ergebnisse im Terminal an. ;)

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5399
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: ev3dev: C für EV3

Beitragvon HaWe » 8. Mai 2015 17:58

normalerweise macht CircleOut u.ä. auch bei Arduino nur eine Kreislinie, FillCircle etc. füllt ihn aus (vergleiche andere Code-Implementierungen).
Füllen dauert natürlich länger als nur die Linie zu zeichnen. Das würde ntl. deinen Code sogar eher zu deinen (ev3dev's) Gunsten beschleunigen!
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5399
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: ev3dev: C für EV3

Beitragvon HaWe » 8. Mai 2015 18:03

speed benchmark fast 260.000!
fast wie ichs geschätzt hatte!
Sogar schon ohne alle environment-Punkte!

100x so schnell wie NXT/NXC
4x so schnell wie EV3/Java, Mono!
(von RobotC gar nicht zu reden ;) )

WAHNSINN !
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5399
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: ev3dev: C für EV3

Beitragvon HaWe » 8. Mai 2015 18:25

ps, matrix algebra plötzlich null ?

kannst du die mal bitte 10x hintereinander durchführen?
Oder mit -O2 compilieren?
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
Ziz
Schreibt ab und zu
Schreibt ab und zu
Beiträge: 36
Registriert: 16. Apr 2015 17:45
Kontaktdaten:

Re: ev3dev: C für EV3

Beitragvon Ziz » 8. Mai 2015 19:34

Habe mal Code für Kreis- und Rechtecklinien hinzugefügt. Damit komme ich auf folgende Werte:

Code: Alles auswählen

  0       2  int_Add
  1       1  int_Mult
  2      52  float_op
  3       1  randomize
  4       1  matrx_algb
  5      38  arr_sort
  6      41  displ_txt
  7      47  graphics
gesamt ms: 183
benchmark: 273224


Muss aber dazu sagen, die Werte schwanken sehr stark. 183 ms ist aber schon ein typischer Wert. ;) Text bekäme ich bestimmt auch schneller, sehe aber nicht wirklich den Sinn darin :D

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5399
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: ev3dev: C für EV3

Beitragvon HaWe » 8. Mai 2015 19:40

nein, völlig richtig - ist ja schon jetzt absolut die Granate ! :D

ob du noch was zu den Punkten 10-24 sagen kannst?

viewtopic.php?f=71&t=8095#p64772
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
Ziz
Schreibt ab und zu
Schreibt ab und zu
Beiträge: 36
Registriert: 16. Apr 2015 17:45
Kontaktdaten:

Re: ev3dev: C für EV3

Beitragvon Ziz » 8. Mai 2015 19:48

Die meisten Werte werden wie bei BCC/gpp C sein, ansonsten was sollen die Punkte 10 bis 12 sein? Was muss ich da wissen / messen?

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5399
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: ev3dev: C für EV3

Beitragvon HaWe » 8. Mai 2015 20:44

10. freier adressierbarer Flash-Speicher (für Code und gespeicherte Daten, Logfiles zur Laufzeit)
11. freies adressierbares RAM für Variablen zur Laufzeit (z.B. stack und heap)
12. SDs werden ja unterstützt, daher ist das klar.
13 - 18: mögliche Vernetzungen.
bei 13 wird die max. Anzahl der slaves für BT-Mailbox-Nachrichten etc. gezählt (z.B. 7 BT slaves bei X3),
14 entfällt bei ev3,
15-18: als Daisy-chaining wird gewertet, wenn wie bei X3/USB alle remote-IOs per API exakt wie lokale angesprochen werden können (ohne dass dies selber programmiert werden muss)
19-22 ist klar (vorhanden)
23: sind alle API-Funktionen für alle Hardware-Module einsatzbereit, ggf welche nicht?
sogar Extras vorhanden: ++, wie bei X3 vorhanden: +; fast komplett: (+), mehrfach teilw. fehlend (-), 1 komplettes Modul fehlend: ---
(Buttons, Screen, Sound, BT, WiFi, USB-serial-network (RNDIS), USB-master für keyb, USB-Sticks, USB-Cam,
alle EV3 + NXT Sensoren, Standard-I2C (auch mehrere Geräte verkettet), Fremd-UART und -ADC Devices,
alle Motoren samt Encoder-Funktionen, wie PID-Controller (absolute + relative Drehungen, erreichen und halten eines Wertes, sync-Funktionen, ramp up und down)
24: einfache, simple IDE vorhanden samt Crosscompiler, Debugger, Makefile samt USB-upload (wie z.B. BCC, RobotC, Arduino Sketch/Wiring ?
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
Ziz
Schreibt ab und zu
Schreibt ab und zu
Beiträge: 36
Registriert: 16. Apr 2015 17:45
Kontaktdaten:

Re: ev3dev: C für EV3

Beitragvon Ziz » 8. Mai 2015 23:54

Hey, ich habe das Programm vollendet, mit Button support und allem:
(edited by HaWe: Programm-Kopf geupdated!)

Code: Alles auswählen

// HaWe Brickbench
// benchmark test for NXT/EV3 and similar Micro Controllers
// PL: GCC, ev3dev (~Debian) Linux
// Autor: (C) Helmut Wunder 2013,2014
// ported to ev3dev by "Ziz" https://github.com/theZiz/ev3c
//
// freie Verwendung für private Zwecke
// für kommerzielle Zwecke nur nach schriftlicher Genehmigung durch den Autor.
// protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/
// version 1.09.001  9.Mai 2015

#include <stdio.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>

//Get ev3c here: https://github.com/theZiz/ev3c
#include "../ev3c/ev3c.h"

unsigned long runtime[8];

int a[500], b[500], c[500], t[500];

uint32_t timer()
{
   struct timeval now;
   uint32_t ticks;
   gettimeofday(&now, NULL);
   ticks=now.tv_sec*1000+now.tv_usec/1000;
   return(ticks);
}


//--------------------------------------------
// Mersenne Twister
//--------------------------------------------

unsigned long randM(void) {
   const int M = 7;
   const unsigned long A[2] = { 0, 0x8ebfd028 };

   static unsigned long y[25];
   static int index = 25+1;

   if (index >= 25) {
     int k;
     if (index > 25) {
        unsigned long r = 9, s = 3402;
        for (k=0 ; k<25 ; ++k) {
          r = 509845221 * r + 3;
          s *= s + 1;
          y[k] = s + (r >> 10);
        }
     }
     for (k=0 ; k<25-M ; ++k)
        y[k] = y[k+M] ^ (y[k] >> 1) ^ A[y[k] & 1];
     for (; k<25 ; ++k)
        y[k] = y[k+(M-25)] ^ (y[k] >> 1) ^ A[y[k] & 1];
     index = 0;
   }

   unsigned long e = y[index++];
   e ^= (e << 7) & 0x2b5b2500;
   e ^= (e << 15) & 0xdb8b0000;
   e ^= (e >> 16);
   return e;
}

//--------------------------------------------
// Matrix Algebra
//--------------------------------------------

// matrix * matrix multiplication (matrix product)

void MatrixMatrixMult(int N, int M, int K, double A[][M], double B[][K], double C[][K]){
  int i, j, s;                                       // matrix A: N x M // B: M x K // C: N x K
  for (i=0; i<N; ++i) {
    for (j=0; j<K; ++j) {
       C[i][j]=0;
       for (s=0; s<M; ++s) {
         C[i][j]=C[i][j] + A[i][s]*B[s][j];
      }
    }
  }
}


// matrix determinant

double MatrixDet(int N, double A[N][N])
{
    int i,j,i_count,j_count, count=0;
    double Asub[N-1][N-1], det=0;

    if(N==1) return A[0][0];
    if(N==2) return (A[0][0]*A[1][1] - A[0][1]*A[1][0]);

    for(count=0; count<N; count++)
    {
        i_count=0;
        for(i=1; i<N; i++)
        {
            j_count=0;
            for(j=0; j<N; j++)
            {
                if(j == count) continue;
                Asub[i_count][j_count] = A[i][j];
                j_count++;
            }
            i_count++;
        }
        det += pow(-1, count) * A[0][count] * MatrixDet(N-1,Asub);
    }
    return det;
}


//--------------------------------------------
// shell sort
//--------------------------------------------

void shellsort(int size, int* A)
{
  int i, j, increment;
  int temp;
  increment = size / 2;

  while (increment > 0) {
    for (i = increment; i < size; i++) {
      j = i;
      temp = A[i];
      while ((j >= increment) && (A[j-increment] > temp)) {
        A[j] = A[j - increment];
        j = j - increment;
      }
      A[j] = temp;
    }

    if (increment == 2)
       increment = 1;
    else
       increment = (unsigned int) (increment / 2.2);
  }
}

//--------------------------------------------
// gnu quick sort
// (0ptional)
//--------------------------------------------

int compare_int (const int *a, const int *b)
{
  int  temp = *a - *b;

  if (temp > 0)          return  1;
  else if (temp < 0)     return -1;
  else                   return  0;
}

// gnu qsort:
// void qsort (void *a , size_a count, size_a size, compare_function)
// gnu qsort call for a[500] array of int:
// qsort (a , 500, sizeof(a), compare_int)



//--------------------------------------------
// benchmark test procedures
//--------------------------------------------


int test_Int_Add() {
   int i=1, j=11, k=112, l=1111, m=11111, n=-1, o=-11, p=-111, q=-1112, r=-11111;
   int x;
   volatile long s=0;
   for(x=0;x<10000;++x) {
     s+=i; s+=j; s+=k; s+=l; s+=m; s+=n; s+=o; s+=p; s+=q; s+=r;
   }
   return s;
}



long test_Int_Mult() {
  int x,y;
  volatile long s;

  for(y=0;y<2000;++y) {
    s=1;
    for(x=1;x<=13;++x) { s*=x;}
    for(x=13;x>0;--x) { s/=x;}

  }
  return s;
}


#define PI  M_PI


double test_float_math() {

  volatile double s=PI;
  int y;

  for(y=0;y<1000;++y) {
     s*=sqrt(s);
     s=sin(s);
     s=exp(s);
     s*=s;
  }
  return s;
}


long test_rand_MT(){
  volatile unsigned long s;
  int y;

  for(y=0;y<5000;++y) {
     s=randM()%10001;
  }
  return s;
}


float test_matrix_math() {
  int x;

  double A[2][2], B[2][2], C[2][2];
  double O[3][3], T[3][3];
  unsigned long s;

  for(x=0;x<250;++x) {

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;

    B[0][0]=10;  B[0][1]=30;
    B[1][0]=20;  B[1][1]=40;

    MatrixMatrixMult(2,2,2, A,B,C);

    A[0][0]=1;   A[0][1]=3;
    A[1][0]=2;   A[1][1]=4;

    MatrixDet(2, A);

    O[0][0]=1;   O[0][1]=4;  O[0][2]=7;
    O[1][0]=2;   O[1][1]=5;  O[1][2]=8;
    O[2][0]=3;   O[2][1]=6;  O[2][2]=9;

    MatrixDet(3, O);

  }

  s=(O[0][0]*O[1][1]*O[2][2]);
  return s;
}



// for array copy using void *memcpy(void *dest, const void *src, size_t n);

long test_Sort(){
  unsigned long s;
  int y, i;
  int t[500];

  for(y=0;y<30;++y) {
    memcpy(t, a, sizeof(a));
    shellsort(500, t);
   
    memcpy(t, a, sizeof(b));
    shellsort(500, t);
   
    memcpy(t, a, sizeof(c));
    shellsort(500, t);
  }

  return y;
}



long test_TextOut(){

  int  y;
  char buf[120];

  for(y=0;y<20;++y) {
    ev3_clear_lcd();
    sprintf (buf, "%3d %4d  int_Add",    0, 1000); ev3_text_lcd_normal( 0,10, buf);
    sprintf (buf, "%3d %4d  int_Mult",   1, 1010); ev3_text_lcd_normal( 0,20, buf);
    sprintf (buf, "%3d %4d  float_op",   2, 1020); ev3_text_lcd_normal( 0,30, buf);
    sprintf (buf, "%3d %4d  randomize",  3, 1030); ev3_text_lcd_normal( 0,40, buf);
    sprintf (buf, "%3d %4d  matrx_algb", 4, 1040); ev3_text_lcd_normal( 0,50, buf);
    sprintf (buf, "%3d %4d  arr_sort",   5, 1050); ev3_text_lcd_normal( 0,60, buf);
    sprintf (buf, "%3d %4d  displ_txt",  6, 1060); ev3_text_lcd_normal( 0,70, buf);
    sprintf (buf, "%3d %4d  testing...", 7, 1070); ev3_text_lcd_normal( 0,80, buf);

  }
  return 99;
}


long test_graphics(){
  int x=88, y;
  for(y=0;y<100;++y) {

    ev3_clear_lcd();

    ev3_circle_lcd(50, 40, 10, 1);
    ev3_circle_lcd_out(30, 24, 10, 1);
    ev3_line_lcd(10, 10, 60, 60, 1);
    ev3_line_lcd(50, 20, 90, 70, 1);
    ev3_rectangle_lcd(20, 20, 40, 40, 1);
    ev3_rectangle_lcd_out(65, 25, 20, 30, 1);
    ev3_ellipse_lcd(70, 30, 15, 20, 1);

  }
  return y;
}


inline void displayValues() {

  char buf[120];

    sprintf (buf, "%3d %7d  int_Add",    0, runtime[0]); ev3_text_lcd_normal( 0,10, buf);
    sprintf (buf, "%3d %7d  int_Mult",   1, runtime[1]); ev3_text_lcd_normal( 0,20, buf);
    sprintf (buf, "%3d %7d  float_op",   2, runtime[2]); ev3_text_lcd_normal( 0,30, buf);
    sprintf (buf, "%3d %7d  randomize",  3, runtime[3]); ev3_text_lcd_normal( 0,40, buf);
    sprintf (buf, "%3d %7d  matrx_algb", 4, runtime[4]); ev3_text_lcd_normal( 0,50, buf);
    sprintf (buf, "%3d %7d  arr_sort",   5, runtime[5]); ev3_text_lcd_normal( 0,60, buf);
    sprintf (buf, "%3d %7d  displ_txt",  6, runtime[6]); ev3_text_lcd_normal( 0,70, buf);
    sprintf (buf, "%3d %7d  graphics",   7, runtime[7]); ev3_text_lcd_normal( 0,80, buf);
}


int main(){

  unsigned long time0, x, y;
  float s;
  char  buf[120];
  int   i;

  ev3_init_lcd();
  ev3_init_button();
 
  ev3_clear_lcd();

  ev3_text_lcd_normal( 0,10, "hw brickbench");
  ev3_text_lcd_normal( 0,20, "(C)H.Wunder 2013");
  ev3_text_lcd_normal( 0,50, "initializing...");

  for(y=0;y<500;++y) {
    a[y]=randM()%30000; b[y]=randM()%30000; c[y]=randM()%30000;
  }


  ev3_clear_lcd();

  time0= timer();
  s=test_Int_Add();
  runtime[0]=timer()-time0;
  sprintf (buf, "%3d %7d  int_Add",    0, runtime[0]); ev3_text_lcd_normal( 0,10, buf);

  time0=timer();
  s=test_Int_Mult();
  runtime[1]=timer()-time0;
  sprintf (buf, "%3d %7d  int_Mult",   0, runtime[1]); ev3_text_lcd_normal( 0,20, buf);

  time0=timer();
  s=test_float_math();
  runtime[2]=timer()-time0;
  sprintf (buf, "%3d %7d  float_op",   0, runtime[2]); ev3_text_lcd_normal( 0,30, buf);

  time0=timer();
  s=test_rand_MT();
  runtime[3]=timer()-time0;
  sprintf (buf, "%3d %7d  randomize",  0, runtime[3]); ev3_text_lcd_normal( 0,40, buf);

  time0=timer();
  s=test_matrix_math();
  runtime[4]=timer()-time0;
  sprintf (buf, "%3d %7d  matrx_algb", 0, runtime[4]); ev3_text_lcd_normal( 0,50, buf);


  time0=timer();
  s=test_Sort();
  runtime[5]=timer()-time0;
  sprintf (buf, "%3d %7d  arr_sort",   0, runtime[5]); ev3_text_lcd_normal( 0,60, buf);

  time0=timer();
  s=test_TextOut();
  runtime[6]=timer()-time0;
  ev3_clear_lcd();
  displayValues();
  printf("---\n");

  time0=timer();
  s=test_graphics();
  runtime[7]=timer()-time0;
  ev3_clear_lcd();
  displayValues();

  ev3_text_lcd_normal(0,100, "cont: press btn < LEFT...");

  while (!ev3_button_pressed(BUTTON_LEFT));
  while (ev3_button_pressed(BUTTON_LEFT));
 
  ev3_clear_lcd();
  y=0;
  for(x=0;x<8;++x) {y+= runtime[x];}

  sprintf (buf, "gesamt ms: %d ", y);           ev3_text_lcd_normal( 0,10, buf);
  sprintf (buf, "benchmark: %d ", 50000000/y ); ev3_text_lcd_normal( 0,20, buf);

  ev3_text_lcd_normal( 0,40, "quit: press btn < LEFT...");

  while (!ev3_button_pressed(BUTTON_LEFT));
  while (ev3_button_pressed(BUTTON_LEFT));
 
  ev3_quit_button();
  ev3_quit_lcd();

  return 0;
}


Interessanterweise läuft es so schneller. Meine Theorie ist, dass der BrickManager (der Starter von ev3dev) weniger dazwischenfunkt, wenn ich ein Programm über das Menü starte statt über SSH. Jedesfalls bekomme ich in ca. 50% der Fälle solche Ergebnisse:

Code: Alles auswählen

  0       2  int_Add
  1       2  int_Mult
  2      49  float_op
  3       1  randomize
  4       0  matrx_algb
  5      38  arr_sort
  6      40  displ_txt
  7      42  graphics
gesamt ms: 164
benchmark: 304878

Die anderen 50% ist die Gesamt-ms so bei 180, aber wir wollen ja protzen. ;) Wie hast du das bei den anderen Messwerten gehandhabt? Best Case, Average Case?

HaWe hat geschrieben:10. freier adressierbarer Flash-Speicher (für Code und gespeicherte Daten, Logfiles zur Laufzeit)

Der interne Speicher ist für ev3dev nicht nutzbar (wäre aber eh nicht sehr viel). ev3dev verbraucht im Moment 2GB. Man kann bis zu 32 GB große Micro SD Karten benutzen, also wären theoretisch bis zu 30 GB zur freien Verfügung... Keine Ahnung, ob der Wert so Aussagekraft besitzt.

11. freies adressierbares RAM für Variablen zur Laufzeit (z.B. stack und heap)

Also free sagt, ich hätte 41MB RAM frei. Dazu kommen aber 137 MB Swap (sowas wie die Auslagerungsdatei von Windows). D.h. ich kann durchaus 178MB benutzen für heap und stack, aber nur bis 41 MB ist das noch schnell. ;)

12. SDs werden ja unterstützt, daher ist das klar.
13 - 18: mögliche Vernetzungen.
bei 13 wird die max. Anzahl der slaves für BT-Mailbox-Nachrichten etc. gezählt (z.B. 7 BT slaves bei X3),
14 entfällt bei ev3,
15-18: als Daisy-chaining wird gewertet, wenn wie bei X3/USB alle remote-IOs per API exakt wie lokale angesprochen werden können (ohne dass dies selber programmiert werden muss)

Das Thema hatten wir ja schon. Keine Punkte für ev3dev hier. ;)

19-22 ist klar (vorhanden)
23: sind alle API-Funktionen für alle Hardware-Module einsatzbereit, ggf welche nicht?
sogar Extras vorhanden: ++, wie bei X3 vorhanden: +; fast komplett: (+), mehrfach teilw. fehlend (-), 1 komplettes Modul fehlend: ---
(Buttons, Screen, Sound, BT, WiFi, USB-serial-network (RNDIS), USB-master für keyb, USB-Sticks, USB-Cam,
alle EV3 + NXT Sensoren, Standard-I2C (auch mehrere Geräte verkettet), Fremd-UART und -ADC Devices,
alle Motoren samt Encoder-Funktionen, wie PID-Controller (absolute + relative Drehungen, erreichen und halten eines Wertes, sync-Funktionen, ramp up und down)

ramp up und ramp down ist im Moment nur eingeschränkt verfügbar, weil der Ralph Hempel an dem Treiber werkelt. Der Rest sollte gehen.

24: einfache, simple IDE vorhanden samt Crosscompiler, Debugger, Makefile samt USB-upload (wie z.B. BCC, RobotC, Arduino Sketch/Wiring) ?

Tja... Ich würde sagen: Ja. Du würdest sagen: Nein. Ich vermute leider, deine Stimme hat mehr Gewicht. :P

LG Ziz

Technicmaster0
Schreibt super viel
Schreibt super viel
Beiträge: 376
Registriert: 22. Dez 2010 12:36
Wohnort: In Berlin rechts abbiegen
Kontaktdaten:

Re: ev3dev: C für EV3

Beitragvon Technicmaster0 » 9. Mai 2015 00:37

Ziz hat geschrieben:
12. SDs werden ja unterstützt, daher ist das klar.
13 - 18: mögliche Vernetzungen.
bei 13 wird die max. Anzahl der slaves für BT-Mailbox-Nachrichten etc. gezählt (z.B. 7 BT slaves bei X3),
14 entfällt bei ev3,
15-18: als Daisy-chaining wird gewertet, wenn wie bei X3/USB alle remote-IOs per API exakt wie lokale angesprochen werden können (ohne dass dies selber programmiert werden muss)

Das Thema hatten wir ja schon. Keine Punkte für ev3dev hier. ;)

BT sollte doch theoretisch gehen? Wahrscheinlich sogar viel ausführlicher als das Mailbox System von X3.

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5399
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: ev3dev: C für EV3

Beitragvon HaWe » 9. Mai 2015 08:04

bei Lejos und Mono gab es breite Schwankungen, die habe ich notiert (best/worst case von 1-6 Läufen)
bei NXC, nxtOSEK, BCC/GCC gab es höchstens Schwankungen +/- 2ms oder 1% pro Messung, die sich sogar rausgemittelt haben.
Rest weiß ich nicht.

- welche IDE nimmst du ?

- wenn man per fertiger Voreinstellungen und per USB-Kabel und per Menü-Button kompiliert, hochlädt und startet (wie bei BCC, RobotC, EV3-SmallBasic, Sketch), und die IDE einfach und downstripped und gebrauchsfertig ist (alles ohne Extra-IDE-Konfiguration und extra-Plugin-Installation, IDE auf Mindstorms-Plattformen maßgeschneidert, keine Multi-Plattform-Monster wie Eclipse)
- das wäre ein "ja",
- ansonsten nein, insb. wenn man ssh oder puTTY oder Linux-Kommandozeilen braucht


- gibts auch kein Bluetooth Protokoll für mehrere Bricks?

- welche C-libs (.c, .h, .cpp) werden von ev3dev bei der Installation NICHT mitinstalliert, d.h. welche hast du für deine Programme selber geschrieben (Buttons? Screen (Grafik+TextOut)? Sound? Sensoren? Motoren? ... etc.?
was genau hast du neu/zusätzlich gemacht,
was ist gegenüber den Original-ev3dev-libs verändert, also nicht mehr kompatibel?



ps, edit:
einen Wert "0" für eine Laufzeit kann es nicht geben (wie z.B. Matrix-Algebra).
Entweder ist es ein Bug (in meinem Programm), oder eine unzulässige Optimierung (durch den Compiler), oder es ist ungenau gerundet (dann bräuchte man die Zeit in µs) !
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
Ziz
Schreibt ab und zu
Schreibt ab und zu
Beiträge: 36
Registriert: 16. Apr 2015 17:45
Kontaktdaten:

Re: ev3dev: C für EV3

Beitragvon Ziz » 9. Mai 2015 20:18

HaWe hat geschrieben:bei Lejos und Mono gab es breite Schwankungen, die habe ich notiert (best/worst case von 1-6 Läufen)
bei NXC, nxtOSEK, BCC/GCC gab es höchstens Schwankungen +/- 2ms oder 1% pro Messung, die sich sogar rausgemittelt haben.
Rest weiß ich nicht.

Gut, dann mache ich nochmal 6 Testläufe.

- welche IDE nimmst du ?

Was gerade da ist... Meist geany, aber zur Not auch nano. Ich mache das meiste ja selbst im Terminal und klicke mich nicht durch.

- wenn man per fertiger Voreinstellungen und per USB-Kabel und per Menü-Button kompiliert, hochlädt und startet (wie bei BCC, RobotC, EV3-SmallBasic, Sketch), und die IDE einfach und downstripped und gebrauchsfertig ist (alles ohne Extra-IDE-Konfiguration und extra-Plugin-Installation, IDE auf Mindstorms-Plattformen maßgeschneidert, keine Multi-Plattform-Monster wie Eclipse)
- das wäre ein "ja",
- ansonsten nein, insb. wenn man ssh oder puTTY oder Linux-Kommandozeilen braucht

Eindeutig ein Nein. ;)

- gibts auch kein Bluetooth Protokoll für mehrere Bricks?

Definiere Protokoll. Bluetooth funktioniert wie Bluetooth halt so funktioniert, man kann Geräte koppeln, Internet freigeben (Tethering) usw. Ich verbinde mich im Moment nur per Bluetooth mit dem Gerät. Aber es gibt kein Daisy Chaining Protokoll über Bluetooth. Die Geräte wären dann halt in einem LAN und könnten sich per IP ansprechen.


- welche C-libs (.c, .h, .cpp) werden von ev3dev bei der Installation NICHT mitinstalliert, d.h. welche hast du für deine Programme selber geschrieben (Buttons? Screen (Grafik+TextOut)? Sound? Sensoren? Motoren? ... etc.?
was genau hast du neu/zusätzlich gemacht,
was ist gegenüber den Original-ev3dev-libs verändert, also nicht mehr kompatibel?

Es ist alles kompatibel. ich füge nur hinzu / vereinfache, ich entferne nichts. An Standardlibs ist EV3-spezifisch nichts dabei, aber man kann eine Menge fertig runterladen, aber ich wollte halt eine C Lösung und keine C++ Lösung. Eigenart von mir. Also die Treiber für die Motoren, Buttons, Sensoren, Bildschirm, Sound usw. sind vorhanden und sehr einfach zugänglich. Ab Werk. Darauf basierend gibt es dann fertige Bibliotheken für C++, Python, Ruby, Go und haste nich gesehn, die muss man aber extra runterladen. ;)

ps, edit:
einen Wert "0" für eine Laufzeit kann es nicht geben (wie z.B. Matrix-Algebra).
Entweder ist es ein Bug (in meinem Programm), oder eine unzulässige Optimierung (durch den Compiler), oder es ist ungenau gerundet (dann bräuchte man die Zeit in µs) !

Wieso sollte das nicht gehen? Das zeigt nur, dass die gemessene Zeit unter 1ms liegt. Wenn wir davon ausgehen, dass immer abgerundet wird, könnte Messwert 1 bei 100,005 und Messwert 2 bei 100,895 liegen. Beide male würden einfach "100 ms" angegeben werden. 100-100 = 0 ;)

Ich habe in einem anderen Beitrag sehr lang und breit über Optimierungen debatiert und dabei u.U. 25000 statt 250 Schleifenumrunden für die Matrixoperation gemacht.
250 Wiederholungen: 1 ms
2500 Wiederholungen: 11 ms
25000 Wiederholungen: 113 ms

Da ist es leicht unter 1 ms zu fallen mit etwas Glück beim Messen. ;)

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5399
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: ev3dev: C für EV3

Beitragvon HaWe » 9. Mai 2015 20:35

dann ist es mit den Matrizen eindeutig ein Code-Design-Fehler meinerseits.
Enorm (und gelinde gesagt, mehr als überraschend), dass ev3dev die Matrizen so extrem viel schneller ausrechnet als BCC/GCC auf DaVinci Linux.
Aber dann müssen künftige Benchmark-Versionen alle Werte <10ms in Mikrosekunden ausgeben.

(ich bin da ein gebranntes Kind, bei den float benchmarks gabs auch mal so einen Bug, da waren nans die Ursache... :-/ )

Tun wir solange so, als wären es immer mindestens 1ms, sonst bin ich irgendwann nochmal gezwungen, durch NULL zu dividieren... 8-)


zu C vs. C++ :
das finde ich eindeutig auch per C (ohne pp) besser!



zu BT:
da ist die Frage,
a) mit wieviel anderen ev3s der 1. gepairt werden kann (üblicherweise begrenzt auf 1-7), und
b) wie senden + empfangen von Strings oder Byte-Arrays implementiert ist (das ist bei Lego üblicherweise per Mailbox-System geregelt).
Natürlich könnte man auch in/aus FILE * stream schreiben/lesen, wie bei einer Datei auf SD.

Einfach die Existenz einer Pair-Möglichkeit reicht nicht aus, Anfänger (Umsteiger von X3 oder NXC) müssen auf intuitiv einfache Weise Werte von 1 Brick zu einem definierten anderen senden können und dort eindeutig wieder empfangen können, möglichst ohne data loss oder corruption.
Ein Bitbus-Protokoll z.B. wäre schön (wie bei leJOS).



Soviel aber jetzt von mir zum Thema Benchmark - die Vergleichstabelle ist jetzt aktualisiert, die API scheint ja ziemlich vollständig zu sein!
Toll, dass du mitgemacht hast, vielen Dank für dein Engagement! :prima:
http://www.mindstormsforum.de/viewtopic.php?f=71&t=8095#p64772


Jetzt lass ich mich mal überraschen, wie die ersten Linefollower, Wallfollower, Mazesolver, Robosoccer, Segways und mehrachsigen Roboterarme mit ev3devC Programmen aussehen - und wie die einfache Installationsroutine und die einfache IDE samt USB-XP-RNDIS gadget... ;)
Das Niveau ist durch ev3dev jetzt immerhin eindeutig gestiegen, und ich bin gespannt, ob jetzt auch noch einer drauf ist :mrgreen:

Zum API-Design würde ich DRINGEND empfehlen, sich an John Hansens NXC oder notfalls auch an der RobotC API zu orientieren!
Einfache, prägnante, kurze Befehle, keine Romane für 1 Funktionsaufruf.
Also z.B. einfach

Code: Alles auswählen

On(port, pwm) // Motor: prozentuale Leistung, anschalten

Rotate(port, pwm, deg) // Motor: prozentuale Leistung, relative Drehung

RotateTo(port, pwm, deg) // Motor: prozentuale Leistung, absolutes Encoder-Ziel

RotatePID(port, pwm, deg, Kp, Ki, Kd, hold) // Motor: prozentuale Leistung, relat. Drehung, PID-Konst., hold/release

RotatePIDTo(port, pwm, deg, Kp, Ki, Kd, hold) // Motor: prozentuale Leistung, abs. Ziel, PID-Konst., hold/release

Off(port) // Motor ausschalten (stromlos = coast)

Brake(port) // Motor bremsen (Strombremse)

SetSensor(port, type, mode) // Sensor an Port X = ADC, I2C, UART, ggf. spezielle Betriebsart (raw, pulse, RGB, colortype)

ReadSensor(port,  * value) // lies Werte-Array von Sensor an Port X

// Anm.: für hold/release könnte man eine enum vorsehen ( nach Erreichen des Ziels), z.B. für
"hold" = ständige Anpassung/Verfolgung
"coast" = Abschalten auf stromlos
"brake" = aktive Strombremse


Ich selber jedenfalls brenne darauf, mein BP-net auf Ev3 zu portieren, es läuft inzwischen schon fast perfekt auf meinem DUE
http://www.mindstormsforum.de/viewtopic.php?f=70&t=6620&p=66151#p67035
- nur leider ohne preemptives Multitasking und mit absolut ausgereiztem RAM, das wäre jetzt per EVTHREE der notwendige "NeXT step"... 8-)
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
Ziz
Schreibt ab und zu
Schreibt ab und zu
Beiträge: 36
Registriert: 16. Apr 2015 17:45
Kontaktdaten:

Re: ev3dev: C für EV3

Beitragvon Ziz » 10. Mai 2015 10:35

HaWe hat geschrieben:dann ist es mit den Matrizen eindeutig ein Code-Design-Fehler meinerseits.
Enorm (und gelinde gesagt, mehr als überraschend), dass ev3dev die Matrizen so extrem viel schneller ausrechnet als BCC/GCC auf DaVinci Linux.
Aber dann müssen künftige Benchmark-Versionen alle Werte <10ms in Mikrosekunden ausgeben.

Meine Methode, um die Zeit zu messen, misst ansich eh in µs, aber dividiert dann durch 1000, um kompatibel zu sein. :D

(ich bin da ein gebranntes Kind, bei den float benchmarks gabs auch mal so einen Bug, da waren nans die Ursache... :-/ )

Ah, das erklärt eine Menge. Sowas ähnliches hatte ich auch vor kurzem. Ich wollte die schnellste Methode wissen, um die Sensorwerte am EV3 mit ev3dev zu messen und habe deshalb auch ein wenig mit Assembler rumgespielt (will nicht zu sehr ins Detail gehen). Naja, ich hatte beindruckende Werte. Speedup 10!!! Naja, Ende des Liedes: Meine Implementierung war falsch, er lieferte nur einen Fehler zurück - das aber sehr schnell - und mein Testcode testete nur auf die Geschwindigkeit, nicht auf die Korrektheit...
Am Ende war mein Assemblercode genauso schnell wie der normale C-Code. Im Nachhinein auch logisch...

Tun wir solange so, als wären es immer mindestens 1ms, sonst bin ich irgendwann nochmal gezwungen, durch NULL zu dividieren... 8-)

Ich denke nicht, dass die Gesamtzeit demnächst 0 wird. :D

zu C vs. C++ :
das finde ich eindeutig auch per C (ohne pp) besser!

Schön, dass wir uns da einig sind. ;)

zu BT:
da ist die Frage,
a) mit wieviel anderen ev3s der 1. gepairt werden kann (üblicherweise begrenzt auf 1-7), und

Keine Ahnung. Ich habe mich mal belesen, die ingesamt 8 miteinander kommunizierenden Bluetoothgeräte basieren auf dem Piconet, welchse eine 3Bit Adressierung verwendet. Das scheint also ein generelles Bluetooth"problem" zu sein.

b) wie senden + empfangen von Strings oder Byte-Arrays implementiert ist (das ist bei Lego üblicherweise per Mailbox-System geregelt).
Natürlich könnte man auch in/aus FILE * stream schreiben/lesen, wie bei einer Datei auf SD.

Ich kann hier nur für mich sprechen. Ich nutze einfach Netzwerksockets, um beliebige - und beliebig lange - Arrays zu versenden.

Einfach die Existenz einer Pair-Möglichkeit reicht nicht aus, Anfänger (Umsteiger von X3 oder NXC) müssen auf intuitiv einfache Weise Werte von 1 Brick zu einem definierten anderen senden können und dort eindeutig wieder empfangen können, möglichst ohne data loss oder corruption.
Ein Bitbus-Protokoll z.B. wäre schön (wie bei leJOS).

Ja, das hatten wir ja schon. Ev3dev ist nix für Anfänger der Programmierung. Anfänger brauchen imo weder Daisy Chaining, noch Rekursion, noch hohe Geschwindigkeiten und sind mit BrixCC und Ev3-Basic sehr gut bedient. Wenn es ambitionierter wird und insbesondere auch vertiefte Kenntnisse der Informatik wichtig werden (z.B. für Rekursionen), kann man weitersehen und schauen, was stattdessen Sinn ergibt. ;)

Soviel aber jetzt von mir zum Thema Benchmark - die Vergleichstabelle ist jetzt aktualisiert, die API scheint ja ziemlich vollständig zu sein!
Toll, dass du mitgemacht hast, vielen Dank für dein Engagement! :prima:
http://www.mindstormsforum.de/viewtopic.php?f=71&t=8095#p64772

Kein Ding, ist mir ja wichtig, ev3dev's Vorteile darzustellen. Die ganze Fummelei muss sich ja lohnen, wenn man am Ende genau endet wie mit der Original-FW, könnte man sich das ja auch sparen.

Jetzt lass ich mich mal überraschen, wie die ersten Linefollower, Wallfollower, Mazesolver, Robosoccer, Segways und mehrachsigen Roboterarme mit ev3devC Programmen aussehen - und wie die einfache Installationsroutine und die einfache IDE samt USB-XP-RNDIS gadget... ;)
Das Niveau ist durch ev3dev jetzt immerhin eindeutig gestiegen, und ich bin gespannt, ob jetzt auch noch einer drauf ist :mrgreen:

Da werden wir sehen, was die Zeit bringt. Mein erstes Projekt ist nicht sonderlich autonom, sondern geht erstmal Richtung Roboter fernsteuern und Sensorwerte über Netzwerk übertragen. Dann seh ich weiter, wo und wie ich das Autonomie unterbringe. Wahrscheinlich etwas in Richtung Linie folgen und Objekte aufnehmen oder so. ;) Die Sache ist: Mit jeder Sprache ist die Umsetzung der API etwas anders. Die C++ API ist ganz anders zu benutzen als meine C-API. Alleine deshalb wird jeder Code etwas anders aussehen.

Zum API-Design würde ich DRINGEND empfehlen, sich an John Hansens NXC oder notfalls auch an der RobotC API zu orientieren!
Einfache, prägnante, kurze Befehle, keine Romane für 1 Funktionsaufruf.
Also z.B. einfach

Code: Alles auswählen

On(port, pwm) // Motor: prozentuale Leistung, anschalten

Rotate(port, pwm, deg) // Motor: prozentuale Leistung, relative Drehung

RotateTo(port, pwm, deg) // Motor: prozentuale Leistung, absolutes Encoder-Ziel

RotatePID(port, pwm, deg, Kp, Ki, Kd, hold) // Motor: prozentuale Leistung, relat. Drehung, PID-Konst., hold/release

RotatePIDTo(port, pwm, deg, Kp, Ki, Kd, hold) // Motor: prozentuale Leistung, abs. Ziel, PID-Konst., hold/release

Off(port) // Motor ausschalten (stromlos = coast)

Brake(port) // Motor bremsen (Strombremse)

SetSensor(port, type, mode) // Sensor an Port X = ADC, I2C, UART, ggf. spezielle Betriebsart (raw, pulse, RGB, colortype)

ReadSensor(port,  * value) // lies Werte-Array von Sensor an Port X

// Anm.: für hold/release könnte man eine enum vorsehen ( nach Erreichen des Ziels), z.B. für
"hold" = ständige Anpassung/Verfolgung
"coast" = Abschalten auf stromlos
"brake" = aktive Strombremse

Tja, das Problem ist: Es geht hier nicht um eine Spezialsprache für Roboter. Es wird er GCC benutzt und der kann beliebige Bibliotheken dazulinken. Man nutzt etwas längere Funktionsaufrufe, um Doppelungen mit anderen Bibliotheken zu vermeiden und den Code für Außenstehende, die vielleicht gar keine Ahnung von der API haben, verständlich zu machen. On(port, pwm) z.B. ist sehr uneindeutig. Was wird auf an gestellt? Eine LED? Ein Motor? Ein Sensor? (Du hast es erklärt, aber selbsterklärender Code ist immer besser als Code + Kommentar).

Ich selber jedenfalls brenne darauf, mein BP-net auf Ev3 zu portieren, es läuft inzwischen schon fast perfekt auf meinem DUE
http://www.mindstormsforum.de/viewtopic.php?f=70&t=6620&p=66151#p67035
- nur leider ohne preemptives Multitasking und mit absolut ausgereiztem RAM, das wäre jetzt per EVTHREE der notwendige "NeXT step"... 8-)

Ich habe den Thread jetzt nur überflogen (lies: Die Bildchen angeguckt), aber es erstaunt mich, dass du einerseits solch komplexen Netze programmierst, aber andererseits auf Windows XP + Daisy Chaining + "Alles muss erklickbar und automatisch sein" pochst. O_o

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5399
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: ev3dev: C für EV3

Beitragvon HaWe » 10. Mai 2015 10:51

Ich habe den Thread jetzt nur überflogen (lies: Die Bildchen angeguckt), aber es erstaunt mich, dass du einerseits solch komplexen Netze programmierst, aber andererseits auf Windows XP + Daisy Chaining + "Alles muss erklickbar und automatisch sein" pochst. O_o


das ist kein Widerspruch, sondern genau der Grund, warum es funktioniert:

Nachdem ich 15 Jahre NQC und NXC (und 10 Jahre vorher Fischertechnik mit Turbo-C und -Pascal ) verwendet habe, konnte ich den Umgang mit Arduinos und Sketch/Wiring innerhalb von 4 Monaten lernen, weil alles so intuitiv einfach geht.
Ich konnte mich aufs Programmieren meiner Algorithmen konzentrieren, ohne mich mit verwurstelten OS-, IDE- und API-Problemen herumschlagen zu müssen.

Erinnere dich mal ein wenig zurück: Der Ev3 kam vor etwa 2-3 Jahren heraus.
Welche nennenswerten Projekte wurden seitdem mit dem EV3 per Text-Progammierung von Nicht-Profis gemacht?
(ich meine Dinge, die über die bekannten NXC-Projekte wie Linefollower mal ein wenig hinausgingen...)
Ich kenne kein einziges.
Selbst David Gilday's EV3 Mindcuber basiert auf Bildchen-Programmierung, und es gab ihn ja bereits für NXC/NXT !

Und welche nennenswerten Projekte wurden seitdem oder kurz vorher mit dem NXT per nxtOSEK-Progammierung gemacht?
(unser Martin0x5E mal außen vor -) ich kenne kein einziges.

Warum wohl?

Ich wage die Prophezeiung:
Wenn sich ev3dev nicht auf das Programmierniveau von ev3Basic und NXC begibt (per Installation, IDE und API), dann wird es selber "runter stürzen wie ein bleierner Zeppelin" - genau wie nxtOSEK.

Es wird ein Nischendasein führen, ausschließlich für Linux-Nerds und Hardware-Hacker.

ps, edit:
auch John Hansen hat eine simple und leicht zu installierende IDE für GCC zur Verfügung gestellt und eine NQC-ähnliche API für GCC erstellt, immerhin für Motoren, Buttons, Sound und Screen, das kann also letztendlich kein Hinderungsgrund gewesen sein.
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E


Zurück zu „textbasierte Programmiersoftware“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 16 Gäste

Lego Mindstorms EV3, NXT und RCX Forum : Haftungsauschluss