Sending AT command TakeOffCommand [ID=REF, param=,290718208] non-stop - ar.drone

I am working on AR.Drone 2.0 control application. I am using javadrone API and library in my project. Here is my code problem: whenever I press TakeOff button in my application, it will keep on sending takeoff commands to drone. And it ignore to issue the next AT command that I wanted to send. For example, I connect to drone, press TakeOff button (It should send AT TakeOffCommand,it works fine) but the next command (e.g.Flying Up) will not issue & send to drone. Why this happen? Any idea what cause this bug?
My Java Code:
**Connect Button in my apps**
private void jButtonConnectActionPerformed(java.awt.event.ActionEvent evt) {
try {
// Create ARDrone object,
// connect to drone and initialize it.
drone = new ARDrone();
drone.playLED(10,10,10);
drone.connect();
drone.clearEmergencySignal();
// Wait until drone is ready
drone.waitForReady(CONNECT_TIMEOUT);
System.err.println("Drone State: " + drone.getState());
// do TRIM operation
drone.trim();
} catch (UnknownHostException ex) {
Logger.getLogger(arDroneFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(arDroneFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
**Take Off Button in my apps**
private void jButtonTakeOffActionPerformed(java.awt.event.ActionEvent evt){
try
{
// Take off
System.err.println("Taking off");
drone.takeOff();
Thread.sleep(5000);
}catch (IOException ex) {
Logger.getLogger(arDroneFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(arDroneFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
**Flying Up Button in java apps:**
private void jButtonUpActionPerformed(java.awt.event.ActionEvent evt) {
try
{
// Flying Up
drone.playAnimation(1,10);
drone.move(0,0,5,0);
// Fly a little :)
Thread.sleep(5000);
} catch (UnknownHostException ex) {
Logger.getLogger(arDroneFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(arDroneFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(arDroneFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
**Output here:**
Current Drone State : CONNECTING
Taking off
6819 [AWT-EventQueue-0] DEBUG ardrone.ARDrone - State changed from CONNECTING to TAKING_OFF
6819 [Thread-6] DEBUG ardrone.CommandSender - Q[1]Sending AT command TakeOffCommand [ID=REF, param=,290718208]
Take off command!
7028 [Thread-6] DEBUG ardrone.CommandSender - Q[1]Sending AT command TakeOffCommand [ID=REF, param=,290718208]
7129 [Thread-6] DEBUG ardrone.CommandSender - Q[1]Sending AT command TakeOffCommand [ID=REF, param=,290718208]
7230 [Thread-6] DEBUG ardrone.CommandSender - Q[1]Sending AT command TakeOffCommand [ID=REF, param=,290718208] [These TakeOff AT commands will continuously send to drone]
Flying Up!
TakeOffCommand [ID=REF, param=,290718208]
Movement Command Sending!
0.0
0.0
5.0
0.0
9847 [Thread-6] DEBUG ardrone.CommandSender - Q[2]Sending AT command TakeOffCommand [ID=REF, param=,290718208] <--Why it still sending TakeOffCommand instead of MoveCommand ?
Movement Command Sent Done!
9947 [Thread-6] DEBUG ardrone.CommandSender - Q[3]Sending AT command TakeOffCommand [ID=REF, param=,290718208]
10047 [Thread-6] DEBUG ardrone.CommandSender - Q[3]Sending AT command TakeOffCommand [ID=REF, param=,290718208]
I been working on this code for few weeks and still cannot identify the problem. Please help me to solve this. Thank you very much.

This behavior is OK, and even necessary. From the AR.Drone Developer Guide:
There are two cases when the local (client side) sequence counter
should be reset:
the drone does not receive any traffic for more that 50ms; it will then set its ARDRONE_COM_WATCHDOG_MASK bit in the ardrone_state field
(2nd field) of the navdata packet. To exit this mode, the client must
send the AT Command AT*COMWDG.
The drone does not receive any traffic for more than 2000ms; it will then stop all communication with the client, and internally
set the ARDRONE_COM_LOST_MASK bit in its state variable. The client
must then reinitialize the network communication with the drone.
So the drone needs to receive something from your app every 50 milliseconds to continue operating normally. The SDKs I've seen usually send REF and/or PCMD commands. javadrone seems to be designed differently, and sends COMWDG (communications watchdog) messages to prevent timeouts).
[Edited to include a small working test program]
I don't know why your code isn't working, but here are a couple things you can try:
I see you call playLED before you actually connect to the drone;
you probably don't want to do that.
I believe the arguments to move should be floats
in the range [0.0, 1.0]--You're calling it with 5.
Here's a short program that takes off, and then begins moving backward. I've tested it on my AR.Drone 2.0 with a fresh checkout and build of javadrone and it works. There are lots of exceptions, but it works: javadrone is pretty out of date at this point, and is primarily aimed at AR.Drone 1.0. It seems to be unable to parse the drone's navdata, for one thing.
When I run this program, I see it send REF commands from the time I tell the drone to takeoff until the drone has finished taking off. It then sends COMWDG commands until the code tells the drone to move, at which point it sends a PCMD, followed by COMWDG messages again.
I recommend trying this program with your drone to see if it works. Make sure you're using a fresh checkout of javadrone.
import com.codeminders.ardrone.ARDrone;
import java.io.IOException;
import java.net.UnknownHostException;
public class DroneTest {
private static final long CONNECT_TIMEOUT = 10000L;
public static void main(String[] args) {
try {
ARDrone drone = new ARDrone();
drone.connect();
// Wait until drone is ready
drone.waitForReady(CONNECT_TIMEOUT);
drone.clearEmergencySignal();
System.err.println("Drone State: " + drone.getState());
// do TRIM operation
System.err.println("**********\nTRIM\n**********");
drone.trim();
Thread.sleep(5000);
System.err.println("**********\nTAKEOFF\n**********");
drone.takeOff();
Thread.sleep(10000);
System.err.println("**********\nMOVE\n**********");
drone.move(0.0f, 0.5f, 0.0f, 0.0f);
} catch (UnknownHostException ex) {
System.err.println(ex);
} catch (IOException ex) {
System.err.println(ex);
} catch (InterruptedException ex) {
System.err.println(ex);
}
}
}

Related

Server restart results in never ending Bad_ServiceUnsupported errors, onSubscriptionTransferFailed not called

my Milo client (sdk 0.4.1) subscribes on server events by use of UaSubscription and can receive events sucessfully. But once I restart the server, the clients only logs errors in an endless loop in the form of:
[ERROR] 2021-06-11 17:29:11.467 [milo-netty-event-loop-0]
UascClientMessageHandler -
errorMessage=ErrorMessage{error=StatusCode{name=Bad_ServiceUnsupported,
value=0x800B0000, quality=bad}, reason=null}
Unfortunately implementing the onSubscriptionTransferFailed method does not help because it is never called.
client.getSubscriptionManager().addSubscriptionListener(new UaSubscriptionManager.SubscriptionListener() {
#Override
public void onSubscriptionTransferFailed(UaSubscription subscription, StatusCode statusCode) {
try {
LOGGER.info("onSubscriptionTransferFailed");
client.getSubscriptionManager().clearSubscriptions();
client.disconnect().get();
run(client, serverAddress, biConsumer, requestedPublishingInterval);
} catch (InterruptedException | ExecutionException e) {
LOGGER.error("Failed re-subscription: {}", e.getMessage(), e);
}
}
}
Any idea how I can get the client to detect its current problem and resubscribe on server events?
Thank you in advance.
Update:
Found this commit https://github.com/eclipse/milo/commit/e854374845e6c5f46a7b033c2c62cee2ee10622a and was able to fix the problem by just increasing the Milo client sdk version to 0.6.1. Version 0.5.3 should probably also fix it but I did not test it.

Why can not I read bytes from the TcpClient in C#?

Why can not I read bytes from the TcpClient in C#?
Here is the error I am getting:
Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
Here is how I start my TcpClient:
public static async void Start()
{
TcpListener server = null;
try
{
server = new TcpListener(IPAddress.Loopback, 13000);
server.Start();
var client = await server.AcceptTcpClientAsync();
var stream = client.GetStream();
var bytes = Convert.FromBase64String("ABCD");
await stream.WriteAsync(bytes, 0, bytes.Length);
client.Close();
}
catch (Exception e)
{
throw;
}
finally
{
if(server != null)
{
server.Stop();
}
}
}
Here is how I run a request to the TcpClient:
try {
var response = (new HttpClient()).GetByteArrayAsync("http://localhost:13000").Result;
return Convert.ToBase64String(response);
} catch(Exception e) {
throw;
}
The return Convert.ToBase64String(response); line is never reached. While I see the quoted above error message inside the Exception e if I hit a breakpoint on the throw line.
Also, during debug the Start() method completes just fine. I.e. it starts, then wait for a request, gets a request, writes to the TclClient and at the end runs the server.Stop(); command.
I am expecting my code to work, because I took it and modified from the official documentation over here.
I tried to check out a few resources which would tackle my exception, but none of them did help.
E.g. I tried to use the question.
First answer tells nothing useful actually, but just plays around with words and at the end states that one can do nothing about the exception (please, correct me if I am missing a point in the answer).
And the second answer tells an impossible in my case problem. Because, I am sure there is nothing running on the 13000 port.
Your client code is using HttpClient, which sends an HTTP request and expects an HTTP response. But your server is not an HTTP server, it is just a plain TCP server, so the client is likely to fail and forcibly close the connection when it doesn't receive a properly formatted HTTP response.
The "official documentation" whose example you modified is not using HttpClient at all, it is using TcpClient instead.
If you want to use HttpClient in your client, then you should use HttpListener instead of TcpListener in your server.

Cancelling Fetch results in client being Disconnected

When cancelling IMailFolder.Fetch method with the cancellationToken, I get an exception that the client is disconnected.
I debugged MailKit and traced the issue to ImapEngine.Iterate() method where there is the following:
try {
while (current.Step ()) {
// more literal data to send...
}
if (current.Bye)
Disconnect ();
} catch {
Disconnect ();
throw;
} finally {
current = null;
}
Is it the right approach to disconnect the client on every exception type being caught?
Should this also apply to the case when we are cancelling the operation, so we can prioritize another operation, and we do not want to disconnect?
How else would you cancel a command that is in progress if not disconnecting the socket?

Android socket client slow

I am trying to make a faster socket client to send RGB colors each time, the faster call should be from 1 to 10 times per second.
I am using this code:
try {
socket = new Socket("192.168.0.9",1234);
try {
dataOutputStream = new DataOutputStream(socket.getOutputStream());
//toServer = new BufferedWriter(new PrintWriter(socket.getOutputStream(),true));
//out = new PrintWriter(new BufferedWriter(
// new OutputStreamWriter(socket.getOutputStream())), false);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (UnknownHostException e1) {
Log.e("Error", "Error");
e1.printStackTrace();
} catch (IOException e1) {
Log.e("Error", "Error");
e1.printStackTrace();
}
And each time I am changing color from the picker, I am calling this method
dataOutputStream.writeUTF(";"+red+";"+green+";"+blue+";"+brightness+";");
I have tried a script in python that does the same, 100 times in 2 seconds and I dont have any lags.
What I am getting, is that the python server is waiting for new requests but Android takes time to send them through the socket connection.
I actually tried 3 different method to instance the output write, but only with the DataOutputStream is faster enough but still have some lag.
What is the best approach to fix this issue?
Put a BufferedOutputStream between the DataOutputStream and the socket, and flush the DOS after each writeUTF(). At the peer, use a DataInputStream over a BufferedInputStream.

MongoDB and Play! Framework Inconsistent Behaviour

I have some code in a test as follows:
#Test
public void testRetrieveMongoDBFailUnkownHost()
{
//Set up test port and host on DSMongo
MyMongo mongoTest = new MyMongo();
mongoTest.setHost("failure");
mongoTest.setPort("0");
//attempt to make the connection
try
{
mongoTest.attemptMongoConnection();
assertTrue(false);
}
catch (Exception e)
{
assertEquals("Incorrect error message received: " + e.getMessage(),"Error (3013) : Unknown database host.", e.getMessage());
}
}
And the attempt MongoConnection() method runs the new Mongo(host, port) method which should fail with an unknown host exception. It isn't failing on my machine (no matter what string I put in instead of failure) but it is failing on my colleagues machine. So the test fails on my machine and passes on his (i.e. he gets the exception). Any ideas cause I am stumped!
Thanks
Paul
EDIT: The code in the attempt Connection Method is
*/
public static void attemptMongoConnection() throws MYException
{
try {
singleMongo = new Mongo(getHost(), getPort());
Logger.debug("Retrieved Mongo database from " + host);
} catch (UnknownHostException e) {
Logger.error("Unknown Host Exception", e);
throw new MYException(MYMessage.MY_UNKNOWN_HOST);
} catch (MongoException e) {
Logger.error("Mongo error", e);
throw new MYException(MYMessage.DS_MONGO_ERROR);
}
}
where singleMOngo is a Mongo variable and the getHost and getPort are the ones we have set (.e. failure and 0).
I have found this was a problem with the DNS somewhere. When I ran it at home (from where I originally made the post) it failed and seems to hav been resolving the name of "failure" so when I instead entered something like "localhost_123" it works perfectly.
I have come into the office this morning and it works with "failure" again. Doing some further digging it seems therefore that my router or something at home is resolving "failure" to an address it is aware of which is not present on the network here in the office.
Thanks for all those who looked at this. Very bizarre.