Android Fall Detection using kotlin: ISSUE - android

I'm trying to implement a simple fall detection algorithm using android's accelerometer.
override fun onSensorChanged(event: SensorEvent?)
{
x=event!!.values[0].toDouble()
y=event!!.values[1].toDouble()
z=event!!.values[2].toDouble()
var sqroot= sqrt(x.pow(2) + y.pow(2)+z.pow(2))
textView.setText("x= ${event!!.values[0]}\n\n"+"y= ${event!!.values[1]}\n\n\n"+
"z= ${event!!.values[2]}"+"\n\n\n acceleration=$sqroot")
if (sqroot<3 && minv==false && status==false)
{
minv=true
lasttime=System.currentTimeMillis()
Log.i("min thresholds","free fall to ground $sqroot" )
Toast.makeText(this,"free fall to ground $sqroot",Toast.LENGTH_SHORT).show()
}
if (minv)
{
counter++
if (sqroot>=30 && maxv==false && status==false) {
newtime = System.currentTimeMillis()
diff = newtime - lasttime
Toast.makeText(this,"last:$lasttime && new:$newtime \n diff:$diff\n\n $sqroot",Toast.LENGTH_LONG).show()
if (diff > 150 && diff<9000)
{
maxv = true
Log.i("hit the ground", "hiting to ground $sqroot")
Toast.makeText(this, "hit to ground $sqroot", Toast.LENGTH_SHORT).show()
status = true
}
}
}
if(maxv==true && minv==true && status==true)
{
Log.i("fall detected ","fall detected $sqroot")
Toast.makeText(this,"fall detected $sqroot",Toast.LENGTH_SHORT).show()
textView2.text="x=$x\ny=$y\nz=$z \n acc=$sqroot \n\n\n last:$lasttime && new:$newtime \n" +
" diff:$diff"
x=0.0
y=0.0
z=0.0
minv=false
maxv=false
status=false
}
if (counter>10)
{
counter=0
minv=true
maxv=true
}
}
I am using simple threshold value system to detect the fall and addition on a time system mean I fall free time to hit the ground time difference is >900 millisecond and <9000 millisecond then fall alert
but I am not getting the required result can you please give the suggestion whats is wrong with this code?

You may try this library:
https://github.com/tompadree/freeFall/tree/master/frefalllib
Usage:
FreeFallService.startService(context,
object : OnSensorChanged {
override fun onFall(fallObject: FallObject) {
// code when free fall is detected
}
},
object : OnFallsListFetch {
override fun onFallsFetch(fallsList: ArrayList<FallObject>) {
// handling call for fetching all events from the db
}
})

Related

How to detect EAR with ArCore android

So I am trying to put a earing on a person with ArCore. But the Face ArCore mask does not cover ears best i can do is at 172 but its still far away from the ear.
this is my code
private fun getRegionPose(region: FaceRegion): Vector3? {
val buffer = augmentedFace?.meshVertices
if (buffer != null) {
return when (region) {
FaceRegion.EAR ->
Vector3(
buffer.get(177 * 3),
buffer.get(177 * 3 + 1),
buffer.get(177 * 3 + 2)
)
}
}
return null
}
override fun onUpdate(frameTime: FrameTime?) {
super.onUpdate(frameTime)
augmentedFace?.let { face ->
getRegionPose(FaceRegion.EAR)?.let {
mustacheNode?.localPosition = Vector3(it.x, it.y - 0.035f, it.z + 0.015f)
mustacheNode?.localScale = Vector3(0.07f, 0.07f, 0.07f)
}
}
}
Can some one help me please is there a way for me to go outside the bonds of the face lnadmakrs?
Well after a lot of research i found this example and it was what lead me to my answer. So i leave the tutorial here hopefouly it can help some one.
https://www.kodeco.com/523-augmented-reality-in-android-with-google-s-face-api#toc-anchor-003

Android ESP32 BLE read after write not working

