Search code examples
androidnavigationrosgamecontroller

How do you send single data when the button is pressed and not looping on the inside and stop the action when the button is release


So i am developing a controller in my mobile app using java and currently whenever i touch the button it will send 3 data in a row. when it should only be sending one data and another data when the button is release

i am able to set get the data when the button is release but not accurate since a lot of data was delivered

    upbtn.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            rosbridge.Publish("/set_velocity", nav_ctrl);
            if(event.getAction() == ACTION_DOWN) {
                nav_ctrl.linear.x = 0.6;
                nav_ctrl.angular.z = 0;
                return true;

            } else if (event.getAction() != MotionEvent.ACTION_UP) {
                    return false;
                }
                nav_ctrl.linear.x = 0;
                nav_ctrl.angular.z = 0;
            return false;
        }
    });

    downbtn.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            rosbridge.Publish("/set_velocity", nav_ctrl);
            if(event.getAction() == ACTION_MOVE) {
                    nav_ctrl.linear.x = -0.6;
                    nav_ctrl.angular.z = 0;
            } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
                nav_ctrl.linear.x = 0;
                nav_ctrl.angular.z = 0;
            }
            return false;
        }
    });


    leftbtn.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            rosbridge.Publish("/set_velocity", nav_ctrl);
            if(event.getAction() == ACTION_DOWN) {
                nav_ctrl.linear.x = 1.2;
                nav_ctrl.angular.z = 0;

                return true;

            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                leftbtn.performClick();
                nav_ctrl.linear.x = 0;
                nav_ctrl.angular.z = 0;
            }
            return false;
        }
    });

    rightbtn.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            rosbridge.Publish("/set_velocity", nav_ctrl);
            if(event.getAction() == ACTION_DOWN) {
                nav_ctrl.linear.x = -1.2;
                nav_ctrl.angular.z = 0;
                return true;

            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                nav_ctrl.linear.x = 0;
                nav_ctrl.angular.z = 0;
            }
            return false;
        }
    });

}

I expect the to send only one line of data, example: "angular":{"x":0.0,"y":0.0,"z":0.0},"linear":{"x":-0.6,"y":0.0,"z":0.0}},

the output is similar but multiple data's was delivered


Solution

  • The issue is that you are publishing, regardless of the type of event. You publish at least once when the touch starts, at least once when the touch ends and again for movement. Haven't checked, but it may also just keep firing if you hold the button.

    Move Publish into the ACTION_DOWN block

     public boolean onTouch(View v, MotionEvent event) {
                //rosbridge.Publish("/set_velocity", nav_ctrl); <--- This
                if(event.getAction() == ACTION_DOWN) {
                    nav_ctrl.linear.x = 1.2;
                    nav_ctrl.angular.z = 0;
                    rosbridge.Publish("/set_velocity", nav_ctrl); <--- Goes here
    
                    return true;
    
                } else if (event.getAction() == MotionEvent.ACTION_UP) {
                    leftbtn.performClick();
                    nav_ctrl.linear.x = 0;
                    nav_ctrl.angular.z = 0;
                }
                return false;
            }