BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
genemroz
Pyrite | Level 9

Esteemed Advisers:

Once again I turn to you for advice...

The mission (should you choose to accept it) is to calculate the angle between two cameras and one target that is within the field of view of both cameras. The complicating factor is that any target may be within the field of view of multiple (up to 10) cameras. So it is necessary to perform the calculation for all possible camera combinations for each target.

Below is the code developed so far.

Dataset TargetList contains the Target ID (Target), the Cartesian coordinates of the Target (Tx, Ty, Tz) followed by (COL1-COL10) 2-10 cameras that have the target in view.

Dataset CameraList contains the Camera ID (Camera) and the Cartesian coordinates of the cameras (xpos, ypos,zpos).

I created 3 user-defined formats from CameraList for use as lookup tables when calculating the convergence angle.

This works well enough for calculating the angle between the first two cameras (COL1 and COL2) but I don't know how to efficiently obtain a result for all possible pair combinations for each target. In the worst-case scenario, where one Target is within the field of view of 10 cameras, I believe there are 45 possible pair combinations and I need to calculate the convergence angle for all 45 possibilities.

All suggestions, guidance or advice is welcomed.

Regards,

Gene

 

Data TargetList;
input Target Tx Ty Tz COL1$ COL2$ COL3$ COL4$ COL5$ COL6$ COL7$ COL8$ COL9$ COL10$;
DATALINES;
15091 -160 -160 100 US0009 US000R . . . . . . . .
15026 0 -170 100 US0005 US0009 US000H . . . . . . .
30980 -30 180 120 US0008 US000J US000L US001L . . . . . .
30600 30 120 120 US0006 US0008 US000H US000J US0001L . . . . .
29273 -90 -30 120 US0004 US000D US000J US000K US000P US000R . . . .
30417  10 110 120 US0007 US0008 US000H US000J US000K US000L US001L . . .
9443 60 -50 90 US0003 US0004 US0005 US000C US000E US000H US000M US000N . .
3439 -40 20 80 US0001 US0004 US000A US000D US000H US000J US000K US000L US000P .
3522 -20 30 80 US0001 US0004 US0007 US0008 US000A US000H US000J US000K US000L US000P
;
run;
Data CameraList;
input Camera$ xpos ypos zpos;
datalines;
US0001 -5 -5 2
US0002 -5 -5 2
US0003 -26 -114 2
US0004 58 57 1
US0005 39 -6 2
US0006 11 5 2
US0007 -4 11 2
US0008 -11 -33 1
US0009 -11 -33 2
US000A -9 -52 1
US000C -55 -110 2
US000D -4 2 2
US000E -5 -5 2
US000G -19 -65 1
US000H -158 -82 2
US000J -55 -106 2
US000K -26 -115 2
US000L 56 67 1
US000M 39 -6 2
US000N 11 5 2
US000P -3 11 2
US000R -11 -33 2
US001L -30 300 2
;
/*Create Format for xpos from dataset*/
data xposlist(
keep = fmtname type start label);
retain fmtname 'xposfmt' type 'C';
set cameralist end=lastrec;
start = camera; label=put(xpos,6.1);
output;
run;
proc format cntlin=xposlist library=work;
run;
/*Create Format for ypos from dataset*/
data yposlist(
keep = fmtname type start label);
retain fmtname 'yposfmt' type 'C';
set cameralist end=lastrec;
start = camera; label=put(ypos,6.1);
output;
run;
proc format cntlin=yposlist library=work;
run;
/*Create Format for zpos from dataset*/
data zposlist(
keep = fmtname type start label);
retain fmtname 'zposfmt' type 'C';
set cameralist end=lastrec;
start = camera; label=put(zpos,6.1);
output;
run;
proc format cntlin=zposlist library=work;
run;
/*Calculate Convergence Angle*/
Data output (Drop=Tx Ty Tz Vx1 Vy1 Vz1 Vx2 Vy2 Vz2 Num Den);
Set targetlist;
/* Vector from COL1 to T */
Vx1=Put(COL1,xposfmt.)-Tx;
Vy1=Put(COL1,yposfmt.)-Ty;
Vz1=Put(COL2,zposfmt.)-Tz;
/* Vector from COL2 to T */
Vx2=Put(COL2,xposfmt.)-Tx;
Vy2=Put(COL2,yposfmt.)-Ty;
Vz2=Put(COL2,zposfmt.)-Tz;
/* Angle between vectors COL1-T and COL2-T*/
Num=(Vx1*Vx2)+(Vy1*Vy2)+(Vz1*Vz2);
Den=sqrt(Vx1**2 +Vy1**2+Vz1**2)*sqrt(Vx2**2 +Vy2**2+Vz2**2);
Theta=arcos(num/den)*180/constant('Pi');
run;


 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
