rosjava / android_core

Android libraries for rosjava

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[LOGS included]Services:App crashes when the mission is done

dkati opened this issue · comments

Good evening people.
Messing with ros services and android apps, i managed to send a custom service request, to my custom-made service.

i am sending a request from my mobile device and i expect a response but it never comes.

The story:
My device has got that code:
Just a button event which triggers a thread run

        final Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                DoStuff();
                Thread.currentThread().interrupt();
            }
        });

        aButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                t.start();
                //t.interrupt();
            }

the DoStuff() :


        Log.e("Not an error:", "Starting the service thread...");
        final ServiceClient<SendGoalArrayRequest, rosjava_test_msgs.SendGoalArrayResponse> serviceClient_;
        try {
            serviceClient_ = ControlApp.controller.connectedNode.newServiceClient("SendGoalArray", rosjava_test_msgs.SendGoalArray._TYPE);

        } catch (ServiceNotFoundException e) {
            throw new RosRuntimeException(e);
        }

        //request_ = serviceClient_.newMessage();
        final SendGoalArrayRequest request_ = ControlApp.controller.connectedNode.getServiceRequestMessageFactory().newFromType(SendGoalArray._TYPE);

        request_.setProductName(selection);


        try {
            serviceClient_.call(request_, new ServiceResponseListener<SendGoalArrayResponse>() {
                @Override
                public void onSuccess(SendGoalArrayResponse response) {
                    Log.e("Not an error:", "Deliverdsdsdsed 1 parcel of " + selection);

                    Log.e("Thread", "Delivery dosdsdsne.Shutting down the service thread...");

                    //serviceClient_.shutdown();
                    Thread.currentThread().interrupt();
                    //response.getSize();
                }

                @Override
                public void onFailure(RemoteException e) {
                    Log.e("REAL ERROR", "REAL ERROR DAMN");
                    throw new RosRuntimeException(e);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.e("WTF", "WTF");
        Thread.currentThread().interrupt();

The onSuccess is never executed....i never get that log.e() .although when i press the button,the robot is moving to a point and then returns.when the robot returns ,app crashes with the following log->

11-10 13:51:08.591 28296-32406/com.robot.ControlApp E/AndroidRuntime: FATAL EXCEPTION: pool-4-thread-68
Process: com.robotca.ControlApp, PID: 28296
java.lang.IndexOutOfBoundsException: Invalid combined index of 1633906547, maximum is 75
                                                                            at org.jboss.netty.buffer.SlicedChannelBuffer.<init>(SlicedChannelBuffer.java:46)
                                                                            at org.jboss.netty.buffer.HeapChannelBuffer.slice(HeapChannelBuffer.java:200)
                                                                            at org.jboss.netty.buffer.AbstractChannelBuffer.readSlice(AbstractChannelBuffer.java:323)
                                                                            at org.ros.internal.message.field.PrimitiveFieldType$14.deserialize(PrimitiveFieldType.java:584)
                                                                            at org.ros.internal.message.field.PrimitiveFieldType$14.deserialize(PrimitiveFieldType.java:555)
                                                                            at org.ros.internal.message.field.ListField.deserialize(ListField.java:71)
                                                                            at org.ros.internal.message.DefaultMessageDeserializer.deserialize(DefaultMessageDeserializer.java:45)
                                                                            at org.ros.internal.node.service.ServiceResponseHandler$1.run(ServiceResponseHandler.java:62)
                                                                            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                                            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                                            at java.lang.Thread.run(Thread.java:818)

My service:

string productName
---
int64 size
int64[4] BoxCounter
string[4] Boxes

Hi @dkati,
This sounds familiar. @ernestmc was there a problem with arrays with fixed length? Were you able to fix it? (see rosjava/rosjava_core#236).

@dkati in the meantime, if you want to try something, perhaps you can leave the size of the array undefined in your custom message and see if that works.

@jubeira i cant even compile the message with undefined array size

Hmm I've tried compiling messages with undefined length (messages, not services in my case) and I had no problem. Do you have the messages in a separate package? I'd recommend you to do that, and maybe clean your workspace before trying to rebuild it.
I will try to compile your custom message in particular; I'm a bit busy right now but I will when I have some time.

@dkati take a look around here: https://github.com/jubeira/rosjava_srv_test.

Can you try to build and use that workspace? I've built that sample service in a small test and I didn't experience any problems. I'm using arrays with undefined size.

@jubeira i did it but.. it compiles fine but how can i "trigger" it ...i see only overrides and i guess they are callbacks...how can i send a request from my device by pressing a button click ?

my server is written in c++....
also, i get md5sum errors even with clean builds

@dkati in the example I did I'm doing all the work in onStart. Have you tried executing it with the instructions in the readme?
You can do the same in your app, but splitting that in two methods:

  • onStart should only create and store the service client:
  private ServiceClient<foo_custom_msg.GetProductRequest, foo_custom_msg.GetProductResponse> serviceClient;
  private ConnectedNode connectedNode;

   // This is your node extending AbstractNodeMain
  @Override
  public void onStart(final ConnectedNode connectedNode) {
    this.connectedNode = connectedNode;
    try {
      this.serviceClient = connectedNode.newServiceClient("get_product", foo_custom_msg.GetProduct._TYPE);
    } catch (ServiceNotFoundException e) {
      throw new RosRuntimeException(e);
    }
  }
  • Then, create a method that uses that service client to trigger the call, and use that method in your onClick callback:
  // This method should be public in your node, so that you can call it anywhere in your app
  public void triggerService() {
    final foo_custom_msg.GetProductRequest request = serviceClient.newMessage(); // you stored this variable in onStart
    request.setProductName("Foo product name");
    serviceClient.call(request, new ServiceResponseListener<foo_custom_msg.GetProductResponse>() {
      @Override
      public void onSuccess(foo_custom_msg.GetProductResponse response) {
        for (long l : response.getBoxCounter()) {
          connectedNode.getLog().info("Got number " + l);
        }

        for (String s : response.getBoxes()) {
          connectedNode.getLog().info("Got box " + s);
        }
        connectedNode.getLog().info("Product size: " + response.getSize());
      }

      @Override
      public void onFailure(RemoteException e) {
        throw new RosRuntimeException(e);
      }
    });
  }
  • You can modify that method to send parameters and so on....

Does that make sense? It doesn't matter that the server is in C++, you should be able to use the client in java. You will need to make sure that you don't press click before the node actually started, and that the service server is already running when you execute the node, maybe adding some synchronized blocks, mutexes or whatever.