I'm writing an embedded system which doesn't have an internet connection, so the main interaction is using BLE from an Android device. (ESP32 is using the NimBLE-Arduino library)
I have some write characteristics and some read characteristics. Each one individually works well, but when I try to read immediately after write (or vice versa), only the first callback in the ESP32 is called
ESP32 code
// Setup function
void Bluetooth::setupCharacteristic()
{
NimBLEService *pService = m_pServer->createService(SERVICE_UUID);
NimBLECharacteristic *getStationsChr = pService->createCharacteristic(GET_STATIONS_CHR_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN);
NimBLECharacteristic *setTimeChr = pService->createCharacteristic(SET_TIME_CHR_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_ENC | NIMBLE_PROPERTY::WRITE_AUTHEN);
getStationsChr->setCallbacks(this);
setTimeChr->setCallbacks(this);
pService->start();
}
// Read/Write callbacks
void Bluetooth::onRead(NimBLECharacteristic* pCharacteristic){
log_i("%s", pCharacteristic->getUUID().toString().c_str());
log_i(": onRead(), value: %s",pCharacteristic->getValue().c_str());
if (m_pCallback)
{
auto value = pCharacteristic->getValue();
//m_pCallback->onMessageReceived(&value);
}
...
}
void Bluetooth::onWrite(NimBLECharacteristic* pCharacteristic) {
std::string characteristicStr = pCharacteristic->getUUID().toString();
std::string value_str(pCharacteristic->getValue().c_str());
log_i("%s: onWrite(), value: %s (%s)", characteristicStr.c_str(), pCharacteristic->getValue().c_str(), value_str.c_str());
// Process incoming value and call the callback
// ...
if (m_pCallback)
{
auto value = pCharacteristic->getValue();
//m_pCallback->onMessageReceived(&value);
}
...
}
Android code
private fun updateTime() {
val calendar = GregorianCalendar()
val ts = Instant.now().epochSecond
val timeZone = timezonesMap?.get(calendar.timeZone.id) ?: ""
val timeMessage = TimeMessage(ts, 0, timeZone)
val setTimeChar = bluetoothGatt?.getService(SERVICE_UUID)?.getCharacteristic(SET_TIME_UUID)
if (setTimeChar?.isWritable() == true) {
val timeStr = gson.toJson(timeMessage)
Log.d("updateTime", "setting time to $timeStr")
sendToCharacteristic(setTimeChar, timeStr)
}
}
// This function is used to break long message to multiple messages, this is a simplified version
// for brevity
private fun sendToCharacteristic(characteristic: BluetoothGattCharacteristic?, value: String)
{
Log.d(TAG, "Sending to write characteristic ${characteristic?.uuid} value ($value)")
characteristic?.value = value.toByteArray()
bluetoothGatt?.writeCharacteristic(characteristic)
TimeUnit.MILLISECONDS.sleep(500)
}
private fun getStations() {
Log.d("getStations", "getting stations")
val getStationsChar = bluetoothGatt?.getService(SERVICE_UUID)?.getCharacteristic(GET_STATIONS_UUID)
if (getStationsChar?.isReadable() == true) {
Log.d("getStations", "reading")
bluetoothGatt?.readCharacteristic(getStationsChar)
}
}
The issue is when calling my sync() function
fun sync() {
Log.d("sync", "syncing")
bluetoothGatt?.apply {
if (device.bondState != BluetoothDevice.BOND_BONDED) {
device.createBond()
}
else {
updateTime()
// getStations()
}
}
}
If I uncomment the getStations, the read callback isn't called. If I comment the updateTime and uncomment the getStations, the read callback is called. switching the order doesn't make a difference. First called function works, second doesn't. Also adding a 1 second delay between the calls doesn't work
Your problem lies on the Android side.
In GATT you may only have one outstanding request. This means you must wait for the previous callback before executing a new operation. In particular, you must in this case wait for onCharacteristicWrite on your BluetoothGattCallback object after performing a write operation, before you can execute a next operation.
Adding a sleep doesn't work since you block the thread and hence prevent the result callback from running, whenever a response is received from the remote device.

Unity Raycast results different on two devices

