1 van 1

[matlab] probleem met loops

Geplaatst: di 17 sep 2013, 21:48
door jppilot
Beste allemaal,

Ik heb een probleem met loops in het programma matlab. Het volgende is de vraag:

Code: Selecteer alles


%Een compacte weergave van de radarcontacten in de omgeving van het schip is het tactisch plot.

%In dit plot kan in één oogopslag gezien worden wat de classificatie van de verschillende

%contacten is (vriend, vijand, ...) en waar de contacten zich bevinden. Tevens is het identificatie

%nummer van elk contact gegeven. In een modern systeem wordt het tactisch plot op een

%computerbeeldscherm gepresenteerd en is het gekoppeld aan verschillende databases. Hierdoor

%kan bijvoorbeeld snel extra informatie over een contact worden verkregen door erop te klikken.

%Gegeven

%Een lijst (array) van contacten (elke regel is één contact) met identificatienummer (ID, 1ste kolom), x- en y-coördinaten

%(in nm; 2de en 3de kolom) en hun IFF-reeks (4de kolom). In tegenstelling tot voorbeeldopgave D (IFF), is de IFF-reeks

%in deze opgave één getal, bijvoorbeeld 10110, waarbij de opeenvolgende ‘bits’ overeenkomen met modes 1, 2, 3a, 3c en 4.

clear all; clc;

%		  ID X  Y  IFF

INVOER = [1 100 70 00100;	% contact 1, etc.

   2 100 -60 11000;

   3 50 100 00110;

   4 -50 60 00101;

   5 -50 -100 00110;

   6 100 40 00010];

A=INVOER(1,4);  

for i =[5:-1:1];

  IFF1(i)=rem(A,10);  % IFF staat voor identificatie Friend or Foe (vriend of vijand)

  A =fix(A/10);

 end;

B=INVOER(2,4);

  for i =[5:-1:1];

  IFF2(i)=rem(B,10);

  B =fix(B/10);

  end;

C=INVOER(3,4);

  for i =[5:-1:1];

  IFF3(i)=rem(C,10);

  C =fix(C/10);

  end;

D=INVOER(4,4);

  for i =[5:-1:1];

  IFF4(i)=rem(D,10);

  D =fix(D/10);

  end;

E=INVOER(5,4);

  for i =[5:-1:1];

  IFF5(i)=rem(E,10);

  E =fix(E/10);

  end;

F=INVOER(6,4);

  for i =[5:-1:1];

  IFF6(i)=rem(F,10);

  F =fix(F/10);

  end;

IFF = [IFF1;IFF2;IFF3;IFF4;IFF5;IFF6];

CONTACT=IFF;  

for i=1:size(CONTACT,1)

   IFF=decode(CONTACT(i,1),CONTACT(i,2),CONTACT(i,3),CONTACT(i,4),CONTACT(i,5));

   disp(['De IFF van contact ' num2str(i) ' is ' IFF '.'])

end

En de locale functie 'decode':

Code: Selecteer alles


function [bericht] = decode(mode1,mode2,mode3a,mode3c,mode4)

% Decoder het IFF bericht (zie inleidende tekst in 'IFF')

reeks = [mode1 mode2 mode3a mode3c mode4];

if sum( (reeks==1)|(reeks==0) )~=5

   errordlg('Fout in de IFF-code: niet binair!');   % fout in de code

end

if mode4

   bericht = 'FRIEND';

elseif (mode3a)&(mode3c)

   bericht = 'NEUTRAL';

elseif mode3c % houdt impliet in dat IFF niet mode4 of mode3a bevat

   bericht = 'ASSUMED NEUTRAL';

else

   bericht = 'FOE';

end

Mijn vraag is hoe het gedeelte van:

A=INVOER(1,4);

for i =[5:-1:1];

IFF1(i)=rem(A,10);

A =fix(A/10);

end;

makkelijker gedaan kan worden zodat hij deze berekening voor [:,4] bij invoer doet. Oftewel zodat er ook een lijst aangeleverd kan worden van 4 of 8 rijen. Vervolgens moet er van deze resultaten vanzelf een matrix gegenereerd worden in de trand van: IFF = [IFF1;IFF2;IFF3;IFF4;IFF5;IFF6]; etc naar gelange het aantal IFF's.

