Jump to content

Using llSensor and llSensor Repeat


You are about to reply to a thread that has been inactive for 4503 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hi,

I am trying to write a script to count the number of objects and scripted objects as it is moving every 5 meters. The moving part is working great but for some reason it is not accurate (or ignoring) objects and scripted objects in the given radius I am giving it. Also, it is printing a lot of messages for the first 5 or so movements. ie. when it first moves it will display a lot of "There are no scripted objects in range". 

Can someone help me out with these 2 problems?

I know it probably has to do with where I am placing my llSensorRepeat's? Is that right?

Thanks!

// declare global variables
integer second;
vector startPos;
integer typeConst;
integer face = -1;
vector color = <1.0, 1.0, 1.0>;
list objectCount = [];
list scriptCount =[];

default
 {
     state_entry()
     {
        // declare the starting position of the object and set the original color back 
        startPos = llGetPos();
        llSetColor(color, face);
     }
 
     touch_start(integer total_number)
     {
         typeConst = 0;
         llSensorRepeat("", "", SCRIPTED, 10.0, PI, 5); // sensor for the scripted objects
         llSetTimerEvent(5);  // a timer event every 5 seconds
     }
    
    timer()  // do every time the timer event occurs
    {
         // increase the second count on the timer
         second++;
        
         // get the position of the object
         vector pos = llGetPos();
         float X1 = pos.x;
         float Y = pos.y;
         float Z = pos.z; 

         // move the object 5 meters at a time
         float X = X1 + 5.0;
         llSetPos (< X,Y,Z>);
             
        if (second > 10)  // bring object back after 20 seconds
        {    
            // move object back to starting position
            while (llVecDist(llGetPos(), startPos) > 0.001) 
            {
                llSetPos(startPos); 
            }
     
            llOwnerSay("Resetting script.");
            key requestid = llHTTPRequest
                    ("http://www.wbi-icc.com/students/SL/text1.php", 
                [HTTP_METHOD, "POST",
                 HTTP_MIMETYPE, "application/x-www-form-urlencoded"],
                "parameter1=" + (string)objectCount 
                + "&parameter2=" + (string)scriptCount);
            llResetScript();  // return object to the last saved script's position
        }
    }
    
     //Use the sensors to keep a count of the total objects and scripts
    sensor(integer detected)
    {
        if(typeConst == 0)
        {
            llOwnerSay("There are "+ (string)detected 
                +" scripted objects in range.");
            scriptCount = scriptCount + detected + "\n";
            typeConst = 1;
            llSensorRepeat("", "",PASSIVE, 10.0, PI, 5); // sensor for the objects
            
            // set the color according to the detected script and object count
            if(detected > 20)
            {
                llOwnerSay("Too many objects and scripts!");
                llSetColor(<0.5, 0.0, 0.0>, face);
            }
            else if(detected < 20 && detected > 15)
            {
                llOwnerSay("The object and script limit is getting high.");
                llSetColor(<1.0, 1.0, 0.0>, face);
            }
            else if(detected < 15)
            {
                llOwnerSay("The object and script count is ok.");
                llSetColor(<0.0, 1.0, 0.0>, face);
            }
            
        }
        else if(typeConst == 1)
        {
            llOwnerSay("There are "+(string)detected 
                +" objects in range.");
            objectCount = objectCount + detected + "\n";
        }
    }

    //Sensor  did not find anything
    no_sensor()
    {
        if(typeConst == 0)
        {
            llOwnerSay("There are no scripted objects in range.");
            typeConst = 1;
            llSensor("", NULL_KEY, PASSIVE, 10.0, PI);
            llSetColor(<0.0, 1.0, 0.0>, face);
        }
        else
        {
            llOwnerSay("No objects in range.");
            llSetColor(<0.0, 1.0, 0.0>, face);
        }
    }
}

 

Link to comment
Share on other sites

You can only have one active sensor at a time.  So calling two sensor repeats does not get you two running sensors each scanning for a different type of object, it simply gets you whatever the last sensor repeat call was.

As a thought, don't use sensor repeat.  Instead just use sensor from your timer event as it is running every five seconds anyway.

Also sensors can only return a maximum of 16 objects, (you have a line in there about if objects detected is greater than 20).