I use the following codes to detect which UI element is the player pointing. It works well in Unity Editor, on one of my Android phone, but failed on a second Android phone.
public static T RaycastOnFirstPointed<T>(EventSystem eventSystem, GraphicRaycaster raycaster)
{
if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
{
if (Input.touches == null || Input.touches.Length == 0) return default;
}
var m_PointerEventData = new PointerEventData(eventSystem);
m_PointerEventData.position = Input.mousePosition;
var results = new List<RaycastResult>();
raycaster.Raycast(m_PointerEventData, results); // On the 2nd phone the results.length is 0
foreach (RaycastResult result in results)
{
var component = result.gameObject.GetComponent<T>();
if (component != null)
{
return component;
}
}
return default;
}
This method is called within a IEndDragHandler.OnEndDrag method. I tried to debug it on the 2nd Android phone, and saw the results.length is 0 after Raycast was executed.(it should be > 0 since I ended my drag on several overlapped UI elements, and it is > 0 on the 1st phone, not sure why the 2nd phone is different)
I don't have any clue where should I go from here to find the problem. Please show me some directions, thank you!
More info:
Phone 1: MI 8 Lite, OS: MIUI 10.3
Phone 2: MI 9, OS: MIUI 10.2.35
============Update===========
Reason found:
When IEndDragHandler.OnEndDrag is triggered, the Input.mousePosition has different value on the two devices. 1st Phone has the touch position from the last frame, while the 2nd phone seems clears that value, and it has a very large wrong value. I'm working on how to solve this in a proper way. Any suggestions are welcomed.
Problem solved. As I updated in the question, this problem is caused by wrong Input.mousePosition value on different devices. So I updated the RaycastOnFirstPointed method as follows:
public static T RaycastOnFirstPointed<T>(EventSystem eventSystem, GraphicRaycaster raycaster, PointerEventData eventData = null)
{
if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
{
if (Input.touches == null || Input.touches.Length == 0) return default;
}
var m_PointerEventData = new PointerEventData(eventSystem);
if (eventData == null)
{
m_PointerEventData.position = Input.mousePosition;
}
else
{
m_PointerEventData.position = eventData.position;
}
var results = new List<RaycastResult>();
raycaster.Raycast(m_PointerEventData, results);
foreach (RaycastResult result in results)
{
var component = result.gameObject.GetComponent<T>();
if (component != null)
{
return component;
}
}
return default;
}
When call this method within OnEndDrag, pass in the PointerEventData that unity provides and use its position.

Issue with removing eventlistener in actionscript

