Lost user? Use in public places

11 views
Skip to first unread message

leochen...@gmail.com

unread,
Oct 24, 2011, 2:13:58 PM10/24/11
to AS3OpenNI
Recent as3openni occasions in public interactive installations.
But whenever people passing, the user will lose the frame.
Checked the forum, in addition to space restrictions, it seems that
there is no other solution.

Well can I ask for some advice?

Gergely Nagy

unread,
Oct 25, 2011, 3:37:49 AM10/25/11
to as3o...@googlegroups.com
Hi,
Have you looked into this thread?
User Tracking: Building game for crowded/heavy traffic area. Have
trouble with USER LOST shutting down game.

You could contact the OP and ask him what he did to solve the problem.
And by the way you could post the result back so that everyxone can
learn. (What the OP of that thread unfortunately forgot to do :/ )

Greg

2011/10/24 leo19...@hotmail.com <leochen...@gmail.com>:

jblatta

unread,
Oct 25, 2011, 11:54:26 AM10/25/11
to AS3OpenNI
My bad for not posting my solution. The run up to the tradeshow was
full of 16 hour days. Now that I am back and rested and I will post my
solution which worked without any major problems. I will try to have
this up before I leave work.

On Oct 25, 3:37 am, Gergely Nagy <gergelynag...@gmail.com> wrote:
> Hi,
> Have you looked into this thread?
> User Tracking: Building game for crowded/heavy traffic area. Have
> trouble with USER LOST shutting down game.
>
> You could contact the OP and ask him what he did to solve the problem.
> And by the way you could post the result back so that everyxone can
> learn. (What the OP of that thread unfortunately forgot to do :/ )
>
> Greg
>
> 2011/10/24 leo1989...@hotmail.com <leochen1989...@gmail.com>:

leochen...@gmail.com

unread,
Oct 25, 2011, 12:44:33 PM10/25/11
to AS3OpenNI
Have seen, but did not see an effective Example.
How does this issue back in version 1.3 is there? Or in 1.3 have it?
And whether to capture the user can adjust the number of it? (Eg do
not need to 15 users)

On 10月25日, 下午3時37分, Gergely Nagy <gergelynag...@gmail.com> wrote:
> Hi,
> Have you looked into this thread?
> User Tracking: Building game for crowded/heavy traffic area. Have
> trouble with USER LOST shutting down game.
>
> You could contact the OP and ask him what he did to solve the problem.
> And by the way you could post the result back so that everyxone can
> learn. (What the OP of that thread unfortunately forgot to do :/ )
>
> Greg
>
> 2011/10/24 leo1989...@hotmail.com <leochen1989...@gmail.com>:

leochen...@gmail.com

unread,
Oct 25, 2011, 12:53:43 PM10/25/11
to AS3OpenNI
Thank you jblatta
I ask whether the user can control the number of screen capture thing?
(For example: do not need up to 15 users)

jblatta

unread,
Oct 25, 2011, 1:21:42 PM10/25/11
to AS3OpenNI
I am not sure if that is controlled on the as3 side or the socket
server side. My guess is the socket server handles that.

My solution was to create a user zone that I defined in space and only
use the info from within the zone. I also had to filter out ghost
users that are caused by the last player and people walking out. The
ghost user data is the biggest issue. What is actually happening
behind the scene is your current user is still active but is competing
30x a sec with ghost data which makes it seem like things are frozen.
I can not post my project because of our non-disclosure with the
client but I will pull out just the filtering code and post it here
shortly.

On Oct 25, 12:53 pm, "leo1989...@hotmail.com"

jblatta

unread,
Oct 25, 2011, 2:09:48 PM10/25/11
to AS3OpenNI
here it is, cleaned up

