Ask Your Question
0

access to mouseXY in ROS on raspberry-pi-2 w/ Ubuntu14.04

asked 2016-11-28 00:25:48 -0600

balewski gravatar image

updated 2016-11-28 04:58:59 -0600

gvdhoorn gravatar image

Hi,

I'm learning how to use ROS on Raspberry-pi2. I was able to follow your tutorial and run talker/listener. I also made simple nodes which would blink LED or move servo in response to a message sent to a dedicated topic.

But I am stuck on my node which is meant to broadcast mouseXY coordinates.

1) I started with the example (attached at the bottom), which compiles and runs as non-sudo after I changed sudo chmod a+r /dev/input/event3

So I can read mouse XY as non-sudo on R-pi using my compiled C++ stand alone code.

time1480312402.421372   x 484   y 662
time1480312409.158280   x 483   y 662
time1480312409.174276   x 484   y 662

2) I have modified your talker.cpp to access X,Y mouse data the same way, for now just want to print the values on the screen. The code compiles and executes as ROS node, but never passes this line:

balewski@rpi2blue:~/catkin_rpi$ rosrun basic_jan streamMouseXY
[ INFO] [1480313171.898452068]: started streaming mouse XY to topic mouseXY3

now will print mouse XY to stdout - stuck

 printf("now will print mouse XY to stdout - stuck\n");
 while(read(fd, &ie, sizeof(struct input_event))) {
    if (ie.type == 2) { ....

The value of ie.type is stuck on some large integer, like: ie.type=11672

With my limited understanding how ROS works I am not able to figure out why the same sequence of C++ code embedded in to a ROS node is not working.

My full ROS code in bitbucket, public repo.

It can be compiled on Ubuntu14.04 as:

cd  ~/catkin_rpi
source ./devel/setup.bash
catkin_make
source ./devel/setup.bash

The code in question is : ~/catkin_rpi/src/basic_jan/src/streamMouseXY.cpp

It executes as follows (assuming mouse is seen as event3)

sudo chmod a+r /dev/input/event3
rosrun basic_jan streamMouseXY 3

Can you perhaps advice me how to proceed?

Thanks

Jan

Below is C++ code working on R-Pi2.

Jans-MBP-3:optMouse balewski$ cat  readMouse1.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <linux/input.h>
#include <fcntl.h>
#include <X11/Xlib.h>

/* 
Tested on R-pi2 w/ Ubuntu14.04

To compile:
  gcc readMouse1.cpp -lX11

To list all  connected devices:
 cat /proc/bus/input/devices |grep mouse

To enable none-sudo user to access mouse data
 sudo chmod a+r /dev/input/event3

Results with
crw-r--r-- 1 root root 13, 67 Nov 27 19:03 /dev/input/event3

*/

#define MOUSEFILE "/dev/input/event3"

int main(){
  int fd;
  struct input_event ie;
  Display *dpy;
  Window root, child;
  int rootX, rootY, winX, winY;
  unsigned int mask;

  dpy = XOpenDisplay(NULL);
  XQueryPointer(dpy,DefaultRootWindow(dpy),&root,&child,
              &rootX,&rootY,&winX,&winY,&mask); 

  if((fd = open(MOUSEFILE, O_RDONLY)) == -1) {
    perror("opening device");
    exit(EXIT_FAILURE);
  }

  while(read(fd, &ie, sizeof(struct input_event))) {
    if (ie.type == 2) {
      if (ie.code == 0) { rootX += ie.value; }
      else if (ie.code == 1) { rootY += ie.value; }
      printf("time%ld.%06ld\tx %d\ty %d\n", 
         ie.time.tv_sec, ie.time.tv_usec, rootX, rootY);
    } else if (ie ...
(more)
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2016-12-07 00:35:10 -0600

balewski gravatar image

updated 2016-12-07 00:53:55 -0600

Hi,

I found a working solution - must have been error on my end.

Attached code will broadcast the XY mouse position and speed as JSON on topic 'chatter':

{"dt": 0.25, "dx": 2, "dy": 10, "mouse": 1, "xpos": 391, "ypos": -103}

When invoking the mouseMsg.py you can select which mouse # you want to read and what is the readout frequency.

Thanks

Jan

#!/usr/bin/env python
''' 
Software License Agreement (BSD License)
Author: Jan Balewski, December 2016

Talker broadcasts mouse relative position, 
published as JSON using std_msgs/Strings message
to the 'chatter' topic
'''

import sys,os
import json
import subprocess
import rospy
from std_msgs.msg import String

#----------------------
def onFailedStart(myNo):
    print 
    print('Mouse %d data access failed. Few tips:'%myNo)
    task = subprocess.Popen("cat /proc/bus/input/devices", shell=True, stdout=subprocess.PIPE)
    data = task.stdout.read()
    assert task.wait() == 0
    m=0
    for line in data.decode('utf-8').split("\n"):
        #    print line
        if "H: Handlers=mouse" in line:
            #print line
            lL=line.split()
            #print lL[1]
            msNo=int(lL[1][-1])
            devName='/dev/input/mouse%d'%msNo
            stats = os.stat(devName)

            print 'see: ',devName, ' access=',oct(stats.st_mode& 0777)

    print ' try:   sudo chmod a+r ',devName 
    print 
    print 'use:  mouseMsg.py [mouseNo] [rate/Hz]'

#----------------------
def mouseState(myNo):
    global fm,readRate,xpos,ypos
    # read from the file. ord() converts char to integer
    state = ord(fm.read(1))
    dx = ord(fm.read(1))
    dy = ord(fm.read(1))

    #convert bits in 'state' in to an array 'mouse_state'
    mouse_state = [(state & (1 << i)) >> i for i in xrange(8)]

    # if mouse moving to the left. dx must be a negative value
    if mouse_state[4] == 1:
        dx = dx - 256    # convert 2's complement negative value

    # if mouse moving down
    if mouse_state[5] == 1:
        dy = dy - 256

    if (mouse_state[6] == 1) or (mouse_state[7]==1):
        print "Overflow!"

    # update the position
    xpos += dx
    ypos += dy

    out={"mouse":myNo,'dx':dx,'dy':dy,'xpos':xpos,'ypos':ypos}

    return out

#----------------------
def mouseMsg(myNo):
    global fm,readRate
    myName='devMouse%d'%myNo
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node(myName, anonymous=True)
    rateHn = rospy.Rate(readRate) 
    dt=1/float(readRate)

    rospy.loginfo(myName+' found, move it , ctrl\ to abort.')
    k=0
    while not rospy.is_shutdown():
        k+=1
        outD=mouseState(myNo)
        outD['dt']=dt
        outStr=json.dumps(outD,sort_keys=True)
        if k%50==0:
            rospy.loginfo(outStr+' k=%d'%k)
        pub.publish(outStr)
        rateHn.sleep()

if __name__ == '__main__':
    global fm,readRate,xpos,ypos
    myNo=0
    readRate=10  # Hz
    (xpos,ypos)=(0,0)

    if len(sys.argv)>=2:
        myNo=int(sys.argv[1])
    if len(sys.argv)==3:
        readRate=int(sys.argv[2])
        assert(readRate>0)
        assert(readRate<20)

    devName='/dev/input/mouse%d'%myNo


    try:
        fm = open(devName, 'rb')
    except:
        onFailedStart(myNo)
        exit(1)

    try:
        mouseMsg(myNo)
    except rospy.ROSInterruptException:
        pass
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2016-11-28 00:25:48 -0600

Seen: 94 times

Last updated: Dec 07 '16