RosAria doesn't update after certain time? - python

I have a robot (Pioneer 3-AT) with distance sensors that I wan't to drive around autonomously.
What am I using?
Pioneer 3-AT (Robot with wheels and a bunch of sensors and stuff, see: http://www.mobilerobots.com/ResearchRobots/P3AT.aspx)
ROS (tool to let scripts interact over network by publishing and subscribing to "topics", see: http://www.ros.org/)
RosAria (this connects the ROS network and Pioneer, it takes data published to the /RosAria/cmd_vel topic and moves the robot accordingly, see: http://wiki.ros.org/ROSARIA)
This is the setup:
The sensors are connected to an Arduino Mega that is connected to the robot over serial port (/dev/ttyS0), after the Arduino gets the sensors data it sends them over the serial port to the robot, where a python scripts takes this data and uploads it to the ROS network, this upload automatically gets detected by RosAria which in turn moves the robot.
In short:
Sensors ---> Arduino ---> Robot (Python Script) --(ROS)-> RosAria
The python script also turns the sensor data into commands for the robot (left, right, ...)
This setup works ... for a certain amount of time
The robot automatically moves forward after the script is started.
If I hold something in front of the sensors it changes direction. NOTICE: This is whilst the robot is connected to my PC using Ethernet. However, after I disconnect the Ethernet cable it continues to work for a short amount of time.
This bug is strange
It stops working in a very strange way.
I found this out whilst debugging:
the robot continues to move forward but does not react to sensor input.
(both things are handled in the same script, at the same place)
the sensors output the data correctly
the script doesn't output any errors
the connection to RosAria is still running
RosAria receives the movement commands
According to what I found out, it should work perfectly (since it does so when connected to the ethernet), but weirdly enough, after a few meters it changes from avoiding obstacles very well to going full on berserk and just ramming everything out of its way.
What could be wrong?

Related

Wait for incoming video call with minimal power consumption

A bit of background on my project: I am doing a robot which can be controlled through the internet with live video feed. For that I have a raspberry pi as an on-board computer that handles the internet connection, video streaming, motor controlling etc. I've been successful with controlling it through a socket connection on python and a public VPS to relay commands (for NAT traversal).
Now I want to implement some sort of "idle state" like you would have on a mobile phone: The robot would stays idle and consume almost no power, and when I initiate a call on my computer it would wake up, stream the video etc. and when I hang up the call it would go to sleep again. Essentially, I want some version of Apple's Facetime and tweak it to my liking. The emphasis is on consuming as little energy as possible, since the robot is battery powered.
I can find almost no information on the internet for such an implementation (or maybe I just don't know the correct keyword). Can anyone point me in the correct direction?

Reading synchronised data from 2 serial USB ports concurrently in Python. Threading? Multiprocessing?

I'm building an autonomous rover controlled by a Raspberry Pi using RTK GPS navigation. I am using two separate U-Blox RTK GPS modules on the rover operating at 4Hz to get very accurate position and heading calculations and they are both connected to the Pi through USB ports. I'm using the pyserial library to read the NMAE sentences as they are output through USB. The problem I have encountered is that the serial data sent by each module is precisely synchronised and so while calling Serial.readline() for one port, the data sent to the other port is missed.
The basics of the code currently looks something like this:
`class GPS():
def __init__(self,port,baud):
self.gpsSerial = serial.Serial(port,baud)
# init some variables
return
def read(self):
NMEASentance = str(self.gpsSerial.readline())
if NMEASentance not what_i_wanted_or_blank:
return 0
# do some processing, update vars
return 1
frontGps = GPS(port1,baud)
rearGps = GPS(port2,baud)
while True:
if frontGps.read():
# grab the new data
if rearGps.read():
# grab the new data
What ends up happening is that while one serial port is being read and the data processed, the other is transmitting simultaneously and is missed. I have tried doing both reads one after the other and leaving the processing for later, but the problem persists.
How do i read both ports simultaneously? Will threading each serial read work (they will both still be running in the same process, and so won't be executed concurrently, right?)
If the solution is multiprocessing then could someone please post some skeleton code for me to follow because this problem is really doing my head in.
Thanks for any help!
Would love to get some code on this:
Set up two processes to read from the serial ports and add them to a shared queue
I have a GPS serial loop running and need to add a second serial link for a magnetometer and needed a way to keep the two streams separate
Currently, working with a Neo6M GPS and noticed that the #GPRMC message is like a heartbeat that is transmitted once a second on each UTC second tick.
The #GPRMC is the GPS standard sentence that transmits UTC time/date
(and location, speed and heading) so it makes sense that it would be transmitted at UTC second = 00.00
After reading about the problem it occurred to me that all the GPS receivers are probably doing the same. So if you have any number of them powered up, they will all be synchronized.
If my theory is correct:
Armies of GPS-enabled pi soldier robots could be made to walk in step even though they are continents apart.

Python, DroneKit, Pixhawk and ArduPilot Mission Planner: how to send text messages via the built-in telemetry to a ground station

I am working on a student project involving a drone which runs on the Pixhawk platform but has a 'companion computer' in the form of a Raspberry Pi. The Pi runs its own Python software and uses DroneKit (and therefore MAVLink?) to communicate with the Pixhawk via USB - giving it commands, transferring data and so on. Additionally, we have a 'ground station' laptop running ArduPilot Mission Planner which can view and interact with the aircraft remotely and also view it's telemetry. I noticed a 'Messages' tab which essentially acts like a remote console, showing 'logged' messages from the Pixhawk - this is what the question is referring to.
For debugging and information purposes, I would like to be able to add to this from Python on the Pi. I assumed this would be easily achievable through DroneKit but it does not seem trivial - send_mavlink and message_factory looked hopeful but I have found nobody else trying to do this specifically.
How can I easily redirect my 'console messages' from Python to the ground station? I realise there are alternative methods but going through the Pixhawk's existing telemetry system seems a much better option.
Thanks
One thing you can do is to create a bridge (proxy) between Pixhawk and GCS with your RPi, similar to this question.
Then in the middle of that you can send your own text messages with:
gcs_conn.mav.statustext_send(mavutil.mavlink.MAV_SEVERITY_INFO, "your message here")
Be careful not blocking too much the telemetry transmission, otherwise you could have intermittent connection to the drone from your GCS.

Can't send/receive command over serial to Arduino to control LED

I have been working on a little side project in which I want to control my Arduino pins via UI that was designed in Tkinter.
The UI is set to send serial command to my Arduino that will place that particular PIN high and turn on the LED for example.
The problem that I am facing is that when I check one of my pins, for instance, PIN4 and press 'SET', a routine is called which keep the PIN high for a small duration of time before putting the PIN to low again. I have notice that this happens when multiple USBs are connected to my laptop. If I remove all USB devices except Arduino and then run my sript then the program works flawlessly as expected.
My intention is to simply connect my arduino to my laptop while the scipt automatically connects the appropriate COM port.
Could someone help me understand where I am making a mistake in my script.
Thanks
Here is the link to the code: http://www.heypasteit.com/clip/28PJ

Serial Communication one to one

If this is a stupid question, please don't mind me. But I spent some time trying to find the answer but I couldn't get anything solid. Maybe this is a hardware question, but I figured I'd try here first.
Does Serial Communication only work one to one? The reason this came up is because I had an arduino board listening for communication on its serial port. I had a python script feed bytes to the port as well. However, whenever I opened up the arduino's serial monitor, the connection with the python script failed. The serial monitor also connects to the serial port for communication for its little text input field.
So what's the deal? Does serial communication only work between a single client and a single server? Is there a way to get multiple clients writing to the server? I appreciate your suggestions.
Multiple clients (e.g. Arduinos) communicating with one server (e.g. a desktop computer) is commonly done with the serial variant:
RS-485
This is a simple method widely used in industrial settings where you want to have many devices connected to one computer via one serial port. This type of arrangement is also called multi-drop, because one cable strings around a building with Tees that tap in and drop lines to each device.
The hardware for this is widely available. You can buy USB serial adapters that provide the hardware interface for a computer. Programmatically the port looks just like an RS232 port. For the Arduino you would just add a transceiver chip. A sea of serial transceivers exists, e.g.
Example computer USB adapter with 485 interface
Sample RS485 transceiver chip from Element14
All the devices hang on the same bus listening at the same time. A simple communication protocol used is just add a device address before every command. For example:
001SETLIGHT1 <- tells Arduino "001" to turn on the light
013SETLIGHT0 <- tells "013" to turn off the light
Any device hanging on the cable ignores commands that do not start with their address. When a device responds, it prepends its address.
001SETLIGHT1DONE <- response from device "001" that the command has been received and executed
The address in the response lets the receiving party know which device was talking.
Well, your question can be quite wide, so I'm going to layer my answer:
On the hardware side, the same pair of wires can work be shared with many devices. It is mostly a question of electronics (maintaining the signal in the good voltage range), and not having all devices writing to the serial port at the same time (or you'll get wreckage).
On the software side, on the host, yes you can share the same serial connection to a device with multiple processes. But that's not straight forward. I'll assume you're using an unix (macos or linux):
in unix, everything is a file, your serial connection is one too: /dev/ttyACM0 on linux, for example.
When you have a process opening that file, it will block it (using ioctl, iirc) so no other process can mess with that file too.
Then, you can input and output to that file using the process that opened it, that's all.
But hopefully, it is still possible to share the connection between processes. One of them would simply be to use the tee command, that will be able to get input from one process, and give it back output, and copy the output to another process. You can also do it from within python, by duplicating the file descriptor.
To easily output stuff that can be redirected the unix way (using pipes), you can use socat: http://www.dest-unreach.org/socat/
here's an usage example:
socat -,raw,echo=0,escape=0x0f /dev/ttyACM0,raw,echo=0,crnl
you may want to tweak it for your needs.
Edit:
I forgot about RS-485, which 'jdr5ca' was smart enough to recommend. My explanation below is restricted to RS-232, the more "garden variety" serial port. As 'jdr5ca' points out, RS-485 is a much better alternative for the described problem.
Original:
To expand on zmo's answer a bit, it is possible to share serial at the hardware level, and it has been done before, but it is rarely done in practice.
Likewise, at the software driver level, it is again theoretically possible to share, but you run into similar problems as the hardware level, i.e. how to "share" the link to prevent collisions, etc.
A "typical" setup would be two serial (hardware) devices attached to each other 1:1. Each would run a single software process that would manage sending/receiving data on the link.
If it is desired to share the serial link amongst multiple processes (on either side), the software process that manages the link would also need to manage passing the received data to each reading process (keeping track of which data each process had read) and also arbitrate which sending process gets access to the link during "writes".
If there are multiple read/write processes on each end of the link, the handshaking/coordination of all this gets deep as some sort of meta-signaling arrangement may be needed to coordinate the comms between the process on each end.
Either a real mess or a fun challenge, depending on your needs and how you view such things.

Categories

Resources