package
{
import adobe.utils.ProductManager;

import flash.desktop.NativeApplication;
import flash.display.MovieClip;
import flash.display.NativeWindow;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageDisplayState;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.system.System;
import flash.utils.Timer;

import org.as3openni.AS3OpenNI;
import org.as3openni.events.AS3OpenNIEvent;
import org.as3openni.faast.events.FAASTEvent;
import org.as3openni.nite.events.NiteGestureEvent;
import org.as3openni.objects.NiPoint2D;
import org.as3openni.objects.NiPoint3D;
import org.as3openni.objects.NiSkeleton;
import org.as3openni.openni.events.ONISkeletonEvent;
import org.as3openni.openni.events.ONIUserTrackingEvent;
import org.as3openni.util.math.NiPoint3DUtil;

public class filterTest extends Sprite
{

[SWF( frameRate="24", backgroundColor="#000000", width="1920",
height="1080")]

public var as3OpenNI:AS3OpenNI;
public var skeletonData:NiSkeleton = new NiSkeleton();

private var dupCheckArray:Array = new Array();
private var dupValues:Array = new Array();
private var lostUserTimer:Timer = new Timer(1000, 5);
private var zone:Object;
private var zoneEmpty:Boolean;
private var userListernersAdded:Boolean = false;
private var warningBox:WarningBox;


public function filterTest()
{
// Setup stage scaling
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;

this.addEventListener(Event.ADDED_TO_STAGE, initKinect);

// Setup load timer and Warning box. The warning box was just a
movieclip that overlays on top of the screen and tells the user they
have 5 secs to step back in the box before it resets.
warningBox = new WarningBox();
warningBox.visible = false;
this.addChild(warningBox);

// Lost user listener
lostUserTimer.addEventListener(TimerEvent.TIMER_COMPLETE,
userLost);
lostUserTimer.addEventListener(TimerEvent.TIMER,
function(e:TimerEvent):void{
warningBox.resetting.text = "resetting in " +
(lostUserTimer.repeatCount - lostUserTimer.currentCount);
warningBox.visible = true;
trace("resetting in " + (lostUserTimer.repeatCount -
lostUserTimer.currentCount));
});

// setup user zone the kinect will use to filter from
zone = createZone(5, 3.25, 3.75);

}

// This will shutdown and restart an air app. I had to do this
because my project was using an alpha version of away3D and I had a
memory leak so this restarted the whole thing. Only took about 5 secs
for it to restart and kinect to be ready for a user.
public function restartApp():void
{
shutdownKinect();
var mgr:ProductManager = new ProductManager("airappinstaller");
mgr.launch("-launch " +
NativeApplication.nativeApplication.applicationID + " " +
NativeApplication.nativeApplication.publisherID);
NativeApplication.nativeApplication.exit();
}


public function initKinect(e:Event=null):void
{
trace("initKinect");
as3OpenNI = new AS3OpenNI();
as3OpenNI.addEventListener(AS3OpenNIEvent.READY, onReady);
as3OpenNI.binaryPath = "bin/AS3OpenNI_Alpha_1.3.0";
as3OpenNI.debug = true;
as3OpenNI.traceLog = true;
as3OpenNI.userTracking = true;
as3OpenNI.depthMap = true;
as3OpenNI.init();
addUserTrackingListeners();
}


protected function onReady(event:AS3OpenNIEvent):void
{
trace("Ready...");
this.addEventListener(Event.ENTER_FRAME, onRender);
this.as3OpenNI.removeEventListener(AS3OpenNIEvent.READY, onReady);
}

protected function onRender(event:Event):void
{
if(as3OpenNI.isReady())
{
as3OpenNI.getDepthBuffer();
as3OpenNI.getUserTrackingBuffer();
as3OpenNI.getSkeletonsBuffer();
}
}

public function shutdownKinect():void
{
trace("SHUTDOWN KINECT");
removeEventListener(Event.ENTER_FRAME, onRender);
removeUserTrackingListeners();
as3OpenNI.bridge.exit(true);
}

private function addUserTrackingListeners():void
{

as3OpenNI.addEventListener(ONIUserTrackingEvent.USER_TRACKING_POSE_DETECTED,
userPoseDetected);

as3OpenNI.addEventListener(ONIUserTrackingEvent.USER_TRACKING_USER_CALIBRATION_START,
userCalibrationStarted);

as3OpenNI.addEventListener(ONIUserTrackingEvent.USER_TRACKING_USER_CALIBRATION_COMPLETE,
userCalibrationComplete);

as3OpenNI.addEventListener(ONIUserTrackingEvent.USER_TRACKING_USER_CALIBRATION_FAILED,
userCalibrationFailed);
as3OpenNI.addEventListener(ONISkeletonEvent.USER_TRACKING,
skeleton);
}

private function removeUserTrackingListeners():void
{

as3OpenNI.removeEventListener(ONIUserTrackingEvent.USER_TRACKING_POSE_DETECTED,
userPoseDetected);

as3OpenNI.removeEventListener(ONIUserTrackingEvent.USER_TRACKING_USER_CALIBRATION_START,
userCalibrationStarted);

as3OpenNI.removeEventListener(ONIUserTrackingEvent.USER_TRACKING_USER_CALIBRATION_COMPLETE,
userCalibrationComplete);

as3OpenNI.removeEventListener(ONIUserTrackingEvent.USER_TRACKING_USER_CALIBRATION_FAILED,
userCalibrationFailed);
as3OpenNI.removeEventListener(ONISkeletonEvent.USER_TRACKING,
skeleton);
}

// When use is lost we restart the app
private function userLost(e:TimerEvent=null):void
{
trace("LOST USER!!!")
zoneEmpty = true;
restartApp();
}

protected function userPoseDetected(event:ONIUserTrackingEvent):void
{
trace("Pose Detected");
}

protected function
userCalibrationStarted(event:ONIUserTrackingEvent):void
{
trace("Calibration Started");
}

protected function
userCalibrationComplete(event:ONIUserTrackingEvent=null):void
{
trace("Calibration Complete");
}

protected function
userCalibrationFailed(event:ONIUserTrackingEvent):void
{
trace('Calibration Failed for User: ' + event.user);
}

// Get Skeleton Data. We use some filtering based on the user zone
to figure out who the active user is and ignore lost or stalled users.
protected function skeleton(event:ONISkeletonEvent):void
{
// We use the torso as the point we check to see if the user is in
the box
var userLoc:NiPoint3D = event.skeleton.torso;

// See if user is in the user zone
if(checkZone(userLoc)){
var fresh:Boolean = true;
for(var d:int = 0; d < dupValues.length; d++){
if(dupValues[d] == userLoc.pointZ){
fresh = false;
}
}

// if user data is from an active user and not stalled/ghosted
data
if(fresh == true){
if(zoneEmpty == true){
zoneEmpty = false;
userCalibrationComplete();
}

skeletonData = event.skeleton;
//////////////////////////////////////////////
// active user found, execute code here
//////////////////////////////////////////////

// keep alive timer that hides the warning box until user is
lost.
warningBox.visible = false;
lostUserTimer.reset();
lostUserTimer.start();
}
}

// add torso z data to dup check array
dupCheckArray.unshift(userLoc.pointZ);

// trim array to 10
dupCheckArray = dupCheckArray.splice(0,12);

// check for dups
var tempValues:Array = countValues(dupCheckArray);
dupValues = new Array();
for(var i:int = 0; i < tempValues.length; i++)
{
if(tempValues[i][1] > 1){
dupValues.push(tempValues[i][0]);
}
}

}

// Define User Zone and convert from feet to mm
private function createZone(dist:Number, width:Number,
depth:Number):Object
{
var z:Object = new Object();
z.distance = convertMM(dist);
z.width = convertMM(width);
z.depth = convertMM(depth);
return z;
}

// Convert Feet to MM
private function convertMM(n:Number):Number
{
return n * 304.8;
}

// Check if active user is in the defined user zone
private function checkZone(p:NiPoint3D):Boolean
{

if(p.pointZ > (zone.distance - (zone.depth/2)) &&
p.pointZ < (zone.distance + (zone.depth/2)) &&
p.pointX > -(zone.width/2) &&
p.pointX < (zone.width/2)
){
return true;
}else{
return false;
}
}

// This function looks at an array of values and checks for
duplicates and gives you a count of how many so you can find the stuck/
stalled data
private function countValues (a:Array) : Array
{
var i:int, j:int = -1, c:Object, o:Object = {}, r:Array = [],
v:Number, n:Number = a.length;
for(i = 0;i < n;++i) (c = o[v = a[i]]) ? ++c[1] : r[int(++j)] =
o[v] = [v,1];
return r;
}
}
}

leochen...@gmail.com

unread,
Oct 28, 2011, 1:15:37 PM10/28/11
to AS3OpenNI
Wow thanks jblatta
This is an effective way to grab him but I can control the number you
new user (as mentioned before message).
I found that each grasping a new user will increase cpu unnecessary
operations, the burden caused by pc.
Reply all
Reply to author
Forward
0 new messages