Iemand een idee?

Re: [matlab] probleem met loops

Geplaatst: wo 18 sep 2013, 14:25
door EvilBro
Je zou zoiets kunnen doen:

Code: Selecteer alles

IFF = mod(fix((INVOER(:,4)*ones(1,5))./(ones(size(INVOER(:,4)))*(10.^[4:-1:0]))),10);
De vraag is natuurlijk of het daar duidelijker van wordt...

Re: [matlab] probleem met loops

Geplaatst: wo 18 sep 2013, 19:17
door jppilot
Nee dat had ik niet zelf kunnen bedenken... Enorm bedankt, zou u deze formule kort kunnen uitleggen?

Re: [matlab] probleem met loops

Geplaatst: wo 18 sep 2013, 20:44
door jppilot
Stapje verder, en weer een vraag waar ik geen oplossing in zie...

De code is nu als volgt:

Code: Selecteer alles


clear all; clc;

%		  ID X  Y  IFF

INVOER = [1 100 70 00100;	% contact 1, etc.

   2 100 -60 11000;

   3 50 100 00110;

   4 -50 60 00101;

   5 -50 -100 00110;

   6 100 40 00010];

  

IFF1 = mod(fix((INVOER(:,4)*ones(1,5))./(ones(size(INVOER(:,4)))*(10.^[4:-1:0]))),10);

for i=1:size(IFF1,1)

   IFF=decode(IFF1(i,1),IFF1(i,2),IFF1(i,3),IFF1(i,4),IFF1(i,5));

   disp(['De IFF van contact ' num2str(i) ' is ' IFF '.'])

end

[theta,r]=cart2pol(INVOER(:,2),INVOER(:,3)); % omzetten naar polar coordinaten voor alle x en y coordinaten

polar(theta,r,'+')

Vervolgens moet er een polarplot gemaakt worden zoals als volgt, waarbij het getal staat voor het ID, en de symbolen aangeven om wat voor contact het gaat.

Afbeelding

greenshot download

Zelf heb ik nu dit, wat logisch volgt uit mijn code. Echter heb ik geen idee hoe ik de code zó moet maken dat het niet uitmaakt hoe groot je invoer is. Ook het teken bij de contacten variabel maken (+. o, driehoek, * ) lukt mij niet.

Afbeelding

photo sharing websites

Re: [matlab] probleem met loops

Geplaatst: do 19 sep 2013, 10:35
door EvilBro
Nee dat had ik niet zelf kunnen bedenken... Enorm bedankt, zou u deze formule kort kunnen uitleggen?
Dat zou ik kunnen doen, maar ik denk dat het zinniger is als je zelf een beetje gaat experimenteren. Kijk bijvoorbeeld eens wat delen doen, zoals:

Code: Selecteer alles

INVOER(:,4)*ones(1,5) 
Zo kom je er zelf achter wat er precies gebeurt.

Ik ben overigens van mening dat je je programma verkeerd hebt opgezet. Ik zou hem zo maken dat je aan decode() gewoon het getal kan geven (of een array van getallen) en dat in decode() dit getal ontbonden wordt en omgezet naar de 'kleurcodering' die je nodig hebt voor het commando 'polar'. Informatie over de kleuren en zo kun je op internet wel vinden (bijvoorbeeld hier).

Re: [matlab] probleem met loops

Geplaatst: do 19 sep 2013, 15:23
door jppilot
Heb je gelijk in, echter mogen we de functie decode() niet aanpassen in het kader van de opdracht :) Bedankt voor de hulp!

Re: [matlab] probleem met loops

Geplaatst: do 19 sep 2013, 16:05
door EvilBro
Mag je wel een extra functie schrijven? Bijvoorbeeld:

Code: Selecteer alles


function [ ret ] = myDecode (iff)

	bits = mod(fix((iff*ones(1,5))./(10.^[4:-1:0])),10);

	state = decode(bits(1),bits(2),bits(3),bits(4),bits(5));

	switch state

		case 'FRIEND'

			ret = 'b*';

		case 'NEUTRAL'

			ret = 'g+';

		case 'ASSUMED NEUTRAL'

			ret = 'yo';

		case 'FOE'

			ret = 'r^';

		otherwise

			ret = 'k.';

	end

endfunction

Dan kun je iets als dit:

Code: Selecteer alles


	invoer = [1 100 70 00100;	   % contact 1, etc.

				   2 100 -60 11000;

				   3 50 100 00110;

				   4 -50 60 00101;

				   5 -50 -100 00110;

				   6 100 40 00010];



	figure;

	hold on;

	for i = 1:1:size(invoer,1),

		[t,r] = cart2pol(invoer(i,2:3));

		polar(t,r,myDecode(invoer(i,4)));

	end				  


Re: [matlab] probleem met loops

Geplaatst: do 19 sep 2013, 21:57
door jppilot
Hm dat was ook een goede oplossing geweest ja. Even geprobeerd en lijkt perfect te werken, snap alleen niet waarom ik tóch een vierkante afbeelding te zien krijg ipv een polar. Raar want de punten worden verder ook niet perfect ingetekend.

Code: Selecteer alles


clear all; clc;

invoer = [1 100 70 00100;		  % contact 1, etc.

   2 100 -60 11000;

   3 50 100 00110;

   4 -50 60 00101;

   5 -50 -100 00110;

   6 100 40 00010];

    figure;

    hold on;

    for i = 1:1:size(invoer,1),

    [t,r] = cart2pol(invoer(i,2),invoer(i,3));

    polar(t,r,myDecode(invoer(i,4)));

    end

 

Code: Selecteer alles


function [ ret ] = myDecode (iff)

    bits = mod(fix((iff*ones(1,5))./(10.^[4:-1:0])),10);

   

    state = decode(bits(1),bits(2),bits(3),bits(4),bits(5));

    switch state

    case 'FRIEND'

    ret = 'b*';

    case 'NEUTRAL'

    ret = 'g+';

    case 'ASSUMED NEUTRAL'

    ret = 'yo';

    case 'FOE'

    ret = 'r^';

    otherwise

    ret = 'k.';

    end

zelf heb ik het ondertussen opgelost volgens onderstaand:

Code: Selecteer alles


clear all; clc;

%		  ID X  Y  IFF

INVOER = [1 100 70 00100;    % contact 1, etc.

   2 100 -60 11000;

   3 50 100 00110;

   4 -50 60 00101;

   5 -50 -100 00110;

   6 100 40 00010];

  

IFF1 = mod(fix((INVOER(:,4)*ones(1,5))./(ones(size(INVOER(:,4)))*(10.^[4:-1:0]))),10); % omzetten van binair naar 'losse' enen en nullen.

for i=1:size(IFF1,1)

   IFF=decode(IFF1(i,1),IFF1(i,2),IFF1(i,3),IFF1(i,4),IFF1(i,5));

   [theta,r]=cart2pol(INVOER(i,2),INVOER(i,3)); % omzetten naar polar coordinaten voor alle x en y coordinaten

   if strcmp(IFF,'FOE');

  polar(theta,r,'^r')

   elseif strcmp(IFF,'NEUTRAL');

  polar(theta,r,'+g')

   elseif strcmp(IFF,'FRIEND');

  polar(theta,r,'*b')

   elseif strcmp(IFF,'ASSUMED FRIEND');

  polar(theta,r,'oc')

   end

   disp(['De IFF van contact ' num2str(i) ' is ' IFF '.'])

   hold on;

end

Toch pittig om dit soort talen te leren. Het voelt alsof je je uren afvraagt hoe je een spijker in de muur kan slaan, om er vervolgens achter te komen dat je gewoon een hamer in je gereedschapskist hebt...

Re: [matlab] probleem met loops

Geplaatst: vr 20 sep 2013, 08:21
door EvilBro
Even geprobeerd en lijkt perfect te werken, snap alleen niet waarom ik tóch een vierkante afbeelding te zien krijg ipv een polar.
Ik vermoed dat dit komt omdat ik "figure;hold on" gedaan heb. Ik kan dit echter niet controleren omdat ik Octave gebruik ipv Matlab en het gedrag daar net even anders is. Ik vermoed dat het volgende wel werkt:

Code: Selecteer alles

clear all; clc;

invoer = [1 100 70 00100;

 % contact 1, etc.

2 100 -60 11000;

3 50 100 00110;

4 -50 60 00101;

5 -50 -100 00110;

6 100 40 00010];

for i = 1:1:size(invoer,1),

