I am using the roomba service--
msg = Roomba.createMessage("myApp","
In the above line, I would like to utilize the "roombaMessageObject" in a way to send multiple things....for example, both a string, say, "goForward", and a float, say 10. This way, in the MRLClient, I can decode the roombaMessageObject when I receive it and call the "goForward" method and pass in the 10 to tell it to go forward 10 feet. I would like to do all this in a single message.
Is this what you
Is this what you mean?
Thanks, but....
That worked, but there seems to be a limit as to how many of these roomba.send commands I can use. It quits after 18. Is this a bug or is jython not equipped to send out more than 18 roomba commands in one program? I can't think of any other reason since this works other ways
Thanks.
There shouldn't be a limit...
There shouldn't be a limit... something else is wrong...
With the following code, everytime I hit the exec button - it sends a 100 messages to the logger. I don't have a Roomba. When I tried to load the roomba, I did get a serial error. It's dependencies need to be adjusted to include the RXTXComm gnu serial device. You can work around this by loading the Arduino package (which has the same dependencies). Other than that it's hard to guess without seeing the log - you could attach it to the post if you want me to look at it.
We are stillhaving issues
We are stillhaving issues with the number of commands that can be sent. Currently, only 18 commands are being executed, even though there are many more in the code... Hoping you might have some ideas for debugging, etc.
The concept is to Make a Simulated Roomba move in a asterisk shape. The roomba is getting commands from the Jython code. The roomba will drive down 1 arm of the askerisk, stop, then spin 180 degrees, stop, then drive back to the origin, stop, and spin in place to do the next arm of the asterisk. A link to a youtube video is on the way.
The origin is set at (24.77, 46.8) ie, (x, y) in meters. The simulated roomba is getting these measurments from the simulated GPS (which is pinpoint accurate).
Jeff is going to add to the problem description (and we'll have a video showing the problem soon).
So far we;'ve been using 14.6 and 14.8. But 14.9 looks cool, can't wait to test it out.
--Adam
Jython is below:
from org.myrobotlab.service import Logging
from org.myrobotlab.service import RemoteAdapter
from org.myrobotlab.service import Roomba
from org.myrobotlab.service import Runtime
from org.myrobotlab.framework import Message
from org.myrobotlab.framework import Service
from java.lang import Math
from time import sleep
from array import *
#setting up the services
remote01 = Runtime.createAndStart("remote01","RemoteAdapter")
log01 = Runtime.createAndStart("log01","Logging")
jython = Runtime.createAndStart("jython","Jython")
roomba = Runtime.createAndStart("roomba","Roomba")
#sleep for 7 seconds, enough for the jME to load and start running
sleep(7)
#arrays of (x,y) locations. Starting location is approx. (24.77, 46.8),
#the robot will travel from the starting location to the (x,y) pairs below.
#'f' means float format, [...] is the list of points
xLocs = array('f', [26.77, 24.77, 26.18, 24.77, 24.77, 24.77, 23.36, 24.77, 22.77, 24.77, 23.36, 24.77, 24.77, 24.77, 26.18, 24.77])
yLocs = array('f', [46.8, 46.8, 48.214, 46.8, 48.8, 46.8, 48.214, 46.8, 46.8, 46.8, 45.386, 46.8, 44.8, 46.8, 43.386, 46.8])
#empty arrays of length corresponding to the number of points.
#[None] means the values are initially empty and len(xLocs)
#means the length of the xLocs array.
#turnAng is the angle the robot will need to turn.
#ang is the current robot angle
turnAng = [None]*len(xLocs)
ang = [None]*len(xLocs)
#converting radians to degrees
CONV_TO_DEG = 180/Math.PI
#beginning of jython program. roomba.send sends a message
#to the "myApp" object of MRLClient invoking the "getInfo"
#string conditional in MRLClient's implemented "receive" method.
#"getInfo" invokes the jython function "input" defined below,
#passing the Roomba App's current latitude, longitude,
#compass direction, and odometer reading
roomba.send("myApp","receive", "getInfo")
#input function invoked by MRLClient upon receiving "getInfo"
def input():
#the process below must be repeated for each (x,y) location
for t in range(0,len(xLocs)):
if (t == 0):
# data coming into the Jython service can be accessed
#using msg_<serviceName>_<sendingMethod>.data[]
# where data[] is the parameters for the method
#(x,y) are the initial locations of the Roomba. They
#are converted from lat/lon to Cartesian coordinates
x = (msg_myApp_send.data[0] - 40.652817)/.00000892
y = (-73.96545 - msg_myApp_send.data[1])/.000011
if (t > 0):
#if (x,y) is not the inital conditions, they will be
#the previous (x,y) pair
x = xLocs[t - 1]
y = yLocs[t - 1]
#calculating distance the roomba must travel using standard distance formula.
#(xLocs, yLocs) is the future position and (x,y) is the current position
dist = Math.sqrt((xLocs[t] - x)*(xLocs[t] - x) + (yLocs[t] - y)*(yLocs[t] - y))
#calculating dx and dy based on the above coordinates. Atan2 is not
#supported by this package, so it must be implemented
dx = (xLocs[t] - x)
dy = (yLocs[t] - y)
#Atan2 function. Please consult an outside source for details if desired
if (dx == 0):
if (dy > 0):
ang[t] = 90
if (dy < 0):
ang[t] = -90
elif (dy == 0):
if (dx > 0):
ang[t] = 0
if (dx < 0):
ang[t] = 180
else:
ang[t] = Math.atan(Math.abs(yLocs[t] - y)/Math.abs(xLocs[t] - x))*CONV_TO_DEG
if ((dx < 0) & (dy > 0)):
ang[t] = 180 - ang[t]
elif ((dx < 0) & (dy < 0)):
ang[t] = (180 - ang[t])*(-1)
elif ((dx > 0) & (dy < 0)):
ang[t] = (ang[t])*(-1)
#end of Atan2 function
#initially, the turn angle is equal to the future angle (ang) minus the current
#angle (msg_myApp_send.data[2])
if (t == 0):
turnAng[t] = ang[t] - msg_myApp_send.data[2]
#else, the turn angle is equal to the future angle (ang[t]) minues the current
#angle (ang[t - 1])
if (t != 0):
turnAng[t] = ang[t] - ang[t - 1]
#keeping angles positive
if (turnAng[t] < 0):
turnAng[t] = turnAng[t] + 360
#the turn angle is calculated by measuring the counterclockwise
#angle (spinLeft). If the angle is less than 180, spinLeft is
#called. If the angle is greater than 180, spinRight is called
#to spin (360 - turnAng[t]) degrees. It is desired to spin
#whichever way will be quickest
if (turnAng[t] <= 180):
roomba.send("myApp","receive", "spinLeft", turnAng[t])
else:
roomba.send("myApp","receive", "spinRight", (360 - turnAng[t]))
#after the roomba spins, it stops, goes forward dist meters, and
#stops agin. The loop repeats after the final "stop" command
roomba.send("myApp","receive", "stop", 0)
roomba.send("myApp","receive", "goForward", dist)
roomba.send("myApp","receive", "stop", 0)
continued.....
Hi Greg,
I can tell you where the bug isn't:
All of these programs by themselves are fine. It seems to be the MRLClientTest/Receiver interface communicating with the roomba file. It seems as though the Receiver interface is only communicating with the roomba file up to 18 times and then it shuts down.
The jython will send unlimited roomba.send commands and MRLClientTest will send unlimited commands back to jython. So I think it is communication between MRLClientTest and roomba. My biggest fear is that the bug is deep within the confidential jME3 code and I won't be able to access it.
video
the youtube video is here but it's awful quality.
http://www.youtube.com/watch?v=2aHcLKx1WSw&feature=plcp
When the robot comes back to the center and turns to 90 degrees it should travel straight, but it stops. This is right at command 19.
better video
here is a beter video
http://www.youtube.com/watch?v=_Np4oqVo54M
Nice video.. the Audio
Nice video.. the Audio helped..
I'd drop the Roomba service just to take it out of the equation - you aren't attempting to control a real Roomba (at the moment.. i think) ... change roomba.send to jython.send(...)
take the atan2 out for the Java one too..
it should help to simplify..
Big Picture Sometimes I
Also it might help to send the messages to the "log01" too. If you can preform a test from the simulator which just sends a stream of canned messages and if more than 18 are processed, you've then isolated the issue to the Simulator or MRLClient vs all the other parts..
I attempted changing
I attempted changing everything to Jython.send yesterday and had no changes. It still stopped at the exact same place. Also, for verification, we are starting work with the real roomba so we can run them both simultaneously using the same jython code. (Starting on interfacing the roomba tomorrow)
We are attempting to use TCP, but are having issues. We've got the following in the MRLClient:
And we have the following in the Jython.
Is tha right? When we run this, the Jython creates the services, but nothing happens when we load the simulator. The first thing that is supposed to happen is that the simulator sends the starting position of the robot, then the jython sends the first command.
We aempted to send just a log message from the MRLClient to the jython, but that didn't print in the log either.
Overall, the flow you drew up is close. Basically, the simulator gets the normal control mesage (such as goForward(10) to go 10 meters). The sensors are checked inside the simulator itself, Jython does not get that sensor information directly. The same with turning a number of degrees. The Jython issues the spinLeft(45) command to spin the robot 45 degrees. The simulator then spins left, all teh while checking the current compass value until the appropriate value (45 degrees in this example) has been met. This is to simulate how the Roomba does it. In the real roomba, wheel encoders are used to determine the distance travelled and number of degrees turned. SEAR cannot currently simulate wheel encoders, so we are using the GPS as a cartesion positioning system and the compass for the number of degrees.
--Jeff and Adam
Don't set the TCPPort ... let
Don't set the TCPPort ... let it listen on the default ... The RemoteAdapter listens on TCP 6767 and UDP 6767 simultaneously without interfering with one another..
Also, the setPort command is a bit useless after the service is created..
You would need to create the service first, set the port .. and then start the service to change the port..
I've written a bug for 14.9 to get that fixed... The code would be like this..
remote01 = Runtime.create("remote01","RemoteAdapter")
remote01.setPort(6868)
remote01.startService()
.. but .. don't do it .. leave it
Using the TCP in the
Using the TCP in the MRLClient alone does not work. In fact, when we use the following code, witht he original Jython we posted above, nothing happens at all.
Also, sometimes using the new version 14.8 doesn't seem to work every time I click the execute button. I've since switched back to useing the MRLCLient14.7.jar and MRL 14.6.
So here is the graphical
So here is the graphical layout of what Jeff's code has been doing:
The reason the sensor data isn't being sent to the Jython is that we are trying to smulate the real hardware, and the real roomba doesn't send its odometer data to the jython when it has bee sent a "goForward(distance)" command.
It seems that the commands *might* be sending all at once (or rather in rapid succession like you said), and therefore might be getting queued all weird on the Client side. All of the commands are sent inside the Jython's input method. Basically, the Jython sends one message "roomba.send("myApp","receive", "getInfo")" and when the simulator repies, the jython catches the reply in the input method. This synchs up the starting of the Simulator and the Jython code. From this point, the rest of the commands are sent from within the input method. The waypoints the robot will go to are already calculated and are inside the Jython code, so all of the messages are likely sending very quickly.
Since we can't seem to get the TCP working, and for some reason, Jeff's having issues with getting MRL 14.8 to work sometimes, We're switching back to using the 14.7 MRLClient,jar and MRL14.6. I've instructed him to attempt a call and response for each command between the Jython and the MRLClient. (I'm not sure if he will do it or not, he's trying to think of other ways to debug too).
In the call and response set-up, the waypoints would be treated as different states of a state machine. Each state will send the command required for that waypoint, then await a response from the client before sending the next command. That would mean completely refactoring his code, which is why I don't know if he will do it or not, but I honestly cannnot think of another way of doing it. It would look kind of like this:
How does the real roomba work? How do you know that a command has been finished before the next one executes?
Also, on a side note, we have a Roomba 500 series which doesn't seem to communicate with the MRL roomba serivice (wven when I create the service manually) Any tips?
--Adam
Your right about the TCP,
Your right about the TCP, there are some issue regarding maintaining and/or recreating a connection. UDP being connectionless does not have to deal with those issues. I'll look into it.
I started working with 14.8 to attempt to model your system, but I think the most expedient way to resolve issues would be for me to work in 14.9. I'll begin to try to model your system with the Jython you've supplied so far.
In regards to debugging, the ./myrobotlab/myrobotlab.log is the target for all log4j - details can be adjusted through the gui or command line. In 14.9 the log4j info is redirected to a Java console in the Jython view. Feel free to attach a log if you have questions or want me to look at something specific.
A quick suggestion after
A quick suggestion after looking at the script it appears the initial sequence could be split up.
You have the option to create another Jython Service which can run a different script.
First Jython service starts initializes everything and puts it in a listening state
Second Jython Service is the "controller" / state machine
BTW - what Operating Systems
BTW - what Operating Systems are involved ?
OS
Currently we are only using Windows 7. That's where KegFloater's work is being done. I haven't even attempted in mac or linux because I remember having serial port issues in mac.
As for the other code, KegFloater's refactoring the code now to be a FSM using switch/case that sends a command and waits for a "done" response before sending the next command. That should help us figure out at which point commands are being dropped.
I believe I have replicated
I believe I have replicated the issue :
if UDP messages are sent in a tight loop then my Windows box will drop them..
I did the following loop in Java driving the MRL client - with a call back from MRL Jython running
Do you have control over the messages coming out of SEAR to put in a small delay ? In the interim I look into what the issues are with TCP.
Running TCP works currently
Running TCP works currently (14.9) when going from MRLClient ---to----> MRL
I can send messages and they are received and processed, however, MRL --- replying ---> MRLClient is sending the messages UDP which is "default" behavior...
Initially I made default MRL communication TCP, then switched to UDP when I did alot more video processing. I think it makes sense really to "default" it to TCP then have some intelligent switching to switch based on datatype.
Hmm default TCP would be ok, but it really should be "talk back on whatever protocol was initially used from the contacting service".. which means adding a key .. yattah yattah
WooHoo, more stuff !
Hello Kegfloater, I'm in the
Hello Kegfloater,
I'm in the middel of refactoring all of the networking in MRL. It shouldn't take long. Did you experiment with slowing the messages down from the simulator?
Yes. I have re-written the
Yes. I have re-written the jython code as if it were a state machine. I send out only 4 commands at a time and I do not send out more until they finish executing. It appears to be working!
That's great... I'm glad you
That's great... I'm glad you figured out a work-around..
I'll still fix this bug in MRL, you "should" have the ability to choose between TCP & UDP and get the expected results.
Additionally,
I heard you were having issues with the actual Roomba & control. This doesn't suprise me too much. When the Arduio IDE was embedded I had begun refactoring Serial Devices such that other JVMs could utilize them (ie Androids Davlik Bluetooth Serial Device) .. so I probably broke all services which use serial devices, except Arduino.
I'll fix it up, but I'd like to finish the network stuff first, unless your jones'n fer it now...
You don't need to worry about
You don't need to worry about the TCP/UDP stuff. I've got everything working PERFECTLY. I found a very elegant and trivially simple solution to the 18-commands problem. If it is your desire to fix the TCP/UDP bug in MRL for your own reasons, go ahead and do so. But, don't feel like you need to do it on our behalf.
Thanks for your help.
Real Roomba
We are trying to interface with a real roomba now with no success. We have both 400 and 500-series robots. We've attempted to start from scratch manually creating a roomba service, then trying the "test" and "Control with Keyboard" buttons with no success. We can select the port correctly, but again, nothing happens afterward. Any tips on this?
Right, I fixed that. I
Right,
I fixed that. I believe I mentioned it was likely broken due to work on integration of Android bluetooth serial devices. I think its fixed in 14.9 and I'll do a release shortly.
My tests regarding roomba are limited to connecting to a Arduino, since I do not currently have a working Roomba. I saw where it was broken, fixed it and tested to see that serial commands were going out over the USB port to the Arduino, but beyond that I can not test.
I want to test it againto make sure Arduino & Roomba successfully write & read from the serial device. After that, I update the release notes and send 14.9 up. I suspect this will take about an hour.
If in your testing you find that it does not work, please send me a log file.
Uploaded now
Uploaded now - http://code.google.com/p/myrobotlab/downloads/list
Grrr...... Didn't get the
Grrr......
Didn't get the Jython.jar in the first 14.9 upload ... is there now.
Hmm, obviously I need more unit & integration tests :P
I started the roomba service
I started the roomba service through the GUI, selected the correct com port and clicked "Test" and nothing happened. I clicked "click here for keyboard control" and nothing happened when I pressed any of the keys. The roombas (tried with both 400 and 500 series) do nothing, in fact, the serial cable never shoes anything download from the computer to the roomba any time I try to send commands. Am I missing a step somewhere?
Nothing I can think of - I
Nothing I can think of - I hooked up the arrows buttons to (goForward, leftTurn, rightTurn, & stop)
Is your recieving com port on the Roomba the default - 57600 8 data 1 stop no parity ?
Can you attach or send me myrobotlab.og, it would help me considerably....
You have a light on the cable which shows activity?
On the 400 series, baud and
On the 400 series (Looks like this)
baud and parity are 8N1. There is no communication other than when the Roomba first starts up:
On the 500 series, the battery is bad, so I have to keep it plugged in. When doing so, I get the "do-charging-checking-fets" message and "bat:" messages.
The log file below is a bit large, but it is the result of connecting the 400 series roomba, opening MRL, starting a roomba service, selecting the correct com port, clicking "test", then clicking "Click here for keyboard controls" then pressing the arrow keys. The robot doesn't move, but I can see that the TX line from the computer is sending the message down the cable. We can delete it for future use in this forum since it is so large:
Thanks for the log file, that
Thanks for the log file, that is helpful.. a couple additional questions..
It looks like we are getting closer if you can see data on the TX line... now it just a matter of talking at the correct speed and sending the right data ..