ErikLund_Jensen
Rhodochrosite | Level 12

Hi @genemroz 

The simplest way is to place the list of cameras in an array and transverse the array so all combinations are covered. I think the code below does it.

It seems to me that there is a typing error in your calculation, so Vz1 should be derived from Col1 and not Col2 as coded. I have changed it in my code.

And please note that you have typed an unknown camera in the list for Target 30600. It should be US001L and not US0001L. Also changed.

Data TargetList;
input Target Tx Ty Tz COL1$ COL2$ COL3$ COL4$ COL5$ COL6$ COL7$ COL8$ COL9$ COL10$;
DATALINES;
15091 -160 -160 100 US0009 US000R . . . . . . . .
15026 0 -170 100 US0005 US0009 US000H . . . . . . .
30980 -30 180 120 US0008 US000J US000L US001L . . . . . .
30600 30 120 120 US0006 US0008 US000H US000J US001L . . . . .
29273 -90 -30 120 US0004 US000D US000J US000K US000P US000R . . . .
30417  10 110 120 US0007 US0008 US000H US000J US000K US000L US001L . . .
9443 60 -50 90 US0003 US0004 US0005 US000C US000E US000H US000M US000N . .
3439 -40 20 80 US0001 US0004 US000A US000D US000H US000J US000K US000L US000P .
3522 -20 30 80 US0001 US0004 US0007 US0008 US000A US000H US000J US000K US000L US000P
;
run;
Data CameraList;
input Camera$ xpos ypos zpos;
datalines;
US0001 -5 -5 2
US0002 -5 -5 2
US0003 -26 -114 2
US0004 58 57 1
US0005 39 -6 2
US0006 11 5 2
US0007 -4 11 2
US0008 -11 -33 1
US0009 -11 -33 2
US000A -9 -52 1
US000C -55 -110 2
US000D -4 2 2
US000E -5 -5 2
US000G -19 -65 1
US000H -158 -82 2
US000J -55 -106 2
US000K -26 -115 2
US000L 56 67 1
US000M 39 -6 2
US000N 11 5 2
US000P -3 11 2
US000R -11 -33 2
US001L -30 300 2
;
/*Create Format for xpos from dataset*/
data xposlist(
	keep = fmtname type start label);
	retain fmtname 'xposfmt' type 'C';
	set cameralist end=lastrec;
	start = camera; label=put(xpos,6.1);
	output;
run;
proc format cntlin=xposlist library=work;
run;
/*Create Format for ypos from dataset*/
data yposlist(
	keep = fmtname type start label);
	retain fmtname 'yposfmt' type 'C';
	set cameralist end=lastrec;
	start = camera; label=put(ypos,6.1);
	output;
run;
proc format cntlin=yposlist library=work;
run;
/*Create Format for zpos from dataset*/
data zposlist(
	keep = fmtname type start label);
	retain fmtname 'zposfmt' type 'C';
	set cameralist end=lastrec;
	start = camera; label=put(zpos,6.1);
	output;
run;
proc format cntlin=zposlist library=work;
run;

/*Calculate Convergence Angle*/
Data output3 (keep=Target Camera1 Camera2 Theta);
	Set targetlist;
	array camera $ col1-col10;
	do i = 1 to 9;
		do j = i+1 to 10;

			camera1 = camera{i}; 
			camera2 = camera{j};

			if camera2 ne '' then do;
				/* Vector from camera1 to T */
				Vx1=input(put(camera{i},xposfmt.),8.)-Tx;
				Vy1=input(put(camera{i},yposfmt.),8.)-Ty;
				Vz1=input(put(camera{i},zposfmt.),8.)-Tz;

				/* Vector from camera2 to T */
				Vx2=input(put(camera{j},xposfmt.),8.)-Tx;
				Vy2=input(put(camera{j},yposfmt.),8.)-Ty;
				Vz2=input(put(camera{j},zposfmt.),8.)-Tz;

				/* Angle between vectors camera1-T and camera2-T*/
				Num=(Vx1*Vx2)+(Vy1*Vy2)+(Vz1*Vz2);
				Den=sqrt(Vx1**2 +Vy1**2+Vz1**2)*sqrt(Vx2**2 +Vy2**2+Vz2**2);
				Theta=arcos(num/den)*180/constant('Pi');

				output;
			end;
		end;
	end;
run;

View solution in original post

2 REPLIES 2
ErikLund_Jensen
Rhodochrosite | Level 12

