Linking Sensors
|
|
Silent Bock
Registered User
Join date: 4 May 2006
Posts: 8
|
05-11-2006 08:18
Hey I am pretty new to SL, and to the scripting side of things, and have searched the wiki and the forums a lot and can't find a helpful solution ( unless I am searching wrong  ). I have a prim that searches and constructs a list of peoples names in a certain area. It works great. Alas, the problem comes when there are more than 16 people in that area, because llSensor won't count any higher than 16. So I figure I will need to have two prims, both searching at different angles to get more than 16 people. Then we look at the results, remove any duplicates and yay! it works. I figure the limit to this will be 32 presuming they are both search semispheres. The only problem is I have NO clue how to do this. I have looked at the example code of linking objects and found nothing that could help, atleast with my knowledge of scripting  . I was wondering if anyone could help me with this? or tell me I have the totally wrong end of a stick about detecing more than 16 people in an area  Also, aside from the wiki and these forums, is there a better collection of documentation availible for the SL scripting langague? Thanks in advance 
|
|
Starax Statosky
Unregistered User
Join date: 23 Dec 2003
Posts: 1,099
|
05-11-2006 08:44
I'm not sure about this. But I think if there are more than 16 items of the required type within range, then llSensorRepeat() will return a different list of items each time. So if there's 32 avatars within range, it'll return the first 16 on the first event and the remaining 16 on the next. Please let me know if I'm right. I can't be bothered testing it myself. Sorry! 
|
|
Llauren Mandelbrot
Twenty-Four Weeks Old.
Join date: 26 Apr 2006
Posts: 665
|
05-11-2006 08:56
From: Starax Statosky I'm not sure about this. But I think if there are more than 16 items of the required type within range, then llSensorRepeat() will return a different list of items each time. So if there's 32 avatars within range, it'll return the first 16 on the first event and the remaining 16 on the next. Please let me know if I'm right. I can't be bothered testing it myself. Sorry!  I don`t think it works this way, but it shure would be cool if it did! Somebody feature-suggest this if it isn`t already the case, please. I cannot test this until after my new hardware arrives [promised next Tuesday evening]. Toodle-oo!
|
|
Silent Bock
Registered User
Join date: 4 May 2006
Posts: 8
|
05-11-2006 09:03
Thanks for the rapid response peeps  An alas no llSensorRepeat() doesn't seem to do that 
|
|
Llauren Mandelbrot
Twenty-Four Weeks Old.
Join date: 26 Apr 2006
Posts: 665
|
Better llSensorRepeat?
05-11-2006 09:34
It`d be nice if there was some kind of flag telling llSensorRepeat() which group of sixteen hits to return, i.e., how many contacts to skip at the beginning of the scan. There would have to be some way of changing this on-the-fly for maximum utility. Toodle-oo!
|
|
Leonard Churchill
Just a Horse
Join date: 19 Oct 2005
Posts: 59
|
05-11-2006 10:09
You asked about linking sensors: I would not link the sensors in the traditional build/link way.
I would use listen/shout. Call one object the 'Control' and the other a 'Remote'. Have a filtered listener in the control, have a shout in the remote. The remote shouts the keys it's sensor detected. The control would hear it and merge that into its own list.
This method would allow you to have more remotes as needed. Remember that the control and remote must be in shout/listen range of each other. Take care with channel selection and duty cycle.
I have tried an approach to change the sensor sweep and 'slice' an area into 4 quarters to reduce the count (assumed: 64 avatars in one location would be a limit). This met with marginal results... as some targets kept moving in and out of my quarters. You may also see this with your 2 sensor approach.
An alternative to having multiple sensors would be to have a single sensor move/orbit a target area. It senses, it records, it moves, it repeats. Again, accuracy improves at the cost of time it takes to do a complete 'sweep'.
I have found that getting a fast, accurate, low-lag, never-ever-ever wrong count of avatars is not an easy thing, especially when trying to detect avatars in close proximity to each other (the most common example would be a dance floor).
Hope this helps. Feel free to IM me if you see me online with questions or script examples.
_____________________
"Give me a fish and I eat for a day. Teach me to fish and I eat for a lifetime." - Chinese Proverb Always check the Wiki and/or Script Library
|
|
Starax Statosky
Unregistered User
Join date: 23 Dec 2003
Posts: 1,099
|
05-11-2006 10:13
Yeah. I tested my theory and I didn't work. Sooo, what you can do is have your device slowly spin around and scan the area directly infront of it, just like a real radar!!! It'll look cool too! If you use your method of using two prims and 32 people are located to the left of your scanner, then both prims will still probably return the same 16 people.
|
|
Silent Bock
Registered User
Join date: 4 May 2006
Posts: 8
|
05-11-2006 11:36
Thanks for the suggestions, the problem is I have looked at various communication between prims sample scripts, and have no idea how to operate it properly. Hence my plea for more documentation  As for scanning radar like how about something like this ? search_for_people () { for ( i=0 ; i < 3 ; i++ ) { // rotate the prim by 90' // llSensorRepeat a cone 90' }
// sensor scan is done, list compiled
process_list (); }
////
sensor ( integer total_number ) { // sensor 'ping' from the radar
for ( i = 0; i <= total_numer; i++ ) {
// add llDetectedKey(i) to a global list } }
/////
process_list () {
// sort the list and remove duplicates
}
I just want to make sure I am actually getting the general idea of this  hence the pseudo code. Is this the correct kind of idea? Or am I being a complete noobie? 
|
|
Starax Statosky
Unregistered User
Join date: 23 Dec 2003
Posts: 1,099
|
05-11-2006 12:05
From: Silent Bock Thanks for the suggestions, the problem is I have looked at various communication between prims sample scripts, and have no idea how to operate it properly. Hence my plea for more documentation  As for scanning radar like how about something like this ? <code> I just want to make sure I am actually getting the general idea of this  hence the pseudo code. Is this the correct kind of idea? Or am I being a complete noobie?  Looks fine. I'd check the "global list" for the key using llListFindList() to see whether it's worth adding the sensed key, rather than process the list later.
|
|
Trep Cosmo
Registered User
Join date: 3 Mar 2005
Posts: 101
|
05-11-2006 12:35
Sensors return the closest 16 hits. If something moves between sensor events, then the list will change.
The best way to grab more than 16 hits is to array 6 sensors pointed along the 6 axes directions. Feed all the data into a central script and eliminate the duplicates.
_____________________
"There is no 'I' in team, but there is a 'Me' if you scramble it." -- House
|
|
Silent Bock
Registered User
Join date: 4 May 2006
Posts: 8
|
05-11-2006 12:36
Ok, I can't build in game at the moment (and this code might be helpful for others because I asked several people in game and no one had a clue) so how about filling out the pseudo code :
search_for_people () { for ( i=0 ; i < 3 ; i++ ) { // rotate the prim by 90' vector rot = <0,90,0>; eul *= DEG_TO_RAD; rotation quat = llEuler2Rot(eul); llSetRot(quat); / // llSensorRepeat a cone 90' llSensorRepeat ( "", NULL_KEY, AGENT, 50, PI_BY_TWO ) // get it in hemisphere, so there will be duplicates, but everywhere is covered }
// sensor scan is done, list compiled
process_list (); }
////
sensor ( integer total_number ) { // sensor 'ping' from the radar
// add llDetectedKey(i) to a global list for ( i = 0; i <= total_number; i++ ) { check_list = llListFind( global_key_list, llDetectedKey(i));
if ( check_list != -1 ) { global_key_list += [llDetectedKey(i)]; }
} }
/////
process_list () {
// do something with it
integer people_in_area = llGetListLength(global_key_list); llSay ( 0, "There are " + people_in_area + " people here" );
}
Again, am I on the right tracks ?
|
|
Starax Statosky
Unregistered User
Join date: 23 Dec 2003
Posts: 1,099
|
05-11-2006 13:12
From: Silent Bock Ok, I can't build in game at the moment (and this code might be helpful for others because I asked several people in game and no one had a clue) so how about filling out the pseudo code :
Again, am I on the right tracks ? Looking good. Although you'd want to change the llSensorRepeat for just llSensor in that code. But I'm sure you knew this, because you didn't put the repeat rate in at the end of the function.  Might be easier to just use llTargetOmega() with a slow spin and llSensorRepeat() with a slow rate. The code would be much shorter.
|
|
Silent Bock
Registered User
Join date: 4 May 2006
Posts: 8
|
05-11-2006 13:59
Ok, I have got it running after sorting out the awful pseudo code. The problem is it doesn't work. And I can't see anything wrong with it all : list gkl =[];
search_for_people () {
integer i;
for ( i = 0 ; i <= 3 ; i++ ) { // rotate the prim by 90' vector rot = <0,90,0>; rot *= DEG_TO_RAD; rotation quat = llEuler2Rot(rot); llSetRot(quat); llSay ( 0, "Sensor - " + (string)(i) + "!" ); llSleep ( 5 ); // sensor flood ? llSensor ( "", NULL_KEY, AGENT, 50, PI_BY_TWO ); // get it in hemisphere, so there will be duplicates, but everywhere is covered }
// sensor scan is done, list compiled
process_list (); }
////
process_list () {
// do something with it
integer people_in_area = llGetListLength(gkl); llSay ( 0, "There are " + (string)(people_in_area) + " people here" );
}
////
////
default { state_entry() { llSay (0, "Touch me!"); }
touch_start ( integer total_number ) { search_for_people(); }
sensor ( integer total_number ) { // sensor 'ping' from the radar llSay ( 0, "PING!" ); integer check_list; integer i; list little_list;
// add llDetectedKey(i) to a global list for ( i = 0; i <= total_number; i++ ) {
little_list = []; little_list = [ llDetectedKey(i) ]; check_list = llListFindList (gkl, little_list );
if ( check_list != -1 ) { gkl += [llDetectedKey(i)]; }
} }
/////
}
The output from this is : Sensor - 0! Sensor - 1! Sensor - 2! Sensor - 3! There are 0 people here PING! PING! Now looking at that code (and what I had in mind) I would have thought the output would be like this : Sensor - 0! PING! Sensor - 1! PING! Sensor - 2! PING! Sensor - 3! PING! There are 19 people here Am I totally mis-understanding the point ?
|
|
Starax Statosky
Unregistered User
Join date: 23 Dec 2003
Posts: 1,099
|
05-11-2006 14:42
From: Silent Bock Ok, I have got it running after sorting out the awful pseudo code. The problem is it doesn't work. And I can't see anything wrong with it all : Am I totally mis-understanding the point ? I see what's happening!! The sensor event is being queued up. So the actual event isn't processed until you come out of your current event. It's not like a typical function call. It doesn't get called immediately. We're gonna need a timer or a llSensorRepeat(). I'll be back!!! 
|
|
Llauren Mandelbrot
Twenty-Four Weeks Old.
Join date: 26 Apr 2006
Posts: 665
|
Try this...
05-11-2006 14:59
From: Silent Bock Ok, I have got it running after sorting out the awful pseudo code. The problem is it doesn't work. And I can't see anything wrong with it all: ...omitted for brevity... The output from this is : Sensor - 0! Sensor - 1! Sensor - 2! Sensor - 3! There are 0 people here PING! PING! Now looking at that code (and what I had in mind) I would have thought the output would be like this : Sensor - 0! PING! Sensor - 1! PING! Sensor - 2! PING! Sensor - 3! PING! There are 19 people here Am I totally mis-understanding the point ? Try this: list gkl =[]; integer ScanCount=0; search_for_people () { integer i; for ( i = 0 ; i <= 3 ; i++ ) { // rotate the prim by 90' vector rot = <0,90,0>; rot *= DEG_TO_RAD; rotation quat = llEuler2Rot(rot); llSetRot(quat); llSay ( 0, "Sensor - " + (string)(i) + "!" ); llSensor ( "", NULL_KEY, AGENT, 50, PI_BY_TWO ); // get it in hemisphere, so there will be duplicates, but everywhere is covered ScanCount += 1 llSleep ( 5 ); // sensor flood ? //Note changed position } } process_list () { // do something with it integer people_in_area = llGetListLength(gkl); llSay ( 0, "There are " + (string)(people_in_area) + " people here" ); } default { state_entry() { llSay (0, "Touch me!"); } } // Warning: I think you were missing an end-brace here. touch_start ( integer total_number ) { search_for_people(); } sensor ( integer total_number ) { // sensor 'ping' from the radar llSay ( 0, "PING! "+(string)total_number ); integer check_list; integer i; list little_list; // add llDetectedKey(i) to a global list for ( i = 0; i <= total_number; i++ ) { llSay("i="+(string)i) little_list = []; little_list = [ llDetectedKey(i) ]; check_list = llListFindList (gkl, little_list ); if ( check_list != -1 ) { llSay("Adding "+(string)llDetectedKey(i)) gkl += [llDetectedKey(i)]; } if ( --ScanCount ) { process_list(); } } } }
Ack! I tried to format it nicely, but the formatting doesn`t seem to carry over to the actual message. Note that I put the test for the scan being finished in the sensor event, not in the search_for_people function. Note also sleeping AFTER the sweep in triggered, instead of before. Cavot Emptor: If the blasted thing works, consider that I have yet to be in-world, nevermind writing, testing, and debugging my own scripts. This is built from your code [obviously!] my understanding --strictly from reading descriptions-- of how LSL works, and my general programming knowledge. If it works, let me know, and buy yourself a $1 lottery ticket from the official state lottery of your choice. Toodle-oo!
|
|
Starax Statosky
Unregistered User
Join date: 23 Dec 2003
Posts: 1,099
|
05-11-2006 15:25
list gkl =[];
integer counter;
Swivel() { // rotate the prim by 90'
rotation r = llEuler2Rot( <0,90 * DEG_TO_RAD, 0> ); rotation new_rot = r*llGetRot(); llSetRot(new_rot); }
process_list () {
// do something with it
integer people_in_area = llGetListLength(gkl); llSay ( 0, "There are " + (string)(people_in_area) + " people here" );
}
////
////
default { state_entry() { llSay (0, "Touch me!"); }
touch_start ( integer total_number ) { llSetTimerEvent(1); }
timer() { if (counter==4) { counter=0; process_list(); llSetTimerEvent(0); return; } llSensor( "", NULL_KEY, AGENT, 50, PI_BY_TWO); Swivel(); counter=counter+1; }
sensor ( integer total_number ) {
// sensor 'ping' from the radar llSay ( 0, "PING!" ); integer check_list; integer i; list little_list;
// add llDetectedKey(i) to a global list for ( i = 0; i <total_number; i++ ) {
little_list = []; little_list = [ llDetectedKey(i) ]; check_list = llListFindList (gkl, little_list );
if ( check_list == -1 ) { gkl += [llDetectedKey(i)]; }
}
}
}
|
|
Starax Statosky
Unregistered User
Join date: 23 Dec 2003
Posts: 1,099
|
05-11-2006 15:33
Silent, just to point out a few things: Your rotation code was broken. It wasn't rotating relative to its current orientation. Also, in the sensor event, it should be: for (i=0;i<total_numer;i++) { } and not: for (i=0;i<=total_number;i++) { } and: if (check_test==-1) { } and not: if (check_test!=-1) { } -1 is when the key doesn't exist. So that's when you want to add the key. But other than that. You're doing great!! Now you need to work out what to do when the avatars leave the area. 
|