I'm not new to flash, but I'm a bit of a noob with actionscript, trying to build an app in flash pro (or rather, animate cc) which will (hopefully) teach the users music theory (how to read music, etc.). What I want is to have different lessons on separate frames, with separate "screens" which the user can swipe through. I'm using multiple copies of the swipe code which adobe provides in their swipe gallery template.
On frame 5, I use the following:
stop()
Multitouch.inputMode = MultitouchInputMode.GESTURE;
var currentGalleryItem:Number = 1;
var totalGalleryItems:Number = 10;
stage.addEventListener (TransformGestureEvent.GESTURE_SWIPE, fl_SwipeToGoToNextPreviousFrameB);
function fl_SwipeToGoToNextPreviousFrameB(event:TransformGestureEvent):void
{
if(event.offsetX == 1)
{
if(currentGalleryItem > 1){
currentGalleryItem--;
slideRight();
}
}
else if(event.offsetX == -1)
{
if(currentGalleryItem < totalGalleryItems){
currentGalleryItem++;
slideLeft();
}
}
}
var slideCounter:Number = 0;
function slideLeft(){
lsn112.addEventListener("enterFrame", moveGalleryLeft);
}
function slideRight(){
lsn112.addEventListener("enterFrame", moveGalleryRight);
}
function moveGalleryLeft(evt:Event){
lsn112.x -= 128;
slideCounter++;
if(slideCounter == 10){
lsn112.removeEventListener("enterFrame", moveGalleryLeft);
slideCounter = 0;
}
}
function moveGalleryRight(evt:Event){
lsn112.x += 128;
slideCounter++;
if(slideCounter == 10){
lsn112.removeEventListener("enterFrame", moveGalleryRight);
slideCounter = 0;
}
}
Home112.addEventListener(MouseEvent.CLICK, fl_ClickToGoToAndStopAtFrame_22);
function fl_ClickToGoToAndStopAtFrame_22(event:MouseEvent):void
{
gotoAndStop(2);
}
stop()
Frame 6 is almost identical, just with different names for variables, functions, etc.:
stop()
Multitouch.inputMode = MultitouchInputMode.GESTURE;
var currentGalleryItemA:Number = 1;
var totalGalleryItemsA:Number = 11;
stage.addEventListener (TransformGestureEvent.GESTURE_SWIPE, fl_SwipeToGoToNextPreviousFrameA);
function fl_SwipeToGoToNextPreviousFrameA(event:TransformGestureEvent):void
{
if(event.offsetX == 1)
{
if(currentGalleryItemA > 1){
currentGalleryItemA--;
slideRightA();
}
}
else if(event.offsetX == -1)
{
if(currentGalleryItemA < totalGalleryItemsA){
currentGalleryItemA++;
slideLeftA();
}
}
}
var slideCounterA:Number = 0;
function slideLeftA(){
lsn113.addEventListener("enterFrame", moveGalleryLeftA);
}
function slideRightA(){
lsn113.addEventListener("enterFrame", moveGalleryRightA);
}
function moveGalleryLeftA(evt:Event){
lsn113.x -= 128;
slideCounterA++;
if(slideCounterA == 10){
lsn113.removeEventListener("enterFrame", moveGalleryLeftA);
slideCounterA = 0;
}
}
function moveGalleryRightA(evt:Event){
lsn113.x += 128;
slideCounterA++;
if(slideCounterA == 10){
lsn113.removeEventListener("enterFrame", moveGalleryRightA);
slideCounterA = 0;
}
}
Home113.addEventListener(MouseEvent.CLICK, fl_ClickToGoToAndStopAtFrame_23);
function fl_ClickToGoToAndStopAtFrame_23(event:MouseEvent):void
{
gotoAndStop(2);
}
stop()
There is also a button as part of the movieclip "lsn112" which is being swiped. Don't know if this is relevant or not, but the code is:
stop();
fwdtest.addEventListener(MouseEvent.CLICK, GoRootNext112);
function GoRootNext112(event:MouseEvent):void
{
MovieClip(root).nextFrame();
}
It works fine to a point, but I think an eventlistener is not being removed properly. When the user swipes through the gallery, it works as expected. They can then move onto the next gallery, which also works as expected. No errors so far. However, if they then go back to the menu, and then back to the gallery, I get an error code 1009:
TypeError: Error #1009: Cannot access a property or method of a null
object reference. at
MusicTheorySwipe_fla::MainTimeline/slideRightA()[MusicTheorySwipe_fla.MainTimeline::frame6:32]
at
MusicTheorySwipe_fla::MainTimeline/fl_SwipeToGoToNextPreviousFrameA()[MusicTheorySwipe_fla.MainTimeline::frame6:16]
at runtime::ContentPlayer/simulationSendGestureEvent() at
runtime::SimulatedContentPlayer/clientSocketDataHandler()
What confuses me is that I am using frame 5 at this point, yet I get an error referencing frame 6. It appears to me that flash is attempting to send a gesture to the eventlistener in frame 6, even though I'm on frame 5, which I'm guessing is down to an eventlistener not being removed. However, being new to code, I don't know when to remove the eventlistener without breaking the code.
Here's a link to a zip containing the relevant .fla, .swf and .xml files.
http://speedy.sh/5JP7c/MusicTheorySwipe.zip
As this is the method I would like to use over many, many frames, I would really appreciate your time and help in resolving this.
EDIT
Ok, I've simplified the code as best I can, to try and eliminate any suspects.
Frame 5:
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE , onSwipeA);
var currentGalleryItemA:Number = 1;
var totalGalleryItemsA:Number = 5;
function onSwipeA (e:TransformGestureEvent):void{
//User swiped towards right
if (e.offsetX == 1) {
if(currentGalleryItemA > 1){
currentGalleryItemA--;
lsn113.x += 1280;
}
}
//User swiped towards left
if (e.offsetX == -1) {
if(currentGalleryItemA < totalGalleryItemsA){
currentGalleryItemA++;
lsn113.x -= 1280;
if(currentGalleryItemA == totalGalleryItemsA){
nextFrame()
}
}
}
}
stop();
Frame 6:
stage.removeEventListener(TransformGestureEvent.GESTURE_SWIPE , onSwipeA);
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE , onSwipeB);
var currentGalleryItemB:Number = 1;
var totalGalleryItemsB:Number = 11;
function onSwipeB (e:TransformGestureEvent):void{
//User swiped towards right
if (e.offsetX == 1) {
if(currentGalleryItemB > 1){
currentGalleryItemB--;
lsn112.x += 1280;
}
}
//User swiped towards left
if (e.offsetX == -1) {
if(currentGalleryItemB < totalGalleryItemsB){
currentGalleryItemB++;
lsn112.x -= 1280;
}
if(currentGalleryItemB == totalGalleryItemsB){
nextFrame()
}
}
}
stop();
And that's all the actionscript there is now, yet it's still not working. Any ideas?
On frame 2 when you switch to frame 6 check if stage has the event listener fl_SwipeToGoToNextPreviousFrameA() and if so remove it. That should fix your error.
You need to remove the listener at couple of frames.
Write these lines on frame2 after all of your code
stage.removeEventListener (TransformGestureEvent.GESTURE_SWIPE, fl_SwipeToGoToNextPreviousFrameA);
stage.removeEventListener (TransformGestureEvent.GESTURE_SWIPE, fl_SwipeToGoToNextPreviousFrameB);
Write this line on frame5 before you define listener
stage.removeEventListener (TransformGestureEvent.GESTURE_SWIPE, fl_SwipeToGoToNextPreviousFrameA);
Write this line on frame6 before you define listener
stage.removeEventListener (TransformGestureEvent.GESTURE_SWIPE, fl_SwipeToGoToNextPreviousFrameB);
and remove both from any other frame you can jump from frame5 and frame6.