Hi @genemroz 

The simplest way is to place the list of cameras in an array and transverse the array so all combinations are covered. I think the code below does it.

It seems to me that there is a typing error in your calculation, so Vz1 should be derived from Col1 and not Col2 as coded. I have changed it in my code.

And please note that you have typed an unknown camera in the list for Target 30600. It should be US001L and not US0001L. Also changed.

Data TargetList;
input Target Tx Ty Tz COL1$ COL2$ COL3$ COL4$ COL5$ COL6$ COL7$ COL8$ COL9$ COL10$;
DATALINES;
15091 -160 -160 100 US0009 US000R . . . . . . . .
15026 0 -170 100 US0005 US0009 US000H . . . . . . .
30980 -30 180 120 US0008 US000J US000L US001L . . . . . .
30600 30 120 120 US0006 US0008 US000H US000J US001L . . . . .
29273 -90 -30 120 US0004 US000D US000J US000K US000P US000R . . . .
30417  10 110 120 US0007 US0008 US000H US000J US000K US000L US001L . . .
9443 60 -50 90 US0003 US0004 US0005 US000C US000E US000H US000M US000N . .
3439 -40 20 80 US0001 US0004 US000A US000D US000H US000J US000K US000L US000P .
3522 -20 30 80 US0001 US0004 US0007 US0008 US000A US000H US000J US000K US000L US000P
;
run;
Data CameraList;
input Camera$ xpos ypos zpos;
datalines;
US0001 -5 -5 2
US0002 -5 -5 2
US0003 -26 -114 2
US0004 58 57 1
US0005 39 -6 2
US0006 11 5 2
US0007 -4 11 2
US0008 -11 -33 1
US0009 -11 -33 2
US000A -9 -52 1
US000C -55 -110 2
US000D -4 2 2
US000E -5 -5 2
US000G -19 -65 1
US000H -158 -82 2
US000J -55 -106 2
US000K -26 -115 2
US000L 56 67 1
US000M 39 -6 2
US000N 11 5 2
US000P -3 11 2
US000R -11 -33 2
US001L -30 300 2
;
/*Create Format for xpos from dataset*/
data xposlist(
	keep = fmtname type start label);
	retain fmtname 'xposfmt' type 'C';
	set cameralist end=lastrec;
	start = camera; label=put(xpos,6.1);
	output;
run;
proc format cntlin=xposlist library=work;
run;
/*Create Format for ypos from dataset*/
data yposlist(
	keep = fmtname type start label);
	retain fmtname 'yposfmt' type 'C';
	set cameralist end=lastrec;
	start = camera; label=put(ypos,6.1);
	output;
run;
proc format cntlin=yposlist library=work;
run;
/*Create Format for zpos from dataset*/
data zposlist(
	keep = fmtname type start label);
	retain fmtname 'zposfmt' type 'C';
	set cameralist end=lastrec;
	start = camera; label=put(zpos,6.1);
	output;
run;
proc format cntlin=zposlist library=work;
run;

/*Calculate Convergence Angle*/
Data output3 (keep=Target Camera1 Camera2 Theta);
	Set targetlist;
	array camera $ col1-col10;
	do i = 1 to 9;
		do j = i+1 to 10;

			camera1 = camera{i}; 
			camera2 = camera{j};

			if camera2 ne '' then do;
				/* Vector from camera1 to T */
				Vx1=input(put(camera{i},xposfmt.),8.)-Tx;
				Vy1=input(put(camera{i},yposfmt.),8.)-Ty;
				Vz1=input(put(camera{i},zposfmt.),8.)-Tz;

				/* Vector from camera2 to T */
				Vx2=input(put(camera{j},xposfmt.),8.)-Tx;
				Vy2=input(put(camera{j},yposfmt.),8.)-Ty;
				Vz2=input(put(camera{j},zposfmt.),8.)-Tz;

				/* Angle between vectors camera1-T and camera2-T*/
				Num=(Vx1*Vx2)+(Vy1*Vy2)+(Vz1*Vz2);
				Den=sqrt(Vx1**2 +Vy1**2+Vz1**2)*sqrt(Vx2**2 +Vy2**2+Vz2**2);
				Theta=arcos(num/den)*180/constant('Pi');

				output;
			end;
		end;
	end;
run;
genemroz
Pyrite | Level 9
Erik,
Thanks so much for this solution! I was pretty certain that an array was the way to go but didn't know how to get there. I apologize for my typos that you graciously fixed for me. I"m marking this solution as "Accepted".
Thanks,
Gene

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 2 replies
  • 889 views
  • 1 like
  • 2 in conversation