Link to comment
Share on other sites

From the wiki on llSensorRepeat ... "Only the most recent sensor event is queued. Previous sensor events are replaced."  So, if you call llSensorRepeat more than one time, the script wipes out all but the most recent ones. In this case, you  call the function in the touch_start event and then call it again every single time the sensor event is triggered, so you get a cascade of messages from the same spot.  Get rid of the call in the sensor event and the one in the no_sensor event.  If you really need to detect two types of objects, include both in your mask:

llSensorRepeat("", "", SCRIPTED|PASSIVE, 15.0. PI, 5.0);

 

Link to comment
Share on other sites

The way things commonly work, there are 2 separate queues, a timing queue (there in fact may be several with different granularity) and an event scheduler queue. There is never a complete sync between them. In your script it means that it may be missing cells because some times sensor event will execute before timer event and some times after it.

For a proper sync get rid of sensor repeat on touch, and do a single sensor inside the timer. In a sensor call do a single filter ACTIVE | PASSIVE

Link to comment
Share on other sites

There are several things to say so I'll start with the most positive: this 'looks' much better than your earlier scripts, clearly you have been learning and practicing quite a bit.

Things to consider:

It moves every 5 seconds, it scans every 5 seconds.  Why use the timer for movement and sensor-repeat for scanning?  You only need one 5s timer, which will make things a bit simpler.  Since you need two sensors (arguably; you can scan for both types at once using "(PASSIVE SCRIPTED)" for instance) your current llSensorRepeat() calls are confused, inconsistent and cancel each-other out and (eg; wait 5s, scan for scripted every 5s, if any found wait 5s then scan for passive every 5s but if none found scan once for passive immediately).  You're also likely to get inconsistent behaviour as to whether the timer or the sensor is raised, queued and handled first.

The way you count passive and scripted objects is ... idiosyncratic.  They are declared as lists but you don't use string syntax for them (scriptCount = scriptCount + detected + "\n") and cast the whole thing as a string (+ (string) scriptCount).  This is also a cumulative count over the 10m radius of the scan so any individual object is going to be counted up to 5 times as you move (10m ahead, 5m ahead, 0m, 5m behind, 10m behind.  Same object adding 5 to the count).

Your whole colour-coding thing just doesn't make sense to me.  It only happens when looking for scripted objects, you test for > 20 when the maximum that can be returned is 16 and you say "getting high" when the very next scan could return no objects at all.

As I've said each time you've posted; keep it simple, go one step at a time and explain exactly what you're trying to do.  Explaining the logic clearly to use - when we have no idea - makes it clearer to you too and you'll find you think of a lot of answers just by trying to tell someone else the problem.

Below is one way that I would go about writing the move-and-scan part.  What should it do next?

 

integer Cycles;integer ScanType = SCRIPTED;vector StartPos;NextScan(integer Count){	if(SCRIPTED == ScanType){		llOwnerSay("There are " + (string) Count + " scripted objects in range.");		ScanType = PASSIVE;		llSensor("", NULL_KEY, ScanType, 10.0, PI);	}else{		llOwnerSay("There are " + (string) Count + " passive objects in range.");		ScanType = SCRIPTED;	}}default{	no_sensor(){		NextScan(0);	}	sensor(integer HowMany){		NextScan(HowMany);	}	state_entry(){		StartPos = llGetPos();	}	timer(){		if(++Cycles > 10){			llSetRegionPos(StartPos);			llResetScript();		}else{			llSetPos(llGetPos() + <5.0, 0.0, 0.0>);			llSensor("", NULL_KEY, ScanType, 10.0, PI);		}	}	touch_end(integer HowMany){		llSetTimerEvent(5.0);	}}

 

  • Like 1
Link to comment
Share on other sites

First, I appreciate your detailed response pointing all of things out very clearly.

I realize the color thing is quite useless since the maximum number it could return is 16. The whole point behind that was to see visually how the number of objects and scripted objects in that given area is affecting that area and the entire region (ie. lag).

Great point about the timer for movement and sensor-repeat. I knew there was probably a better way but that is just what I came up with in the beginning.

Also, won't your script only return either passive or scripted? You can't get both of the values?