Why is the link element's onload attribute unreliable for android stock browsers?

var style1 = document.createElement("link");
style1.id = "rel";
style1.rel = "stylesheet";
style1.href = "http://www.mysite.com/css.css";
style1.onload = function(){document.body.innerHTML+="fffffff";};
document.getElementsByTagName("head")[0].appendChild(style1);
This code works in Chrome/Firefox, and yet stock browsers on my Froyo (2.3) and Jellybean (4.1) Android devices will print nothing. What's the problem? I'd like if I could execute some js onload of a link. Anything else would in my case amount to a hack. :/
The problem isn't innerHTML. Try it with alerts if you want (at your own peril).
Another answer mentions checking for this functionality by doing
var huh = 'onload' in document.createElement('link');
..but this is true in both stock browsers! wtf guys?
Android browser doesn't support "onload" / "onreadystatechange" events for element: http://pieisgood.org/test/script-link-events/
But it returns:
"onload" in link === true
So, my solution is to detect Android browser from userAgent and then wait for some special css rule in your stylesheet (e.g., reset for "body" margins).
If it's not Android browser and it supports "onload" event- we will use it:
var userAgent = navigator.userAgent,
iChromeBrowser = /CriOS|Chrome/.test(userAgent),
isAndroidBrowser = /Mozilla\/5.0/.test(userAgent) && /Android/.test(userAgent) && /AppleWebKit/.test(userAgent) && !iChromeBrowser;
addCssLink('PATH/NAME.css', function(){
console.log('css is loaded');
});
function addCssLink(href, onload) {
var css = document.createElement("link");
css.setAttribute("rel", "stylesheet");
css.setAttribute("type", "text/css");
css.setAttribute("href", href);
document.head.appendChild(css);
if (onload) {
if (isAndroidBrowser || !("onload" in css)) {
waitForCss({
success: onload
});
} else {
css.onload = onload;
}
}
}
// We will check for css reset for "body" element- if success-> than css is loaded
function waitForCss(params) {
var maxWaitTime = 1000,
stepTime = 50,
alreadyWaitedTime = 0;
function nextStep() {
var startTime = +new Date(),
endTime;
setTimeout(function () {
endTime = +new Date();
alreadyWaitedTime += (endTime - startTime);
if (alreadyWaitedTime >= maxWaitTime) {
params.fail && params.fail();
} else {
// check for style- if no- revoke timer
if (window.getComputedStyle(document.body).marginTop === '0px') {
params.success();
} else {
nextStep();
}
}
}, stepTime);
}
nextStep();
}
Demo: http://codepen.io/malyw/pen/AuCtH

Categories

Resources