elmarti / react-joystick-component

Tiny, multitouch, component driven joysticks in react
MIT License
86 stars 27 forks source link

continuous joystick event if stick is not released. #37

Open dolikemedo opened 2 years ago

dolikemedo commented 2 years ago

Hello! Sorry if I'm being inapropriet! I'm a newbie! I would like to ask, if it is possibly to have a continuous event? If I keep the stick in a non zero position, then the events stop happening.

I'm controlling a robot, and I have to keep making little movements, to keep moving in a direction. I'm sending movement messages directly to the robot, but as I see in the console of the browser, the event counter stops if I just hold the stick whereever.

I'm also new to React, and JS .. :)

I'm doing this: handleMove(event){...translating event to robot, sending...}

I don't really know, but does it makes sense to have a boolean property like 'continuous={false}' or true and so the when I just hold the stick in a certain position, It is still an event. Or a threshold or something, that can be set to 0 IF the stick is in a non zero position. (I guess It wouldnt make much sense to have a nonstop event happening if its zero)

Thanks!! :)

(I might be just very noobish, I trying to figure out a workaround, I played with throttled, I tried figuring out the code)

elmarti commented 2 years ago

No problem at all:

I believe what you're talking about is a continuous/modulating control, i.e in electronics it would be similar to controlling a signal with a potentiometer, what we have is a more similar to an incremental encoder whereby change is communicated when it happens, which is more suited to event driven systems i.e the JS event loop.

What you'd need is a signal converter i.e

class SignalConverter {
    signalRate = 100; 
    joystickState = null; 
    constructor(rate){
        if(rate){
            this.signalRate = rate;
        }
    }
    //provided to `move` and `start` callback
    onMove(joystickUpdate){
        this.joystickState = joystickUpdate
    }
    //provided to `stop` callback
    onStop(){
        this.joystickState = null; 
    }

    streamUpdates(callback){
        setInterval(()=> {
            callback(this.joystickState)
        }, this.signalRate)
    }
}

const signalConverter = new SignalConverter(100);
signalConverter.streamUpdates((state) => {/*Logs every 100ms*/})
//React
<Joystick move={(update) => signalConverter.onMove(update)} start={(update) => signalConverter.onMove(update)} stop={signalConverter.onStop} />

That should work, i've not tested it. I need to read up on control theory to find a solution that works in the grand scheme of things, but that should at least solve your problem in the mean time. Let me know how you get on!

dolikemedo commented 2 years ago

Thank you very much @elmarti !!! :) :) I'm gonna try this now

abishek commented 2 years ago

No problem at all:

I believe what you're talking about is a continuous/modulating control, i.e in electronics it would be similar to controlling a signal with a potentiometer, what we have is a more similar to an incremental encoder whereby change is communicated when it happens, which is more suited to event driven systems i.e the JS event loop.

What you'd need is a signal converter i.e

class SignalConverter {
    signalRate = 100; 
    joystickState = null; 
    constructor(rate){
        if(rate){
            this.signalRate = rate;
        }
    }
    //provided to `move` and `start` callback
    onMove(joystickUpdate){
        this.joystickState = joystickUpdate
    }
    //provided to `stop` callback
    onStop(){
        this.joystickState = null; 
    }

    streamUpdates(callback){
        setInterval(()=> {
            callback(this.joystickState)
        }, this.signalRate)
    }
}

const signalConverter = new SignalConverter(100);
signalConverter.streamUpdates((state) => {/*Logs every 100ms*/})
//React
<Joystick move={(update) => signalConverter.onMove(update)} start={(update) => signalConverter.onMove(update)} stop={signalConverter.onStop} />

That should work, i've not tested it. I need to read up on control theory to find a solution that works in the grand scheme of things, but that should at least solve your problem in the mean time. Let me know how you get on!

Thanks! Saved me a tonne of time. I hope the snippet is MIT too :-D

elmarti commented 2 years ago

@abishek of course, enjoy!

elmarti commented 1 year ago

Working on this here: https://github.com/elmarti/react-joystick-component/tree/%2337-add-continuous-signal

Still needs

ValkyrX commented 1 year ago

is there an easy way to sort this, i cant fit your code solutio above in my application, unless i wobble the joystick about the robot stops moving, i move via this code through ros2

class Teleoperation extends Component { state = { ros: null };

constructor() {
    super();
    this.init_connection();

    this.handleMove = this.handleMove.bind(this);
    this.handleStop = this.handleStop.bind(this);
}

Then to actually move

handleMove(event) {
    console.log("handel move");
    //Create a ROS publisher on the topic cmd_vel
    var cmd_vel = new window.ROSLIB.Topic({
        ros: this.state.ros,
        name: Config.CMD_VEL_TOPIC,
        messageType: "geometry_msgs/Twist",
    });

    //Create a twist message to send to rosbridge
    var twist = new window.ROSLIB.Message({
        linear: {
            x: event.y,
            y: 0,
            z: 0,
        },
        angular: {
            x: 0,
            y: 0,
            z: -event.x,
        },
    });

    //Publish message on cmd_vel topic
    cmd_vel.publish(twist);
}
handleStop(event) {
    console.log("handel stop");
    var cmd_vel = new window.ROSLIB.Topic({
        ros: this.state.ros,
        name: Config.CMD_VEL_TOPIC,
        messageType: "geometry_msgs/Twist",
    });

    //Create a twist message to send to rosbridge
    var twist = new window.ROSLIB.Message({
        linear: {
            x: 0,
            y: 0,
            z: 0,
        },
        angular: {
            x: 0,
            y: 0,
            z: 0,
        },
    });

    //Publish message on cmd_vel topic
    cmd_vel.publish(twist);
}

render() { 
    return <div>
        <Joystick
        size={100}
        baseColor="black"
        stickColor="red"
        move={this.handleMove}
        stop={this.handleStop}
        ></Joystick>
    </div>
}

Where can i add a comamnd to stop the robot stuttering and having to keep moving the joystick ? any help would be appreciated :-)

Thanks