Eventually, I want it to be able to move in a confined path (rigth now its just going straight and coming back). I want it to be able to go however many meters forward, go however many meters right, go however many meters backwards ect...

Link to comment
Share on other sites


CincinnatiBearcats wrote:

[...]

Also, won't your script only return either passive or scripted? You can't get both of the values?  [...]

In that call, llSensorRepeat( "", "", SCRIPTED | PASSIVE, 15.0, PI, 5.) , you are creating a mask by ORing the two codes together.  When the sensor event processes the result of a scan, it compares the result with that mask implicitly, effectively asking

 

if (llDetectedType(0) & (SCRIPTED | PASSIVE) )  //That is, if it is TRUE that the detected object is either scripted or passive...{    //This is a real hit}

 Notice that because you are making a bitwise comparison, OR is | , not ||, and the AND is &, not &&.  Now, if you want to know exactly which one of the two acceptable conditions was met, you can always ask about llDetectedType specifically .....

Link to comment
Share on other sites


CincinnatiBearcats wrote:

First, I appreciate your detailed response pointing all of things out very clearly.

...

Also, won't your script only return either passive or scripted? You can't get both of the values?

Eventually, I want it to be able to move in a confined path (rigth now its just going straight and coming back). I want it to be able to go however many meters forward, go however many meters right, go however many meters backwards ect...

We appreciate that you are learning.  We know it can be - is - frustrating but I hope you are seeing improvement in yourself and feeling more confident about scripting than when you started.

As Rolig has already posted, and I mentioned briefly, you can detect scripted objects as well as passive objects in one pass as shown on http://wiki.secondlife.com/wiki/LlSensorRepeat.  The return-limit is still 16 hits though so I have used your method of making separate scans.  Please note that on touch the script scans for scripted objects, either sensor() or no_sensor() will result, both of which direct control to NextScan() which does a scan for passive objects.  The script as it is doesn't 'return' anything, but if you want to capture counts and things you'd do it for scripted and/or passive objects in NextScan().

Look at http://wiki.secondlife.com/wiki/LlSetKeyframedMotion for generalised route-following.  You won't need the timer in that case so might as well go back to llSensorRepeat() - but that's probably getting ahead of ourselves.

This version of the script changes NextScan() to record unique object IDs.  NB: at the end llGetListLength() will tell you the count of objects.

 

integer Cycles;list ObjectPassive;list ObjectScripted;integer ScanType = SCRIPTED;vector StartPos;NextScan(integer Count){	integer New;	if(SCRIPTED == ScanType){		llOwnerSay("There are " + (string) Count + " scripted objects in range.");		while(Count--){			if(-1 == llListFindList(ObjectScripted, [llDetectedKey(Count)])){				++New;				ObjectScripted += [llDetectedKey(Count)];			}		}		llOwnerSay((string) New + " of them are new.");		ScanType = PASSIVE;		llSensor("", NULL_KEY, ScanType, 10.0, PI);	}else{		llOwnerSay("There are " + (string) Count + " passive objects in range.");		while(Count--){			if(-1 == llListFindList(ObjectPassive, [llDetectedKey(Count)])){				++New;				ObjectPassive += [llDetectedKey(Count)];			}		}		llOwnerSay((string) New + " of them are new.");		ScanType = SCRIPTED;	}}default{	no_sensor(){		NextScan(0);	}	sensor(integer HowMany){		NextScan(HowMany);	}	state_entry(){		StartPos = llGetPos();	}	timer(){		if(++Cycles > 10){						llSetRegionPos(StartPos);			llResetScript();		}else{			llSetPos(llGetPos() + <5.0, 0.0, 0.0>);			llSensor("", NULL_KEY, ScanType, 10.0, PI);		}	}	touch_end(integer HowMany){		llSetTimerEvent(5.0);	}}

 

Make sure you understand this:  every detected thing is checked against its list type and added once.  Something may be in both lists, but that's "as designed" from what you've said so far.

Link to comment
Share on other sites

There are at least 2 other ways to get what you want, that don't use sensor, I can't say as one of them I currently use for some of my products, I am sure the others here can tell you, but sensor is very limited, and one of the other ways, that I don't use would suit you well as you are moving about as well and has no limit on the objects or AV's it detects, so you could have numbers into the hundreds,

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 4503 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...