[t,r] = cart2pol(invoer(i,2),invoer(i,3));

polar(t,r,myDecode(invoer(i,4)));

hold on;

end

  

Toch pittig om dit soort talen te leren. Het voelt alsof je je uren afvraagt hoe je een spijker in de muur kan slaan, om er vervolgens achter te komen dat je gewoon een hamer in je gereedschapskist hebt...
Dat klopt. Zeker omdat er al heel veel functies bestaan. Ik heb zelf ook al diverse malen het wiel opnieuw uitgevonden om er vervolgens achter te komen dat het wiel al bestond en nog in een betere vorm ook.

Ik heb toch nog wel een tip over je programmeerstijl. Bekijk mijn programma. Door het opsplitsen in twee functies wordt het geheel overzichtelijker. In het hoofdprogramma kun je heel simpel zien dat de invoer rij voor rij wordt geplot in een polar-diagram. Doordat de conversie van de IFF 'verstopt' zit in myDecode, vertroebelt dit het beeld niet.

Bekijk nu jouw programma. Doordat je al het werk in dezelfde file doet, is het minder makkelijk om snel te zien wat er gebeurt. De grote vraag is bij dat soort code, zeker de oneliner die ik voor je bedacht heb met IFF, of je over een jaar nog weet wat dit ook alweer deed.

Verder is het volgende stukje niet zo mooi:

Code: Selecteer alles


   if strcmp(IFF,'FOE');

  polar(theta,r,'^r')

   elseif strcmp(IFF,'NEUTRAL');

  polar(theta,r,'+g')

   elseif strcmp(IFF,'FRIEND');

  polar(theta,r,'*b')

   elseif strcmp(IFF,'ASSUMED FRIEND');

  polar(theta,r,'oc')

   end

Ten eerste denk ik dat een switch-case structuur duidelijker is. Ten tweede doe je voor elke optie eigenlijk hetzelfde. Bij alle opties plot je een polar. Dat de actie bij alle opties eigenlijk hetzelfde is heb je echter verstopt door bij elke optie opnieuw te vertellen wat je gaat doen. Vergelijk dit bijvoorbeeld met:

Code: Selecteer alles


   pl = '.k';

   if strcmp(IFF,'FOE');

  pl = '^r';

   elseif strcmp(IFF,'NEUTRAL');

  pl ='+g';

   elseif strcmp(IFF,'FRIEND');

  pl ='*b';

   elseif strcmp(IFF,'ASSUMED FRIEND');

  pl ='oc';

   end

   polar(theta,r,pl)

De omschrijving van dit stukje code is: 'zoek uit welk label het punt heeft en plot dan dat punt.'

Re: [matlab] probleem met loops

Geplaatst: vr 20 sep 2013, 18:31
door Xenion
Nog even terzijde:

De code waarmee EvilBro jouw probleem op 1 lijntje oplost is mooi. De filosofie in MATLAB is ook om zoveel mogelijk met matrix-bewerkingen te doen, MATLAB is namelijk geoptimaliseerd om 'vectorized' code uit te voeren.

Het vergt echter veel inzicht in het probleem en in matrix/vector rekening om je code op die manier te kunnen schrijven. Jij bent duidelijk zover nog niet, maar wat je wél zou moeten zien is het repetitieve karakter van je code. Je voert letterlijk 6 keer dezelfde code uit, zij het met andere namen voor variabelen.

Een betere manier zou zijn:

Code: Selecteer alles


N = size(INVOER,1); % aantal rijen invoer

IFF = zeros(N,5); % pre-alloceer de matrix waar je het resultaat in wegschrijft

for i = 1:N

    % voer hier die repetitieve code uit en schrijf telkens je resultaat naar IFF(i, :) 

end

Dat 'pre-alloceren' is een gewoonte die je best aanneemt in MATLAB. Je kan code schrijven waarin je dingen zegt als:

Code: Selecteer alles


x = 0;

for i = 1:10

    x = [x;0];

end

Bij elke iteratie wordt de vector x langer. Dat betekent dat MATLAB bij elke iteratie een nieuw stuk geheugen moet reserveren en alle oude data daarnaar moet verplaatsen. Als je ooit met grote vectoren werkt, dan zal je merken dat je scripts erg traag worden op deze manier.